泰凌微TLSR825X开发三 ADC模数转换

前言

TLSR825X集成了一个逐次逼近型(SAR)ADC模块,可以应用在电池电压、温度、单声道或立体声音频信号的采样
在这里插入图片描述

本章主要讲解下差分ADC模拟信号采样的功能,如有异议,欢迎留言指正

功能与参数
  • ADC时钟通过外部24MHz晶体时钟源通过分频因子分频后获得,公式如下
    • Fadc_clk = 24MHz/(adc_clk_div+1)
  • 如下支持ADC的10个管脚输入通道
GPIO_PinTypeDef ADC_GPIO_tab[10] = {
		GPIO_PB0,GPIO_PB1,
		GPIO_PB2,GPIO_PB3,
		GPIO_PB4,GPIO_PB5,
		GPIO_PB6,GPIO_PB7,
		GPIO_PC4,GPIO_PC5
};
  • ADC仅支持差分模式(differential mode),测量电池电压时可将负端配置到GND
  • ADC支持 Left、Right、Misc三个通道,无法同时工作,必须通过状态机切换来运行采样
    • 三个通道都包含一个设置set状态和捕获Capture状态
      在这里插入图片描述
代码实例
初始化
  • 参考例程app_adc.c,初始化adc代码如下
void app_adc_test_init(void)
{
    /******关闭adc电源********/
    adc_power_on_sar_adc(0);
    /****** 使能adc 24nhz时钟源********/
    adc_enable_clk_24m_to_sar_adc(1); 
    /******采用时钟 4MHz******/
    adc_set_sample_clk(5); //采样时钟 = 24M/(1+5)=4M   
    /******配置左右增益偏置,电池检测可以不用配置******/
    adc_set_left_gain_bias(GAIN_STAGE_BIAS_PER100);
    adc_set_right_gain_bias(GAIN_STAGE_BIAS_PER100);   
Step 3: Config adc settings  as needed /
#if (TEST_ADC_SELECT == TEST_ADC_GPIO)
    adc_gpio_ain_init();
#elif (TEST_ADC_SELECT == TEST_ADC_VBAT)
    adc_vbat_detect_init();
#endif
    /******开启adc电源********/
    adc_power_on_sar_adc(1);
}
设置参数
  • 配置使能adc通道参数与映射管脚
void adc_gpio_ain_init(void)
{
    //set misc channel en,  and adc state machine state cnt 2( "set" stage and "capture" state for misc channel)
    adc_set_chn_enable_and_max_state_cnt(ADC_MISC_CHN, 2); //使能MISC通道与状态数
    //set "capture state" length for misc channel: 240
    //set "set state" length for misc channel: 10
    //adc 状态机执行周期  = 24M/250 = 96K, T = 10.4 uS
    adc_set_state_length(240, 0, 10);  //设置 R_max_mc,R_max_c,R_max_s ,这里仅配置MISC通道的set与capture状态
    //PB4差分正端  GND为差分负端 
    gpio_set_func(GPIO_PB4, AS_GPIO);
    gpio_set_input_en(GPIO_PB4, 0);
    gpio_set_output_en(GPIO_PB4, 0);
    gpio_write(GPIO_PB4, 0);
    adc_set_ain_channel_differential_mode(ADC_MISC_CHN, B4P, GND);
    //采样分辨率14位;差分模式下最高位为符号位(bit13)
    adc_set_resolution(ADC_MISC_CHN, RES14);  //set resolution
    //参考电压1.2V
    adc_set_ref_voltage(ADC_MISC_CHN, ADC_VREF_1P2V);                   //set channel Vref
    //配置6个时钟周期为一次采样 6/4M = 1.5
    adc_set_tsample_cycle(ADC_MISC_CHN, SAMPLING_CYCLES_6);     //Number of ADC clock cycles in sampling phase
    //设置模拟输入缩放比例1/8,可支持输入0~9.6V
    adc_set_ain_pre_scaler(ADC_PRESCALER_1F8);
}
读取数据
  • 通过接口adc_sample_and_get_result读取转换结果
