OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4785|回复: 1

基于华大L170和L130的ADC采样HAL库模块化程序

[复制链接]

56

主题

167

帖子

4

精华

高级会员

Rank: 4

积分
602
金钱
602
注册时间
2013-10-18
在线时间
59 小时
发表于 2022-6-29 17:57:26 | 显示全部楼层 |阅读模式
基于华大L170和L130的ADC采样HAL库模块化程序,实测可用
支持国产

#include "hal_adc.h"





extern void DelayUs(uint32_t nus);/*引用到的外部接口*/

#define HAL_ADC_SAMPLE_CLK_DIV1   (0u<<2)         /*!< PCLK */
#define HAL_ADC_SAMPLE_CLK_DIV2   (1u<<2)         /*!< 1/2 PCLK */
#define HAL_ADC_SAMPLE_CLK_DIV4   (2u<<2)         /*!< 1/4 PCLK */
#define HAL_ADC_SAMPLE_CLK_DIV8   (3u<<2)        /*!< 1/8 PCLK */

#define HAL_ADC_SAMPLE_OP_ENABLE         (1u<<11)/*!< 打开放大器BUF */
#define HAL_ADC_SAMPLE_OP_DISABLE        (0U)         /*!< 关闭放大器BUF */  

/*此内部基准不是芯片的基准通道,只是adc特有的内部基准的使能即1.5V和2.5V--华大特有,本次不使用*/
#define HAL_ADC_SAMPLE_IN_REF_ENABLE    (1u<<14)/*!< 内部参考电压使能 */
#define HAL_ADC_SAMPLE_IN_REF_DISABLE          (0U)        /*!< 内部参考电压关闭 */



       
       
       
typedef struct
{
    uint32_t        adc_conv_mode;              /*! ADC转换模式*/
    uint32_t        adc_clk_div;                /*! ADC时钟分频*/
    uint32_t                 adc_sample_cycle;                  /*! ADC采样周期选择*/
    uint32_t            adc_ref_sel;                     /*! ADC参考电压选择*/
    uint32_t        adc_op_en;                         /*! ADC输入信号放大器控制使能*/
    uint32_t        in_ref_en;                  /*! ADC内部参考电压使能*/
    uint32_t        adc_data_align;             /*! ADC转换结果对齐控制*/
       
       
}sHalAdcCfg;


/*
采用通道如果是内部的高阻通道,速率不能超过200Ksps采样率
*/
void HalAdcInit(sHalAdcTypeDef* adc_reg, sHalAdcInitTypeDef* adc_cfg)
{

        sHalAdcCfg temp_cfg;

        temp_cfg.adc_clk_div                   =        HAL_ADC_SAMPLE_CLK_DIV8;/*8分频,16M主频下是2M*/
        temp_cfg.adc_conv_mode                =        adc_cfg->adc_conv_mode;
        temp_cfg.adc_data_align                =        adc_cfg->adc_data_align;
        temp_cfg.adc_op_en                        =        HAL_ADC_SAMPLE_OP_DISABLE;/*关闭放大器BUF*/
        temp_cfg.adc_ref_sel                =        adc_cfg->adc_ref_sel;
        temp_cfg.adc_sample_cycle        =        adc_cfg->adc_sample_cycle;
        temp_cfg.in_ref_en                        =        HAL_ADC_SAMPLE_IN_REF_DISABLE;/*不使用内部基准*/
       
       
       
    adc_reg->CR0 = 0x1u;    /*< ADC 使能*/
       
    DelayUs(20);

    M0P_ADC->CR0 |= (uint32_t)temp_cfg.adc_clk_div       |\
                    (uint32_t)temp_cfg.adc_ref_sel     |\
                    (uint32_t)temp_cfg.adc_op_en        |\
                    (uint32_t)temp_cfg.adc_sample_cycle  |\
                    (uint32_t)temp_cfg.in_ref_en;

    M0P_ADC->CR1_f.MODE  = temp_cfg.adc_conv_mode;
    M0P_ADC->CR1_f.ALIGN = temp_cfg.adc_data_align;
}



/*ADC功能使能和禁能*/
void HalAdcCmd(sHalAdcTypeDef* adc_reg, eFunctionalState enable_or_disable)
{
        if(DISABLE == enable_or_disable)
        {
                M0P_ADC->CR0_f.EN = 0u;
        }
        else
        {
                M0P_ADC->CR0_f.EN = 1u;
        }
}
/*配置单次转换通道*/
void HalAdcChannelCfg(uint32_t ch)
{
        if(ch >= 26u)
        {
                M0P_ADC->CR0_f.BUF = 1U;
        }
        else
        {
                M0P_ADC->CR0_f.BUF = 0U;
        }
    M0P_ADC->CR0_f.SGLMUX = ch;
}




