求助:STM8S103F2的AD采样值偏小

hanbin   2010-5-4 10:04 楼主


STM8S103F2,用于采样电流。电流采样电阻为50毫欧,通过1K及104简单滤波后输入至芯片的AD口。采样电阻上的电压大约在10~50mV,芯片工作于5.0v,16MHz内部振荡。
调试过程中,发现,芯片采样出来的AD结果比实际值偏小1~2个AD字,请问有什么解决办法。
AD采样模块程序如下:

uint16 GetADResult(void)
{
     uint16    result = 0;
     uint8      i = 0;

     ADC_CSR = 0x00;           // 选择AD转换通道
     ADC_CR1 = 0x62;           //  设置AD转换时钟1/12,连续转换模式
     ADC_CR2 = 0x08;           // 设置数据为右对齐
     ADC_CR3 = 0x00;           // 不使用数据缓冲
     ADC_CR1 |= 0x01;          // 打开AD模块电源
     Delay(200);                     // 延时至少100uS,用于等待采样保持电容充电至稳定
     ADC_CR1 |= 0x01;          // 启动AD转换

     for(i = 0; i < 16; i++)
    {
         ADC_CSR &= 0x7F;
         while(!(ADC_CSR & 0x80));    // 等待AD转换完成
         result += ADC_DRH * 256 + ADC_DRL;
     }
     ADC_CR1 &= 0xFE;
     return result >>4;
}

转换的结果比理论值偏小,但很稳定。请问是否有改善的空间?由于我的系统电流动态范围比较大,不能增大电流采样电阻值,也不能降低芯片工作电源电压。
PCB板以前是采用Microchip以及台系的芯片,只更改了对应的芯片封装,布板上应该没什么问题。滤波电容紧靠芯片引脚
谢谢

回复评论 (33)

1)请看看数据手册上标明的误差,是否你得到的结果在此误差范围内?
2)请尝试更换系统中其它器件,比如采样电阻,借以确定不是由于其它器件的误差而导致的偏差。
3)芯片采样出来的AD结果比实际值偏小1~2个AD字,这个结论的参照值是如何得到?即所谓的"理论值"是否准确。
点赞  2010-5-4 10:27
感谢版主的回复
1、已查看过数据手册,此偏差的确是在器件的偏差范围内。(数据手册标明的误差为:1.6~3.5LSB @fADC=2MHz)
2、器件误差引起的问题可以排除,见3
3、以50mV为例,先采用万用表测量采样电阻上电压为50mV,芯片工作电源为4.99v,那么理论值应该是:50/4990*1023= 10.25,但是调试过程中,观察AD转换出来的结果为7~8之间,比理论值偏小。

如果按器件的误差来看,的确是正常的。但,由于之前所使用的其它芯片看,一般实际误差都在+/-1LSB之间(数据手册通常标称的也在3LSB)。因此,想看看是否有其它改善的可能。

附:以前用的台系芯片,标称误差也是3LSB,但转换结果偏差一般也在1LSB内。并经过大量量产验证(3kk/y)。

我想这些芯片的AD模块都是采用逐次比较的方式,应该特性差异不会太大吧。由于第一次使用ST的芯片,对芯片特性不了解,故寻求帮助。
再次感谢
点赞  2010-5-4 10:45
重新仔细测试了一下,发现是AD的零点失调引起的。
在4.99v电压供电下,当输入的模拟电压<30mV时,采样出来的AD结果均为零。而理论上应该是30*1023/4990=6
目前还不清楚是什么原因引起的,寻求帮助,谢谢
点赞  2010-5-4 15:12
                                 AD的精度有这么高吗,6mV?
点赞  2010-5-4 20:34
                                 精度肯定是有的,就是这个6mv如何读出
点赞  2010-5-4 20:58
                                 请把电路图贴出来。
点赞  2010-5-4 21:10
                                 输入经过运放了?, Rain 的阻值最大1.2K
点赞  2010-5-5 11:45