u32 tick_adc_sample = 0;
void app_adc_test_start(void)
{
    if(clock_time_exceed(tick_adc_sample, 200000)){//200ms读取一次
        tick_adc_sample = clock_time();
        Adc_cur_rawData =  adc_sample_and_get_result();//获取采样数据
        Adc_raw_data[Adc_raw_datIndex ++]  = Adc_cur_rawData;
        
#if 1 //debug 显示使用
        Adc_cur_vol_oct =   (Adc_cur_rawData/1000)<<12 | ((Adc_cur_rawData/100)%10)<<8 \
                                      | ((Adc_cur_rawData%100)/10)<<4  | (Adc_cur_rawData%10);
        Adc_cal_vol_oct[Adc_cal_vol_octIndex ++] = Adc_cur_vol_oct; //用作显示
#endif
    }
}
采样接口解读
  • 采样读取接口代码,内部会进行8次读取并取平均,最终返回电压值;这里强调下adc_vol_mv换算需要根据自己实际配置来做相对应的修改
  • ADC采样数据的获取使用了Dfifo mode,默认采样8byte数据,adc采样周期为10.4uS,总数据获取时长为83uS
    • 例程中仅配置了Misc,Td时间计算公式为 Td = (1r_max_s + 1max_mc)/24M = (240+10)/24 ≈ 10.4uS
      在这里插入图片描述
#define ADC_SAMPLE_NUM      8 //一次采集8个数据
/**
 * @brief This function serves to set adc sampling and get results.
 * @param[in]  none.
 * @return the result of sampling.
 */
unsigned int adc_sample_and_get_result(void)
{
    unsigned short temp;
    volatile signed int adc_data_buf[ADC_SAMPLE_NUM];  //size must 16 byte aligned(16/32/64...)
    int i,j;
    unsigned int  adc_vol_mv = 0;
    unsigned short adc_sample[ADC_SAMPLE_NUM] = {0};//数据缓存
    unsigned short  adc_result=0;
    adc_reset_adc_module();//复位adc模块
    unsigned int t0 = clock_time();
    for(i=0;i<ADC_SAMPLE_NUM;i++){      //清缓存数据
        adc_data_buf[i] = 0;
    }
    while(!clock_time_exceed(t0, 25));  //等待至少2个采样周期 wait at least 2 sample cycle(f = 96K, T = 10.4us)
    //buf缓存地址映射dfifo setting will lose in suspend/deep, so we need config it every time
    adc_config_misc_channel_buf((unsigned short *)adc_data_buf, ADC_SAMPLE_NUM<<2);  //size: ADC_SAMPLE_NUM*4
    dfifo_enable_dfifo2();//使能dfifo
 get adc sample data and sort these data 
    for(i=0;i<ADC_SAMPLE_NUM;i++){
        /*wait for new adc sample data, When the data is not zero and more than 1.5 sampling times (when the data is zero),
     The default data is already ready.*/
        while((!adc_data_buf[i])&&(!clock_time_exceed(t0,25)));//通过判断数据非0与等待1.5个采样时间
         t0 = clock_time();
        if(adc_data_buf[i] & BIT(13)){  //判断符号位  14 bit resolution, BIT(13) is sign bit, 1 means negative voltage in differential_mode
            adc_sample[i] = 0;
        }
        else{
            adc_sample[i] = ((unsigned short)adc_data_buf[i] & 0x1FFF);  //BIT(12..0) is valid adc result
        }
        //排序 insert sort
        if(i){
            if(adc_sample[i] < adc_sample[i-1]){
                temp = adc_sample[i];
                adc_sample[i] = adc_sample[i-1];
                for(j=i-1;j>=0 && adc_sample[j] > temp;j--){
                    adc_sample[j+1] = adc_sample[j];
                }
                adc_sample[j+1] = temp;
            }
        }
    }
//
    dfifo_disable_dfifo2();   //禁用dfifo  misc channel data dfifo disable
/ get average value from raw data(abandon some small and big data ), then filter with history data //
#if (ADC_SAMPLE_NUM == 4)   //use middle 2 data (index: 1,2)
    unsigned int adc_average = (adc_sample[1] + adc_sample[2])/2;
#elif(ADC_SAMPLE_NUM == 8)  //use middle 4 data (index: 2,3,4,5)
    unsigned int adc_average = (adc_sample[2] + adc_sample[3] + adc_sample[4] + adc_sample[5])/4; //均值滤波
#endif
    adc_code=adc_result = adc_average;
      adc sample data convert to voltage(mv) 
    //                          (Vref, 1/8 scaler)   (BIT<12~0> valid data)
    //           =  adc_result * Vref * 8 / 0x2000
    //           =  adc_result * Vref >>10
    adc_vol_mv  = (adc_result * adc_vref_cfg.adc_vref)>>10; //换算电压值
    return adc_vol_mv;
}

PS:adc寄存器可查看数据手册第11章11.4节

  • 7
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值