打印
[STM8]

STM8L152 AD采集交流信号精度的问题?

[复制链接]
6826|18
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
viack|  楼主 | 2011-3-19 14:45 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 viack 于 2011-3-19 15:40 编辑

我使用STM8L系列中的STM8L152C6T6 单片机进行ADC转换,其检测的信号为交流电压信号,我们使用了信号发生器进行模拟输入,输入信号经过下图1的信号调理电路和低通滤波电路进行调理使输出信号能够满足STM8L152C6T6 ADC输入的条件。图2为输入信号波形与经过调理后的波形。
橙色为原始输入交流50Hz信号500mVpp,红色为经过调理后的信号,既输入至ADC采样的信号。


图2

我们在一个周波里面定时1.66mS采集12个点电压值。如下图所示:



我们采集12点数据用傅立叶计算出实际信号的峰峰值,当我们输入信号比较小的时候,误差还是比较小的,可以接受的。当输入500mVpp信号时,峰峰值误差大概在6-10左右的变化。当我们将信号幅度调整到2.5Vpp的时候,我们发现误差非常大。经常是40-120左右的变化。跟我们实际的值有20%的误差。这个比较不能接受。大家有没有这类的问题,或者能帮忙分析下到底出了什么问题。


PS1:我们测试采集纯直流电压发现精度是很准的。
PS2:我们用了一块AVR的M32也进行了一场对比测试,同样的输入信号,AVR精度误差始终不会超过3.




沙发
viack|  楼主 | 2011-3-19 14:51 | 只看该作者
把我们单片机的ADC配置也发一下出来:

void ADC_Init(void)
{
        PB_DDR |= 1<<1;
        PB_CR1 |= 1<<1;
        //设置PB1为输出模式
  PD_DDR &= (~((1<<4)|(1<<5)|(1<<6)));  
  PD_CR1 &= (~((1<<4)|(1<<5)|(1<<6)));   
  PD_CR2 &= (~((1<<4)|(1<<5)|(1<<6)));  
        PB_DDR &= (~(1<<0));
        PB_CR1 &= (~(1<<0));
        PB_CR2 &= (~(1<<0));
        //ADC channel 8,9,10,16
  ADCOpen();
  ADC1_CR1 = 0x01;  
  //12-bit resolution /Single conversion mode/ADC enabled
  ADC1_CR2 = 0x00;
//f (ADC_CLK) = CK /Sampling time:4 ADC clock cycles  
//ADC1_CR3 = 0x1f;
//初始化值
  ADC1_TRIGR1 = 0x00;//初始化值       
        ADC1_TRIGR2 |= (1<<0);                   //channel 16 Schmitt trigger disabled
  ADC1_TRIGR3 |= ((1<<0)|(1<<1)|(1<<2));   //channel 8,9,10 Schmitt trigger disabled
  ADC1_SQR1 |= 0x80;//OFF DMA
  ADC1_SQR1 &= 0x7F;
  ADC1_SQR1 = 0x80;//OFF DMA
  ADC1_SQR2 = 0;
  ADC1_SQR3 = 0;
  ADC1_SQR4 = 0;
  ADCClose();
}

void ADCDelay(u32 n)
{
        while(!n--);
}
#define ADCOpen()          CLK_PCKENR2 |= (1<<0) ; ADC1_CR1 |= (1<<0)  //开启ADC,开启ADC时钟
#define ADCClose()          ADC1_CR1 &= (~(1<<0));   CLK_PCKENR2 &= (~(1<<0))  //关闭ADC,关闭ADC时钟

s16 ADCGetData_SingleTrans(s8 n)
{
        u8 temp = 0x01 << n;
        s16 result = 0x0000;
        ADCOpen();
        ADC1_SQR3 = temp;
        ADCDelay(24);
        ADC1_CR1 |= (1<<1);//开始转换       
        while(!(ADC1_SR & (1<<0)));   //等待转换结束
        result = (s16)(ADC1_DRH << 8) + ADC1_DRL;
        ADC1_CR1 &= ~(1<<1);//关闭转换       
        ADC1_SQR3 = 0x00;                //关闭8,9,10通道
        ADCClose();
        return result;
       
}

使用特权

评论回复
板凳
viack|  楼主 | 2011-3-19 15:02 | 只看该作者
再补发一个单片机的电路图:

使用特权

评论回复
地板
yu120036| | 2011-3-19 15:56 | 只看该作者
本帖最后由 yu120036 于 2011-3-19 15:58 编辑

嘿嘿!
我们部门另外一个小组使用STM8L,使用AD也出现问题,待转换的信号是个恒定的直流电压信号,只是测量的信号变化了,电压才变化,如果信号不变,电压是不变的。问题是现在测量信号未变,电压恒定,经过AD转换后,连续采样转换了1024个数据,发现转换结果变化太大。听说电压是0.503V时,理论值是0x270,实际得到的数据中有10%的结果是小于0x1F0的,这个问题已经搞了一个星期了,今天把我们这个小组也拉来加班,帮忙找问题。