电路比较简单,如图
通过调节稳压电源的值,改变采样电阻上的电压值。并用万用表读数。
今天再测试时,更改系统分频,调节MCU时钟为2MHz,外设时钟为16MHz时,偏差值为3。
当输入电压低于18mV时,所读到的数据均为0,超过20mV以后,可读到AD结果,但均比理论值小3~4
如果MCU时钟也为16MHz,在30mV以下读到的数据均为0,超过30mV,结果比理论值小5~6
由于AD转换过程中,已设置了相应的延时,不清楚为什么更改MCU时钟会影响到AD转换结果。AD转换时钟设置为分频10或16都一样

再次感谢各位的帮忙
点赞  2010-5-5 15:08


ADC时钟的设置是多少MHz?

16MHz/12  ??
点赞  2010-5-5 15:26
                                 请把C1去掉试试看。
点赞  2010-5-5 15:30
外设时钟为16MHz,分别设置ADC时钟分频为1/8, 1/10, 1/12, 1/18均是一样的结果
数据手册给出来的ADC时钟范围是1~6MHz
点赞  2010-5-5 15:31
                                 感谢版主的回复,去掉后,有改善了一些,但是在<16mV以下,转换结果仍然为0
点赞  2010-5-5 15:39


分别更改了CPU时钟,以及ADC的时钟,测试结果如下:
ADC转换结果采用64次转换累加的方式
随着CPU时钟降低,AD转换结果变大(设置ADC时,延时采用Delay(2000)是足够的)


现在有两个疑惑:
1、为什么CPU时钟下降会影响到ADC转换结果?
2、为什么在AD输入口上,不能加那个滤波电容?
点赞  2010-5-5 16:40
ADC的基本工作原理是使用输入电压对内部电容充电,当内部电容的压降与外部电压相同时,则可以开始进行转换。

CPU时钟下降意味着ADC的时钟频率下降,只要不超出规定的范围,基本上不会对ADC转换结果有太大的影响。

在AD输入口上加那个滤波电容,将会影响对内部电容的充电,所以会影响测量结果。
点赞  2010-5-5 18:43
看了一下你的程序,下面这句有问题:
        result += ADC_DRH * 256 + ADC_DRL;

因为你选择的是“数据为右对齐”,按照要求应该先读ADC_DRL,再读ADC_DRH;但是你这样写,不知道编译器会如何生成代码,请最好改成这样:
        result = ADC_DRL;
        result |= ADC_DRH * 256;

这样可以保证读出顺序肯定是正确的。

STM8_ADC_Alignment.GIF (11.37 KB)

点赞  2010-5-5 18:47


昨天发的图表,Fadc计算有识,Fadc只与Fmaster有关,与Fcpu无关,如附件,橙色区域表示Fadc符合数据手册规定值(1~6MHz),至于ADC_DR的读出顺序,调整后结果是一样的。


1、CPU时钟变化,其实并不影响AD的时钟,但从测试的结果上看,随着CPU时钟的下降,AD转换结果变大,并接近于理论值。
2、至于AD输入引脚的电容,我认为并不会影响ADC内部电容的充电。由于外部的电容远大于ADC内部的保持电容,在ADC未开始工作前,外部电容C1已充电至稳定。在ADC工作时,外部电容可以对内部ADC的保持电容进行充电,从而降低对外部电压源的内阻要求。特别是当外部模拟电压远高于AD参考电压时,通常采用电阻直接分压的方式,如果不加外部电容C1,分压电阻阻值就不能太大,从而增加了额外的电流消耗。
如下图:
点赞  2010-5-6 10:28


数据手册上有一段关于ADC部份的描述:



个人感觉,描述中的CAIN,应该是Cadc吧
点赞  2010-5-6 10:34
在更改CPU频率时,下面的Delay()函数是否也做了相应的修改?

     ADC_CR1 |= 0x01;          // 打开AD模块电源
     Delay(200);                     // 延时至少100uS,用于等待采样保持电容充电至稳定
     ADC_CR1 |= 0x01;          // 启动AD转换
点赞  2010-5-6 10:47
测试的时候,我全部更改为Delay(2000);

void    Delay(uint16 times)
{
         while(times--);
}

此延时在数据手册里面是7uS,我在更改CPU时钟是倒没有再更改延值,统一采用Delay(2000);时间应该是足够长的,这个时间应该不会影响AD转换结果吧?
点赞  2010-5-6 11:32
12下一页
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复