打印
[N32G03x]

N32G032的ADC,采样电池分压后的电压,为什么有比较大的误差

[复制链接]
1535|28
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
阳光的掌控者|  楼主 | 2022-11-30 17:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
使用N32G032内部的ADC,锂电池使用2个47k电阻分压,计算得到的电压误差比较大,但是分压的电阻越小,则误差也越小。实际电压是2.05V,采样后计算为2.16,这是芯片自身的特性吗?
现在主时钟配置为48MHz,ADC时钟是4M,采样周期是600,看资料这个状态外部允许的外部输入阻抗是几百k:
https://bbs.21ic.com/icview-3253266-1-1.html
有谁遇到过类似的问题吗?


以下是代码:
void Adc_Init(void)
{
        GPIO_InitType GPIO_InitStructure;
        DMA_InitType DMA_InitStructure;
        ADC_InitType ADC_InitStructure;
        ADC_InitTypeEx ADC_InitStructureEx;

        /* Enable DMA clocks */
    RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA, ENABLE);

    /* Enable GPIOC clocks */
    RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE);
    /* Enable ADC clocks */
    RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_ADC, ENABLE);
    /* enable ADC 1M clock */
    RCC_EnableHsi(ENABLE);
    RCC_ConfigAdc1mClk(RCC_ADC1MCLK_SRC_HSI, RCC_ADC1MCLK_DIV8);  //这里必须是 1M 的时钟
    /* RCC_ADCHCLK_DIV3*/
    ADC_ConfigClk(ADC_CTRL3_CKMOD_AHB, RCC_ADCHCLK_DIV12); //48/12 = 4M        // 最高 18 MHz
       
        //ADC 中有的引脚
    GPIO_InitStruct(&GPIO_InitStructure);
    /* Configure PA.01 as analog input -------------------------*/
        GPIO_InitStructure.Pin = GPIO_PIN_5;
        GPIO_InitStructure.GPIO_Mode = GPIO_MODE_ANALOG;
        GPIO_InitStructure.GPIO_Pull = GPIO_NO_PULL;
        GPIO_InitStructure.GPIO_Speed = GPIO_SPEED_LOW;
        GPIO_InitStructure.GPIO_Current = GPIO_DC_HIGH;
        GPIO_InitStructure.GPIO_Alternate = GPIO_NO_AF;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
       
        GPIO_InitStructure.Pin       = GPIO_PIN_4;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
       
       
        /* DMA channel1 configuration ----------------------------------------------*/
    DMA_DeInit(DMA_CH1);
    DMA_InitStructure.PeriphAddr     = (uint32_t)&ADC->DAT;
    DMA_InitStructure.MemAddr        = (uint32_t)&ADCConvertedValue[0];
    DMA_InitStructure.Direction      = DMA_DIR_PERIPH_SRC;
    DMA_InitStructure.BufSize        = 3;
    DMA_InitStructure.PeriphInc      = DMA_PERIPH_INC_DISABLE;
    DMA_InitStructure.DMA_MemoryInc  = DMA_MEM_INC_ENABLE;
    DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_HALFWORD;
    DMA_InitStructure.MemDataSize    = DMA_MemoryDataSize_HalfWord;
    DMA_InitStructure.CircularMode   = DMA_MODE_CIRCULAR;
    DMA_InitStructure.Priority       = DMA_PRIORITY_HIGH;
    DMA_InitStructure.Mem2Mem        = DMA_M2M_DISABLE;
    DMA_Init(DMA_CH1, &DMA_InitStructure);
    DMA_RequestRemap(DMA_REMAP_ADC, DMA, DMA_CH1, ENABLE);
   
    /* Enable DMA channel1 */
    DMA_EnableChannel(DMA_CH1, ENABLE);
   
    /* ADC configuration ------------------------------------------------------*/
    ADC_InitStructure.MultiChEn      = ENABLE;
    ADC_InitStructure.ContinueConvEn = ENABLE;
    ADC_InitStructure.ExtTrigSelect  = ADC_EXT_TRIGCONV_NONE;
    ADC_InitStructure.DatAlign       = ADC_DAT_ALIGN_R;
    ADC_InitStructure.ChsNumber      = ADC_CHANNEL_NUM;
    ADC_Init(ADC, &ADC_InitStructure);
       
        ADC_InitStructureEx.ClkMode = ADC_CTRL3_CKMOD_AHB;//
        ADC_InitStructureEx.EndcIntEn = DISABLE;//禁用注入结束中断
        ADC_InitStructureEx.JendcIntEn = DISABLE;//禁用规则结束中断
        ADC_InitStructureEx.RefSel = DISABLE;//是否内部2.4V为参考
        ADC_InitStructureEx.VrefEn = ENABLE;//使能内部参考
        ADC_InitEx(ADC,&ADC_InitStructureEx);
    /* ADC regular channel1 configuration */
        //每个通道的时长是 (600+12)/4 = 153us   @4MHz
        //每个通道的时长是 (600+12)/12 = 51us   @12MHz
        ADC_ConfigRegularChannel(ADC, ADC_CH_5_PA5, 1, ADC_SAMP_TIME_600CYCLES5);
        ADC_ConfigRegularChannel(ADC, ADC_CH_4_PA4, 2, ADC_SAMP_TIME_600CYCLES5);
        ADC_ConfigRegularChannel(ADC, ADC_CH_17, 3, ADC_SAMP_TIME_600CYCLES5); //内部参照电压, 1.16---1.26 , 标准 1.21V
       
    /* Enable ADC DMA */
    ADC_EnableDMA(ADC, ENABLE);

    /* Enable ADC */
    ADC_Enable(ADC, ENABLE);
   
    /*wait ADC is ready to use*/
    while(!ADC_GetFlagStatusNew(ADC, ADC_FLAG_RDY))//等待这个寄存器为 1
    ;
    /*wait ADC is powered on*/
    while(ADC_GetFlagStatusNew(ADC, ADC_FLAG_PD_RDY))//等待这个寄存器为 0
    ;
        /*wait ADC VREFRDY is ready*/
    while(!ADC_GetFlagStatusNew(ADC, ADC_FLAG_VREF_RDY))
    ;
    /* Start ADC Software Conversion */
    ADC_EnableSoftwareStartConv(ADC, ENABLE);       
}