(怎么老是陪太子读书!郁闷!:()

使用特权

评论回复
5
viack|  楼主 | 2011-3-19 16:03 | 只看该作者
同是天涯沦落人,我也是今天特别加班。。。。

使用特权

评论回复
6
donkey89| | 2011-3-19 22:18 | 只看该作者
关注一下先

使用特权

评论回复
7
viack|  楼主 | 2011-3-21 08:54 | 只看该作者
没有人遇到过这种问题么?

使用特权

评论回复
8
IJK| | 2011-3-21 10:05 | 只看该作者
既然LZ测量直流信号很准,而测量交流50Hz的大信号不准,其实不难找问题。
1.短路R12,避免阻抗匹配的影响。
2.直接给ADC输入50Hz的大信号方波信号,看ADC输出是否正确

使用特权

评论回复
9
viack|  楼主 | 2011-3-21 11:04 | 只看该作者
感谢8楼的,我刚刚用50Hz的大大信号方波进行测试,读取了一下12点的值,有大概2-9个值的误差,AD值为1382-1390这样子。
通过这个我还发现了一个问题,我的采集好像有点问题,我采集到的值出现了
0,0,0,0,0,0,1382,1382,1382,1382,1382,1382,1382,0,0,0,0,0,0,1380...
等这样的数据,采样点数都发生了变化。。。。
我用示波器去看我的定时,好像还是比较准的。。。不知道问题出在哪里。

使用特权

评论回复
10
关聿| | 2011-3-21 12:03 | 只看该作者
我用STM32F103VCT6和STM32F100VBT6做测量,很准的,STM32不能输入差分信号,若是交流信号,务必要用电压基准,使交流信号叠加在直流信号上,且正峰值不能超过VREF+,

使用特权

评论回复
11
viack|  楼主 | 2011-3-21 12:23 | 只看该作者
我前面的运放电路就是起这个作用的。就是将交流信号叠加到直流信号上,正峰值没有超过VREF+

使用特权

评论回复
12
zhd87| | 2011-3-21 15:09 | 只看该作者
额,原来是STM8。。。我正纳闷呢,我的32没这问题啊

使用特权

评论回复
13
capron| | 2011-3-23 12:39 | 只看该作者
本帖最后由 capron 于 2011-3-23 12:41 编辑

中间还出现6个点是0值,是不是ADC时钟频繁开/关,ADC模块没达到稳定状态的可能性?

试把ADC时钟一直开着看看结果?

楼主能否把相关FFT共享观赏一下?

使用特权

评论回复
14
viack|  楼主 | 2011-3-24 10:16 | 只看该作者
上述问题已解决,分享简易算法。目前出了新问题,我们使用10块板进行一致性测试,发现每块单片机的RTC定时不一致,误差有0.3mS,由于定时误差偏大,精度还是达不到要求。
//精简型的12点傅里叶级数
void FFT_funRo(s16 *Pin,Complex *str)
{
s16 sam1 = 0;
s16 sam2 = 0;
s16 sam3 = 0;
s16 sam4 = 0;
sam1 = *Pin-*(Pin+4)-*(Pin+6)+*(Pin+10);
sam2 = *(Pin+1)-*(Pin+3)-*(Pin+7)+*(Pin+9);
sam3 = *Pin+*(Pin+4)-*(Pin+6)-*(Pin+10);
sam4 = *(Pin+1)+*(Pin+3)-*(Pin+7)-*(Pin+9);
str->real = (sam1*1.732+sam2)/12+(*(Pin+11)-*(Pin+5))/6;
str->imag = (sam4*1.732+sam3)/12+(*(Pin+2)- *(Pin+8))/6;
}

使用特权

评论回复
15
香水城| | 2011-3-24 10:27 | 只看该作者
1)分享一下问题的解决办法
2)RTC定时不一致的问题很可能是外部晶体的不一致导致,你可以做交叉对比。

使用特权

评论回复
16
viack|  楼主 | 2011-3-24 13:46 | 只看该作者
1):原先问题是由于我们FFT计算出一个实部,虚部,然后再利用SQRT(实部×实部+虚部×虚部)计算出峰峰值。由于16位变量转32位时出现溢出。
2):我们没有使用外部晶振,使用内部RTC定时采集

使用特权

评论回复
17
香水城| | 2011-3-24 13:50 | 只看该作者
内部RTC的时钟源是什么? RC振荡器(LSI)还是晶体振荡器(LSE)?

使用特权

评论回复
18
viack|  楼主 | 2011-3-24 13:54 | 只看该作者
是内部的LSI

使用特权

评论回复
19
IJK| | 2011-3-24 16:16 | 只看该作者
是内部的LSI
viack 发表于 2011-3-24 13:54


内部的LSI 偏差太大了,不能用作精确定时。

使用特权

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

本版积分规则

16

主题

43

帖子

1

粉丝