搜索
bottom↓
回复: 45

STM8S ADC 多通道 单次转换引脚会出现干扰波

[复制链接]

出0入0汤圆

发表于 2010-8-6 17:08:32 | 显示全部楼层 |阅读模式
程序如下,使用的芯片为STM8S105S4,使用的是ADC单次转换。有的进行一路ADC转换时,ADC引脚没有干扰波,ADC转换正常,有的进行一路转换,或进行两个通道或以上转换时,发现引脚会出现干扰波,而且那个尖峰发生在ADC开始转换的瞬间,240ns。这是什么问题,很奇怪。
void Clk_Init(void)
{
        CLK_CKDIVR = 0x00;           //设为16MHZ
}

void ADC_Init(void)
{
    u8 i;
    ADC_CR2   =   0x00;
    ADC_CR1  |=   0x20;                 
    ADC_CR1  |=   0x01;                          //开始启动
     i=30;
     while(i--);
}

u16 ReadAdc(u8 chn)
{
         u16 AD_Value;
        u8 i;
       
        ADC_CSR &= 0xF0;
        ADC_CSR |= (chn-1);
        //ADC_CR1 |= 0x01;                          //开始启动
        //i=30;
        //while(i--);
        ADC_CR1 |= 0x01;                          //开始转换
        while(!(ADC_CSR & 0x80));   //等待转换结束
        AD_Value=((((unsigned int)ADC_DRH)<<2)+ADC_DRL);
        ADC_CSR &= 0x7F;                  //清除标志位
        //ADC_CR1 &= ~(0x01);
        return AD_Value;
}