使用特权

评论回复
沙发
阳光的掌控者|  楼主 | 2022-11-30 17:49 | 只看该作者
使用内部跟随器后再采样,可以降低误差达到可用状态,但我想知道这是芯片的原因还是配置的原因

使用特权

评论回复
板凳
主战坦克| | 2022-12-1 11:25 | 只看该作者
是不是单片机内部AD的输入电阻太小导致的。

使用特权

评论回复
地板
lcdi| | 2022-12-1 14:53 | 只看该作者
是阻抗的问题,AD的输入阻抗不是太大,一般需要低阻的输入,或者用运放做缓冲.

这个阻抗不是指外部信号的阻抗,而是指从外部看进去的阻抗,就是我们一般说的输入阻抗.

具体你这个情况,可以并联一个小电容到分压电阻上,比如1nf.不过这样的话,对电压的快速细微变化会不敏感.

ADC一般都是这个这个水平,所以既不是芯片的问题也不是设置的问题,是设计初未考虑好.

使用特权

评论回复
5
gxs64| | 2022-12-1 16:21 | 只看该作者
与基准和分压电阻精度有关

使用特权

评论回复
6
wangshujun| | 2022-12-1 16:57 | 只看该作者
给下面的电阻并联一个103以上的电容看看

使用特权

评论回复
7
阳光的掌控者|  楼主 | 2022-12-2 15:55 | 只看该作者
确实可以通过下面电阻增加电容来解决这个问题

在电池电压为4.15V时
没有电容,测量到电压是 4.28V
1uF电容,测量到电压是 4.15V
100nF电容,测量到电压是 4.15V
1nf电容,测量到电压是 4.21V

使用特权

评论回复
8
chenjun89| | 2022-12-2 18:39 | 只看该作者
电池电压本身也在变化

使用特权

评论回复
9
51xlf| | 2023-1-5 12:25 | 只看该作者
分压会后,肯定是有误差的。              

使用特权

评论回复
10
sheflynn| | 2023-1-5 17:31 | 只看该作者
你看看差多少,使用修正一下。              

使用特权

评论回复
11
dspmana| | 2023-1-6 19:01 | 只看该作者
说明你的电阻不是高精度电阻              

使用特权

评论回复
12
rosemoore| | 2023-1-6 22:03 | 只看该作者
误差在哪查看的              

使用特权

评论回复
13
1988020566| | 2023-1-6 22:32 | 只看该作者
这个误差是固定的吗?              

使用特权

评论回复
14
usysm| | 2023-2-4 22:11 | 只看该作者
你可以人工修正数据,比较接近原来的数值的。

使用特权

评论回复
15
uiint| | 2023-2-5 13:04 | 只看该作者
可能电阻不是精密电阻,数值不精确。

使用特权

评论回复
16
mattlincoln| | 2023-2-5 13:34 | 只看该作者
是误差较大的吗?              

使用特权

评论回复
17
10299823| | 2023-2-6 12:35 | 只看该作者
会不会ADC存在串扰的问题,对数据采集造成干扰?

使用特权

评论回复
18
maudlu| | 2023-2-6 16:18 | 只看该作者
推荐使用滤波算法,把数据精准度提高一下。

使用特权

评论回复
19
kkzz| | 2023-2-7 20:30 | 只看该作者
这个是硬件的问题吗?              

使用特权

评论回复
20
sdCAD| | 2023-2-7 21:19 | 只看该作者
可能是你选用的电阻存在问题。              

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

13

帖子

0

粉丝