void HalAdcSampleStart(void)
{
    M0P_ADC->SGLSTART = 1u;
}

/*ADC 单次转换停止*/
void HalAdcSampleStop(void)
{
    M0P_ADC->SGLSTART = 0u;
}


/*0代表采样完成,*/
uint8_t HalAdcIrqStatusGet(HAL_ADC_IRQ_STATE_TYPE_DEF  irq_flag)
{
        uint8_t ret = 0u;
    if(M0P_ADC->IFR & irq_flag)
    {
        ret = 0u;
    }
    else
    {
        ret = 1u;
    }
        return ret;
}

void HalAdcIrqStatusClear(HAL_ADC_IRQ_STATE_TYPE_DEF  irq_flag)
{
       
        M0P_ADC->ICR &= ~(uint32_t)irq_flag;
}
       




void HalMcuInterVRefEnable(void)
{
        M0P_BGR->CR |= 0x1u;
    DelayUs(20);
}



void HalMcuInterVRefDisable(void)
{
        M0P_BGR->CR &= 0x2u;
}       




/*获取采样值*/
uint32_t HalAdcSampleDataGet(void)
{
    return M0P_ADC->RESULT;
}





/*单次采样模式值获取*/
static uint16_t HalSampleAdcValueGet(void )
{
        uint16_t ans;
        uint32_t count=0;
       
        HalMcuInterVRefEnable();/*打开BGR*/
       
       
        HalAdcSampleStart();/*采样启动*/
       
        do
        {
                if(HalAdcIrqStatusGet(HAL_ADC_IRQ_SGL) == 0u)
                {
                        break;
                }
                count++;
        }while(count<6000u);
       
        HalAdcIrqStatusClear(HAL_ADC_IRQ_SGL);/*成功失败都清除*/
       
        ans=(uint16_t)HalAdcSampleDataGet();/*数值获取*/
       
        HalAdcSampleStop();/*停止采样*/
        HalMcuInterVRefDisable();/*关闭BGR*/
        return ans;
}

/*多次采样接口*/
uint16_t HalSampleAdcAverageGet(HAL_ADC_CH_TYPE_DEF ch,uint8_t times)
{
        uint8_t i;
        uint16_t ans;
        uint32_t temp=0;
       
        HalAdcChannelCfg(ch);
       
        for(i=0;i<times;i++)
        {
                ans=HalSampleAdcValueGet();
                temp+=(uint32_t )ans;
        }
        temp/=(uint32_t )times;
        ans=(uint16_t )temp;
        return ans;
}















#ifndef HAL_ADC_H
#define HAL_ADC_H

#include "hc32l17x.h"
#include "type.h"