void main()
{
u16 test;
_asm("sim");      //停止所有中断
Clk_Init();
GPIO_Init(GPIOB, ((u8)0x7F), GPIO_MODE_IN_FL_NO_IT); //需要用到0-6个通道
ADC_TDRL=0x7F;//禁用ADC端口触发器
ADC_Init();          //ADC初始化
_asm("rim");      //开启中断

while(1)
{
test = ReadAdc(1);
test = ReadAdc(2);
}
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2010-8-6 20:22:08 | 显示全部楼层
在通道切换后延时长一点,或有所帮助。我也遇到过类似的问题。后来我改用单通道连续转换。三通道切换转换数据很稳定。

出0入0汤圆

 楼主| 发表于 2010-8-10 09:11:50 | 显示全部楼层
我把外围是电路断开,发现干扰波是从芯片引脚中发中,外围电路本来就是没有这种干扰的。干扰都是时间很短的尖峰波

出0入0汤圆

 楼主| 发表于 2010-8-10 10:20:24 | 显示全部楼层
问题就出在这里,如果我按照下面的写法是会出现干扰波。
ADC_CSR &= 0xF0;
ADC_CSR |= (chn-1);

出0入0汤圆

发表于 2010-8-10 10:46:35 | 显示全部楼层
ADC_CSR |= (chn-1);

是不对的。。。

chn==1时,选中的是AIN0

chn=0时。。。杯具。。。

出0入0汤圆

 楼主| 发表于 2010-8-10 14:06:10 | 显示全部楼层
就是一写入ADC_CSR肯定会有干扰波出来,有没有影响的?

出0入0汤圆

 楼主| 发表于 2010-8-11 11:23:18 | 显示全部楼层
回复【4楼】snoopyzz
adc_csr |= (chn-1);  
是不对的。。。
chn==1时,选中的是ain0
chn=0时。。。杯具。。。
-----------------------------------------------------------------------

我为了调整函数,方便使用。

出0入0汤圆

发表于 2010-9-26 20:34:52 | 显示全部楼层
的确,烦死了,如果只是读取一个通道ADC,则一切正常,如果要切换通道使用,会有干扰波出现。而且好像置位,清除 ADON 位(也就是开关ADC)也会出现干扰波在引脚上,搞不清楚怎么会这样。

出0入0汤圆

发表于 2010-9-29 22:54:05 | 显示全部楼层
没人知道原因吗

出0入0汤圆

发表于 2010-9-30 00:15:08 | 显示全部楼层
回复【楼主位】wendyfox  
-----------------------------------------------------------------------

请问楼主的问题解决了没?
我最近也碰到了这个问题,头痛的很,多通道读值会导致ADC输入信号的纹波变大,达到了几十个mV了,而断开ADC输入脚后,纹波很小,就算是加入1K的电阻+电容隔离也只能减轻“症状“,不能处理干净;

出0入90汤圆

发表于 2010-9-30 10:03:38 | 显示全部楼层
为什么我多个通道扫描,就是加了个104滤波,结果就很稳定呢,实现了10bit AD的最小采样。误差也就在+-1。

出0入0汤圆

发表于 2010-9-30 10:52:31 | 显示全部楼层
回复【10楼】honami520
-----------------------------------------------------------------------

请问你是怎么处理的?能否参考你的ADC处理代码,有用到DMA没?据说DMA的处理有稳定的多?

出0入0汤圆

发表于 2010-9-30 16:22:50 | 显示全部楼层
本来ADC是是输入引脚,加104也是为了滤除输入杂波,现在ADC变成了输出了,在ADC引脚悬空的状态下,用示波器量,输出尖波的幅度达到几百毫伏。输出尖波的情形发生在开启和关闭ADC电源,也发生在ADC通道切换。

出0入0汤圆

发表于 2011-3-19 10:27:05 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-11-15 16:40:21 | 显示全部楼层
AD_Value=((((unsigned int)ADC_DRH)<<2)+ADC_DRL);
这个应该是:
AD_Value=((((unsigned int)ADC_DRH)<<8)+ADC_DRL);
吧?
还有,要先读ADC_DRL再读ADC_DRH,改成:
AD_Value=ADC_DRL+(((unsigned int)ADC_DRH)<<8);
比较合理吧

出0入0汤圆

发表于 2013-3-5 20:05:36 | 显示全部楼层
我也正在头疼连续扫描模式下,读出的AD值不稳定,数值来回变换,但我直接测试3.3又很稳定,经过分压后测试5V,就出现数值来回变化。

出0入0汤圆

发表于 2013-3-17 19:09:26 | 显示全部楼层
  我也在研究呢。

出0入0汤圆

发表于 2013-4-11 12:44:59 | 显示全部楼层
lwg998 发表于 2013-3-5 20:05
我也正在头疼连续扫描模式下,读出的AD值不稳定,数值来回变换,但我直接测试3.3又很稳定,经过分压后测试5 ...

   我也遇到了这个问题,真的很奇怪。

出0入0汤圆

发表于 2013-4-13 22:31:07 | 显示全部楼层
主要还是供电电压不稳。只能多次采样平均一下了

出0入112汤圆

发表于 2013-4-13 23:51:50 | 显示全部楼层
是什么回事?解决没?
我也准备用STM8

出0入0汤圆

发表于 2013-5-17 00:35:22 | 显示全部楼层
同问,我也搞不明白,用在定时器中选择通道,然后开启AD转换与中断,在AD中断程序中取对应通道的AD值,完成后,改为下一个通道,不知为什么,有的通道AD值变化很大,有如下疑问:
1: 当通道1还没转换完中断时,就转为下一个通道了,因我轮流转换的时间间隔为100US,但STM8的转换时间不会这么长吧
2:  是先开启中断,再选择通道,再开启转换吗
3: 在ADC中断中取完数后要清EOC标志位吗,然后关中断

出0入112汤圆

发表于 2013-5-18 09:05:22 | 显示全部楼层
那个脚上有干扰?

出0入0汤圆

发表于 2013-5-18 09:13:30 | 显示全部楼层
是因为相邻的ADC输入口压差较大,通道切换后,内部ADC滤波电路的电容上的电压施加到切换后的输入口所致,解决方法:
1:多采样几次,丢掉前面不稳定的。
2:延迟,用示波器观察输入波动的时间,延迟等待稳定。
3:降低信号源阻抗,缩短延迟时间。
4:合理安排输入口,使其相邻压差较小。

出0入0汤圆

发表于 2013-5-18 15:40:06 | 显示全部楼层
楼上说的好像很有道理啊,学习了

出0入0汤圆

发表于 2013-8-21 14:33:45 | 显示全部楼层
切换通道后,前几次转换结果丢掉,取后几次转换结果。具体几次跟据实际情况来取。

出0入0汤圆

发表于 2013-8-21 17:21:06 | 显示全部楼层
关注该帖子,共同学习。

出0入0汤圆

发表于 2013-10-9 10:21:17 | 显示全部楼层
很好很有用,学习了。有谁解决了这个问题,分享一下。

出0入0汤圆

发表于 2013-11-2 18:31:44 | 显示全部楼层
u16 Get_ADC_Value(u8 channel)
{
      //start ADC
      ADC_Init(channel);
      for(ADC_Cnt=0;ADC_Cnt<10;ADC_Cnt++)
      {
        ADC1_StartConversion();
        Delay(0xff);
        ADC_Data_Buffer[ADC_Cnt] = ADC1_GetConversionValue();
需要加延时才行 ,等待转换结束

出0入0汤圆

发表于 2013-11-21 14:29:37 | 显示全部楼层
正需要,AD多通道测试中。

出0入0汤圆

发表于 2014-1-24 11:46:10 | 显示全部楼层
遇到同样问题? 单次没问题 多次就有问题 到底是什么原因?

出0入0汤圆

发表于 2014-1-24 12:26:42 | 显示全部楼层
建议你去 stmcu。org网站上找stm8的有个文档,讲怎样提高ADC准确性,stm8的adc是利用电容充电后进行比较的,开始采集时,需要吸收外部电流给adc内的比较用的电容充电,你看看  文档是这个 AN3137 ,里面有一些介绍,比如降低输入电阻,增加外部电容缓冲等,还有取样时间,等的选择。

出0入0汤圆

发表于 2014-1-24 16:46:38 | 显示全部楼层
这个可以了
  1. /*********************************************
  2. 函数功能:ADC单通道转换初始化
  3. 输入参数:无
  4. 输出参数:AD数值
  5. 备    注:使用该函数前,需修改在ADC.h中的IO口宏定义
  6. *********************************************/
  7. void ADC_Init(void)
  8. {  
  9.   
  10.     //ADC_IOConfig();

  11.     //ADC1->CSR &=~BIT(5);
  12.     ADC1->CSR = (0<<5);  
  13.    
  14.     ADC1->CR1 |= BIT(6);//   Fmaster/8
  15.     ADC1->CR1 &=~BIT(1);//单次转换模式
  16.     //ADC1->CR1 |=BIT(1);//连续转换模式
  17.    
  18.     ADC1->CR2 |= BIT(3);//数据右对齐
  19.    
  20.     ADC1->CR1 |= BIT(0);//把AD唤醒
  21.    
  22.    
  23.    
  24.   /*
  25.    ADC1->CR1 = (0<<4)|(1<<1)|(0<<0);    //ADC时钟输入频率为16MHz 这里设置分频系数为2  连续转换模式 先禁止ADC转换      
  26.    ADC1->CR2 = (1<<3)|(0<<1);           //设置数据右对齐  禁止扫描模式
  27.   
  28.    //ADC_CSR = (0<<5)|(0x4<<0);         //不用外部触发 禁止转换结束中断 设置转换通道为AIN10
  29.    ADC1->CSR = (0<<5);   
  30.    
  31.    ADC1->TDRH = 4;                      //禁止AIN10施密特触发器功能  
  32.    ADC1->CR1 |= 1;                      //第一次写1是从低功耗模式唤醒
  33.    ADC1->CR1 |= 1;                      //在这一位是1的情况下再次写1启动ADC转换
  34. */
  35. }

  36. /*********************************************
  37. 函数功能:获取ADC转换数据
  38. 输入参数:Channel:Channel_0——Channel_15
  39. 输出参数:AD数值
  40. 备    注:无
  41. *********************************************/
  42. u16 ADC_Data(u8 Channel)
  43. {
  44.     u8 i = 0;
  45.     u16 data=0;
  46.    
  47.     ADC_Init();
  48.     ADC1->CSR |= Channel;//选择通道
  49.    
  50.     i=60;
  51.     while(i--);
  52.    
  53.     ADC1->CR1 |= BIT(0);//ADC使能
  54.    
  55.     while((ADC1->CSR&0X80)==0);//等待转换结束
  56.     ADC1->CSR &=~BIT(7);//清除转换结束标志位

  57.     data =  ADC1->DRL;
  58.     data |= ((ADC1->DRH << 8) & 0x0300);

  59.     return data;
  60. }

  61. /*********************************************
  62. 函数功能:ADC IO初始化
  63. 输入参数:无
  64. 输出参数:无
  65. 备    注:通过修改宏定义改变所要初始化的IO
  66. *********************************************/
  67. void ADC_IOConfig(void)
  68. {
  69.     ADC_GPIO->DDR &=~ADC_PIN_CHA;//输入模式
  70.     ADC_GPIO->CR1 &=~ADC_PIN_CHA;//浮空输入模式   
  71.    
  72.     ADC_GPIO->DDR &=~ADC_PIN_CON;//输入模式
  73.     ADC_GPIO->CR1 &=~ADC_PIN_CON;//浮空输入模式   
  74. }
复制代码

  1.       while(1)
  2.       {   
  3. #if  1        
  4.           AD_Value = (u16)((u32)ADC_Data(Channel_4)*3300/1024);
  5.           UART_SendChar(AD_Value & 0xff);
  6.           delay_ms(500);
  7.          
  8. #endif           
  9. #if  1
  10.           AD_Value=0;
  11.           AD_Value = (u16)((u32)ADC_Data(Channel_3)*3300/1024);
  12.           UART_SendChar(AD_Value & 0xff);
  13.           delay_ms(500);

  14. #endif           
  15.       }
  16.         
复制代码

出0入0汤圆

发表于 2014-1-24 16:49:37 | 显示全部楼层
  STM8_4432_Key.rar
这是测试代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2014-2-13 19:04:45 | 显示全部楼层
lwg998 发表于 2013-3-5 20:05
我也正在头疼连续扫描模式下,读出的AD值不稳定,数值来回变换,但我直接测试3.3又很稳定,经过分压后测试5 ...

请问STM8S多通道连续扫描的问题是否解决?我最近做的部分应用在多通道连续扫描时遇到了问题,只有第一个通道有测量值,后续通道都没有,不知道你是否遇到过?

出0入0汤圆

发表于 2014-9-1 21:07:50 | 显示全部楼层
MARK~~~~~~~~~~~~~~~~~~~~~~~~~`

出0入8汤圆

发表于 2014-11-5 22:42:00 | 显示全部楼层
beijisnow 发表于 2013-11-2 18:31
u16 Get_ADC_Value(u8 channel)
{
      //start ADC

哥们 用这个不准啊,差了0.4v  给跪了!~~~~

出0入8汤圆

发表于 2014-11-5 23:02:02 | 显示全部楼层
opiviqo 发表于 2014-11-5 22:42
哥们 用这个不准啊,差了0.4v  给跪了!~~~~

好了  在这里加个延时 问题解决了:
u16 Get_ADC_Value(int channel)
{
  uint16_t adc_result = 0;
  ADC_Init(channel);
  Delay(1000);           //这里加个延时就好了!
  for(int j=0;j<10;j++)
  {
    ADC1_StartConversion();
    adc_result += ADC1_GetConversionValue();
    Delay(0xff);
  }
  adc_result = adc_result/10;
  return adc_result;
}

出0入0汤圆

发表于 2015-4-29 20:09:13 | 显示全部楼层
本帖最后由 ddddd120 于 2015-4-29 20:11 编辑
lovepig200 发表于 2014-1-24 12:26
建议你去 stmcu。org网站上找stm8的有个文档,讲怎样提高ADC准确性,stm8的adc是利用电容充电后进行比较的 ...


这个说的很有道理,stm8s没有这个文档,stm8 和stm8l有,应该内部结构是一样的。可能是外部信号没有稳定,就开始转换的原因

出0入0汤圆

发表于 2015-5-22 08:16:26 | 显示全部楼层
挖出来,那个连续扫描有人试出来了吗,怎么解决的啊?

出0入0汤圆

发表于 2015-5-22 09:45:16 | 显示全部楼层
第一次转换的AD不使用,或者每次转换完之后,采集一下一个接地的AD口,这种叫AD放电,

出0入0汤圆

发表于 2015-5-22 20:51:01 | 显示全部楼层
我的解决办法:把AD输入端口的思密特触发器使能。并且扫描模式下,AD0-AD9的端口不能配置为输出,否则会有50KHZr的尖峰,这个在PDF文档上有说明。总之STM8第一次用挺头疼。。。

出0入0汤圆

发表于 2015-5-22 23:36:34 | 显示全部楼层
现在遇到了这个问题,把以上的方法都要试一遍

出0入213汤圆

发表于 2015-5-23 15:11:32 | 显示全部楼层
unsigned int ADC16s(void)
{
        unsigned int result = 0;
        unsigned char i;
        //预先配置好ADC_CSR    // 选择AD转换通道
        ADC_CR1 = B01100010;      // 设置AD转换时钟1/12,连续转换模式
        ADC_CR2 = B00001000;      // 设置数据为右对齐,高2位,低8位
        ADC_CR3 = B00000000;      // 不使用数据缓冲
        ADC_CR1 |=B00000001;      // 打开AD模块电源
        DelayXus(150);            // 延时至少100uS,用于等待采样保持电容充电至稳定
        ADC_CR1 |=B00000001;      // 启动AD转换
        ADC_CSR &= 0x7F;
        while(!(ADC_CSR & 0x80));    // 等待AD转换完成
        i=ADC_DRL;
        i=ADC_DRH;
        for(i = 0; i < 16; i++)
                {
                        ADC_CSR &= 0x7F;
                        while(!(ADC_CSR & 0x80));    // 等待AD转换完成
                        result += ADC_DRL;
                        result += ADC_DRH * 256;
                }
        ADC_CR1 &= 0xFE;
        result =(result+8)>>4; //取16次的平均数,四舍五入(10bit)
        return result;
}

每次切换通道,加适量延时,放弃第一次的结果。然后采样16次,取平均数。

我是这么用的。供楼主参考。

出0入0汤圆

发表于 2015-11-19 12:36:48 | 显示全部楼层
honami520 发表于 2010-9-30 10:03
为什么我多个通道扫描,就是加了个104滤波,结果就很稳定呢,实现了10bit AD的最小采样。误差也就在+-1。 ...

多通道扫描是用单次模式还是连续模式,通道切换需要注意什么的?

出0入90汤圆

发表于 2015-11-19 14:31:32 | 显示全部楼层
lzly0302 发表于 2015-11-19 12:36
多通道扫描是用单次模式还是连续模式,通道切换需要注意什么的?

多通道扫描,没有通道切换一说,自动切换了,哪里还需要你自己去切换。
至于单次和连续,要看你是否使用DMA。

出0入89汤圆

发表于 2017-10-16 22:36:58 | 显示全部楼层
这个问题我也遇到了。。。
搞了1天都不行。那个脉冲和我的输出PWM混在一起无法正常使用。
最后我是这样解决的:http://www.cnblogs.com/csaaa/p/7679289.html
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-26 16:37

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表