打印
[STM8]

求助:STM8S103F2的AD采样值偏小

[复制链接]
12459|37
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
kyoko|  楼主 | 2010-5-4 10:04 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 kyoko 于 2010-5-4 10:21 编辑

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以及台系的芯片,只更改了对应的芯片封装,布板上应该没什么问题。滤波电容紧靠芯片引脚
谢谢
沙发
香水城| | 2010-5-4 10:27 | 只看该作者
1)请看看数据手册上标明的误差,是否你得到的结果在此误差范围内?
2)请尝试更换系统中其它器件,比如采样电阻,借以确定不是由于其它器件的误差而导致的偏差。
3)芯片采样出来的AD结果比实际值偏小1~2个AD字,这个结论的参照值是如何得到?即所谓的"理论值"是否准确。

使用特权

评论回复
板凳
kyoko|  楼主 | 2010-5-4 10:45 | 只看该作者
感谢版主的回复
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的芯片,对芯片特性不了解,故寻求帮助。
再次感谢

使用特权

评论回复
地板
kyoko|  楼主 | 2010-5-4 15:12 | 只看该作者
重新仔细测试了一下,发现是AD的零点失调引起的。
在4.99v电压供电下,当输入的模拟电压<30mV时,采样出来的AD结果均为零。而理论上应该是30*1023/4990=6
目前还不清楚是什么原因引起的,寻求帮助,谢谢

使用特权

评论回复
5
yybj| | 2010-5-4 20:34 | 只看该作者
AD的精度有这么高吗,6mV?

使用特权

评论回复
6
txcy| | 2010-5-4 20:58 | 只看该作者
精度肯定是有的,就是这个6mv如何读出

使用特权

评论回复
7
香水城| | 2010-5-4 21:10 | 只看该作者
请把电路图贴出来。

使用特权

评论回复
8
wxzhouqing| | 2010-5-5 11:45 | 只看该作者
输入经过运放了?, Rain 的阻值最大1.2K

使用特权

评论回复
9
kyoko|  楼主 | 2010-5-5 15:08 | 只看该作者
本帖最后由 kyoko 于 2010-5-5 15:10 编辑

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

再次感谢各位的帮忙

使用特权

评论回复
10
香水城| | 2010-5-5 15:26 | 只看该作者
本帖最后由 香水城 于 2010-5-5 15:29 编辑

ADC时钟的设置是多少MHz?

16MHz/12  ??

使用特权

评论回复
11
香水城| | 2010-5-5 15:30 | 只看该作者
请把C1去掉试试看。

使用特权

评论回复
12
kyoko|  楼主 | 2010-5-5 15:31 | 只看该作者
外设时钟为16MHz,分别设置ADC时钟分频为1/8, 1/10, 1/12, 1/18均是一样的结果
数据手册给出来的ADC时钟范围是1~6MHz

使用特权

评论回复
13
kyoko|  楼主 | 2010-5-5 15:39 | 只看该作者
感谢版主的回复,去掉后,有改善了一些,但是在<16mV以下,转换结果仍然为0

使用特权

评论回复
14
kyoko|  楼主 | 2010-5-5 16:40 | 只看该作者
本帖最后由 kyoko 于 2010-5-5 17:18 编辑

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


现在有两个疑惑:
1、为什么CPU时钟下降会影响到ADC转换结果?
2、为什么在AD输入口上,不能加那个滤波电容?

使用特权

评论回复
15
香水城| | 2010-5-5 18:43 | 只看该作者
ADC的基本工作原理是使用输入电压对内部电容充电,当内部电容的压降与外部电压相同时,则可以开始进行转换。

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

在AD输入口上加那个滤波电容,将会影响对内部电容的充电,所以会影响测量结果。

使用特权

评论回复
16
香水城| | 2010-5-5 18:47 | 只看该作者
看了一下你的程序,下面这句有问题:
        result += ADC_DRH * 256 + ADC_DRL;

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

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

STM8_ADC_Alignment.GIF (11.37 KB )

STM8_ADC_Alignment.GIF

使用特权

评论回复
17
kyoko|  楼主 | 2010-5-6 10:28 | 只看该作者
本帖最后由 kyoko 于 2010-5-6 10:30 编辑

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


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

使用特权

评论回复
18
kyoko|  楼主 | 2010-5-6 10:34 | 只看该作者
本帖最后由 kyoko 于 2010-5-6 10:35 编辑

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



个人感觉,描述中的CAIN,应该是Cadc吧

使用特权

评论回复
19
香水城| | 2010-5-6 10:47 | 只看该作者
在更改CPU频率时,下面的Delay()函数是否也做了相应的修改?

     ADC_CR1 |= 0x01;          // 打开AD模块电源
     Delay(200);                     // 延时至少100uS,用于等待采样保持电容充电至稳定
     ADC_CR1 |= 0x01;          // 启动AD转换

使用特权

评论回复
20
kyoko|  楼主 | 2010-5-6 11:32 | 只看该作者
测试的时候,我全部更改为Delay(2000);

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

此延时在数据手册里面是7uS,我在更改CPU时钟是倒没有再更改延值,统一采用Delay(2000);时间应该是足够长的,这个时间应该不会影响AD转换结果吧?

使用特权

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

本版积分规则

12

主题

57

帖子

0

粉丝