CH32内部参考电压的自学笔记

fa01b251533480b916ff8b782e3af078.png

前言

CH32V/F单片机能够在一定的电压范围内进行工作,以CH32V203C8T6 芯片为例,在不使用 USB 外设时,最低工作电压能够达到 2.4V。较为宽泛的工作电压,允许单片机直接使用电池供电,但由于 CH32V203C8T6 芯片没有独立的 Vref 引脚,使用 ADC 的过程中无法换算出真实的电压。为解决无法获得真实电压的问题,可以使用内置参考电压换算当前供电电压(即 ADC参考电压)。对于项目要求精确测量时,也可尝试使用该方法对 ADC 进行校准。

电源电压的换算

CH32V203C8T6 芯片内部参考电压是典型值为 1.2V,正负偏差为 0.04V 的电压范围,在 ADC 转换精度要求不高的应用场景下,可以直接使用 1.2V 换算芯片供电电压。

5a8205a22b525556eec971fa08a874a6.png

如果需要更加精确的转换结果,就应在稳定的供电条件下,先对内部参考电压进行测量并将结果保存在 Flash 中,实际的使用过程中,再根据已知的内部参考电压进行换算。

d604325440f137da2b9b78ae361467e6.png

实现上述操作,可参考以下代码:

u16 ADC_val = 0;
s32 val_mv = 0;
u16 Vref = 0;               // Flash中存储的内部参考电压实测值
s32 Vref_To_VDD = 0;        // 由Vref的实测值换算出的电源电压值 


if ( *(u32*)(FAST_FLASH_PROGRAM_START_ADDR) == 0xe339e339 ) {       // 判断Flash中是否有内部参考电压的实测值
    printf("Address:0x%08x -> %08x\r\n", FAST_FLASH_PROGRAM_START_ADDR, *(u32*)(FAST_FLASH_PROGRAM_START_ADDR));
    // 获取内部参考电压实测值,此时务必保证电源电压或参考电压(如果有)的准确
    ADC_val = Get_ADC_Average(ADC_Channel_Vrefint, 255);            // 255次取平均
    ADC_val = Get_ConversionVal(ADC_val);
    val_mv = (ADC_val * 3300 / 4096);
    printf("Vref_mv -> %d\r\n", val_mv);
    // 将测得的结果存储在Flash中
    buf[0] = val_mv;
    FLASH_Unlock_Fast();
    FLASH_ProgramPage_Fast(FAST_FLASH_PROGRAM_START_ADDR, buf);
    FLASH_Lock_Fast();
    printf("Address:0x%08x -> %08x\r\n", FAST_FLASH_PROGRAM_START_ADDR, *(u32*)(FAST_FLASH_PROGRAM_START_ADDR));
} else {
    printf("Address:0x%08x -> %08x\r\n", FAST_FLASH_PROGRAM_START_ADDR, *(u32*)(FAST_FLASH_PROGRAM_START_ADDR));
    Vref = *(u32*)(FAST_FLASH_PROGRAM_START_ADDR);
    ADC_val = Get_ADC_Average(ADC_Channel_Vrefint, 255);            // 255次取平均
    ADC_val = Get_ConversionVal(ADC_val);
    Vref_To_VDD = (4096 * Vref / ADC_val);
    printf("Vref_To_VDD_mV -> %d\r\n", Vref_To_VDD);
    }

ADC 初始化过程中的校准

ADC 初始化函数中完成了一次校准过程,经过校准环节可大幅减小因内部电容器组的变化而造成的精准度误差。校准过程中 ADC 仅获取了 Vcc 的采样值,与实际电压大小无关,因此,在浮动电压供电的场景中,不会引入额外的误差。获取校准值函数,通过写 ADC_CTLR2 寄存器的 RSTCAL 位置 1 初始化校准寄存器,等待 RSTCAL 硬件清 0完成初始化。置位 CAL 位,启动校准功能,校准结束后,硬件自动清除 CAL 位,将校准码存储到 ADC_RDATAR 中。使用多次校准结果,计算 ADC 补偿。

 
 
int16_t Get_CalibrationValue(ADC_TypeDef *ADCx)
{
    __IO uint8_t  i, j;
    uint16_t      buf[10];
    __IO uint16_t t;
#if defined (CH32V20x_D6)
    __IO uint16_t p;
#endif




    for(i = 0; i < 10; i++){
        ADC_ResetCalibration(ADCx);
        while(ADC_GetResetCalibrationStatus(ADCx));
        ADC_StartCalibration(ADCx);
        while(ADC_GetCalibrationStatus(ADCx));
        buf[i] = ADCx->RDATAR;
//        printf("CalibrationValue[%d]->%d\r\n", i, buf[i]);
    }




    for(i = 0; i < 10; i++){
        for(j = 0; j < 9; j++){
            if(buf[j] > buf[j + 1])
            {
                t = buf[j];
                buf[j] = buf[j + 1];
                buf[j + 1] = t;
            }
        }
    }




#if defined (CH32V20x_D8) || defined (CH32V20x_D8W)
    t = 0;
    for( i = 0; i < 6; i++ ) {
        t += buf[i + 2];
    }




    t = ( t / 6 ) + ( ( t % 6 ) / 3 );




    return ( int16_t )( 2048 - ( int16_t )t );
#else
    t = 0;
    p = 0;
    /* 1024 */
    for(i = 0; i < 6; i++ ){
            if(buf[i+2] > 1536) break;
            t += buf[i+2];
    }




    if(i > 0){
            t = ( t / i ) + ( (( t % i )*2) / i );
    }
    else t = 1024;




    /* 2048 */
    j = 6-i;
    if(j > 0){
        for(; i < 6; i++ ){
                p += buf[i+2];
        }




        p = ( p / j ) + ( (( p % j )*2) / j );
    }
    else p = 2048;




    return ( int16_t )(((( int16_t )( 1024 - ( int16_t )t ) + ( int16_t )( 2048 - ( int16_t )p ))/2) + ((( int16_t )( 1024 - ( int16_t )t ) + ( int16_t )( 2048 - ( int16_t )p ))%2));




#endif
}

可以在校准值转换的 for 循环中添加打印,观察每次校准值结果是否随芯片供电电压(即 ADC 参考电压)的改变而改变。

3c55e6e60d77529c22456db51cd219aa.png

==========

往期回顾:

strlen和sizeof的异同

STM32CubeMx的串口DMA收发数据

好看的PCB也是产品的优势

STM32的DMA的五大问题

单片机的各个通信协议的波特率

==========

原文链接:点击阅读原文

平台:博客园

作者:wchmcu

cb174705b31ee0338e9000eaa07176ce.png

424c0badd3dea71eb0ab22e77db3e0d0.png

278a65fd1925e064afe57dc6f0f9ed7e.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值