/* C binding of definitions if building with C++ compiler */
#ifdef __cplusplus
extern "C"
{
#endif





#define   HAL_ADC_REG_BASE_ADD M0P_ADC

/*采样模式*/
#define HAL_ADC_SAMPLE_MODE_SIGNAL         (0U)        /*!< 单输入通道单次转换模式 */
#define HAL_ADC_SAMPLE_MODE_SCAN          (1U)         /*!< 多输入通道顺序/插队扫描转换模式*/

/*数据对其格式*/
#define HAL_ADC_SAMPLE_DATA_ALIGN_RIGHT (0U)
#define HAL_ADC_SAMPLE_DATA_ALIGN_LEFT (1U)

/*ADC基准源选择*/
#define        HAL_ADC_SAMPLE_IN_REF_1V5        (0u<<9)/*!<内部参考电压1.5V(SPS<=200kHz)*/
#define        HAL_ADC_SAMPLE_IN_REF_2V5        (1u<<9)/*!<内部参考电压2.5V(avdd>3V,SPS<=200kHz)*/
#define        HAL_ADC_SAMPLE_EXTERN                (2u<<9)/*!<外部输入(max avdd)   PB01*/
#define        HAL_ADC_SAMPLE_AVDD                        (3u<<9)/*!<AVDD*/


/*采样周期*/
#define HAL_ADC_SAMPLE_4CYCLE                (0u<<12)        /*!<4个采样时钟*/
#define HAL_ADC_SAMPLE_6CYCLE                (1u<<12)        /*!<4个采样时钟*/
#define HAL_ADC_SAMPLE_8CYCLE                (2u<<12)        /*!<4个采样时钟*/
#define HAL_ADC_SAMPLE_12CYCLE                (3u<<12)        /*!<4个采样时钟*/


       
       
/*ADC可选通道*/
#define HAL_ADC_EXINPUT_CH0         0U        /*!<使用PA00*/
#define HAL_ADC_EXINPUT_CH1                1U
#define HAL_ADC_EXINPUT_CH2                2U
#define HAL_ADC_EXINPUT_CH3                3U
#define HAL_ADC_EXINPUT_CH4                4U
#define HAL_ADC_EXINPUT_CH5                5U
#define HAL_ADC_EXINPUT_CH6                6U
#define HAL_ADC_EXINPUT_CH7                7U         /*!<使用PA07*/
#define HAL_ADC_EXINPUT_CH8                8U         /*!<使用PB00*/
#define HAL_ADC_EXINPUT_CH9                9U        /*!<使用PB01*/
#define HAL_ADC_EXINPUT_CH10        10U        /*!<使用PC00*/
#define HAL_ADC_EXINPUT_CH11        11U
#define HAL_ADC_EXINPUT_CH12        12U
#define HAL_ADC_EXINPUT_CH13        13U
#define HAL_ADC_EXINPUT_CH14        14U
#define HAL_ADC_EXINPUT_CH15        15U /*!<使用PC05*/
#define HAL_ADC_EXINPUT_CH16        16U /*!<使用PB02*/
#define HAL_ADC_EXINPUT_CH17        17U        /*!<使用PB10*/
#define HAL_ADC_EXINPUT_CH18        18U
#define HAL_ADC_EXINPUT_CH19        19U
#define HAL_ADC_EXINPUT_CH20        20U
#define HAL_ADC_EXINPUT_CH21        21U
#define HAL_ADC_EXINPUT_CH22        22U /*!<使用PB15*/
#define HAL_ADC_EXINPUT_CH23        23U /*!<使用PE15*/
#define HAL_ADC_EXINPUT_CH24        24U        /*!<使用PE14*/
#define HAL_ADC_EXINPUT_CH25        25U /*!<使用PE13*/

#define HAL_ADC_DAC_CH                                26U /*!<使用DAC输出(必须使用输入增益)*/  
#define HAL_ADC_AVDD_DIV3_INPUT_CH        27U /*!<使用1/3 AVCC(必须使用输入增益)*/
#define HAL_ADC_TS_CH                                28U        /*!<使用内置温度传感器BGR_TS(必须使用输入增益)*/
#define HAL_ADC_VREF_DIV2_CH                29U        /*!<使用内部基准1.2V(必须使用输入增益)*/


/*转换完成状态标志*/
#define HAL_ADC_IRQ_JQR        (1u<<5)        /*!<ADC插队扫描转换完成*/
#define HAL_ADC_IRQ_SQR        (1u<<4)        /*!<ADC顺序扫描转换完成*/
#define HAL_ADC_IRQ_REG        (1u<<3) /*!<ADC转换结果比较区间内*/
#define HAL_ADC_IRQ_HT        (1u<<2) /*!<ADC转换结果高于HT*/
#define HAL_ADC_IRQ_LT        (1u<<1) /*!<ADC转换结果低于LT*/
#define HAL_ADC_IRQ_SGL        (1u<<0) /*!<ADC单次转换完成*/


#define   HAL_ADC_IRQ_STATE_TYPE_DEF          uint32_t
#define   HAL_ADC_CH_TYPE_DEF                        uint32_t





#define   sHalAdcTypeDef  M0P_ADC_TypeDef


typedef struct
{
    uint32_t                   adc_conv_mode;                 /*! ADC采样模式*/
        uint32_t                        adc_sample_cycle;                /*采样周期设置*/
        uint32_t                        adc_ref_sel;                        /*采样周期选择*/
    uint32_t                  adc_data_align;                /*! ADC转换结果对齐控制*/
       
} sHalAdcInitTypeDef;





/*配置*/
extern void HalAdcInit(sHalAdcTypeDef* adc_reg, sHalAdcInitTypeDef* adc_cfg);
extern void HalAdcCmd(sHalAdcTypeDef* adc_reg, eFunctionalState enable_or_disable);

/*读取数据*/
/*多次采样接口*/
extern uint16_t HalSampleAdcAverageGet(HAL_ADC_CH_TYPE_DEF ch,uint8_t times);
/*用于休眠下的功耗管理关闭内部基准会降低功耗,ADC采样必须打开内部进准电压*/
extern void HalMcuInterVRefEnable(void);
extern void HalMcuInterVRefDisable(void);       
       
#endif



















正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

13

主题

644

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1976
金钱
1976
注册时间
2021-4-16
在线时间
505 小时
发表于 2022-6-30 09:53:33 | 显示全部楼层
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-26 19:46

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表