你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

stm8s ADC设计上的bug吗??

[复制链接]
善良2016 提问时间:2017-5-11 13:25 /
问题如下:用的stms207芯片,timer1 100us中断,采样2路电流,软件启动AD,电机不转时,value1值在210附近,调节电位器,当value2超过255时候,value1变大,value2变小,明显两个AD转换值异常!怎么会有此现象,怎么解释??
@near @interrupt @svlreg void TIM1_UPD_OVF_TRG_BRK_IRQHandler (void)
{                                                   
//100us  中采集2路AD,一路电流,一路电位器
//        static unsigned int count2=0;                        
        TIM1->SR1 = (u8)(~0x01);//清除中断悬挂位
        cnt_1ms++;
        count2++;         
        if(count2>=5000)        //5000,0.5S时间累计
        {
         count2=0;
         GPIOD->ODR ^= GPIO_PIN_5;
        }                               
        ADC2->CSR = 10;          //一路电流 ,待机偏移量,1v附近
        ADC2->CR1 |= 0x01;                
        nop();
        while((ADC2->CSR&0x80)==RESET);        //没转换完,等待
        ADC2->CSR &= (u8)(~0x80);        //清EOC标志
        ADConverValue1= (u16)(ADC2->DRH<<8) + (u8)ADC2->DRL;//读取AD转换值                                                

        ADC2->CSR = 13;          //一路电位器,0~1024
        ADC2->CR1 |= 0x01;                   
        nop();
        while((ADC2->CSR&0x80)==RESET);        //没转换完,等待
        ADC2->CSR &= (u8)(~0x80);        //清EOC标志
        ADConverValue2= (u16)(ADC2->DRH<<8) + (u8)ADC2->DRL;//读取AD转换值   
}
收藏 2 评论8 发布时间:2017-5-11 13:25

举报

8个回答
善良2016 回答时间:2017-5-11 13:31:05
折腾了半天,解决办法就是同一路,多采样一次,即两路AD至少采样4次,各取后一次的值。奇葩的ADC啊,难道没人遇到过这问题??
另外:若中断中只是采样一路AD,就没有此问题,转换的值始终是对的。
zhuoyemp4 回答时间:2017-5-12 11:29:50
从你的程序来看,你只是采样了一次,严格来说一次采样的值在工程应用中是不可取的,通常是做多次采样后再滤波,最简单的就是多次采样后取平均值。我常用的是多次采样后按大小排序,去掉小的几个和大的几个,中间剩下的取平均值。在这里我给你提供一些简单滤波算法的参考。

假定从8位AD中读取数据(如果是更高位的AD可定义数据类型为int),子程序为get_ad();  
1、限副滤波
/*  A值可根据实际情况调整
    value为有效值,new_value为当前采样值   
    滤波程序返回有效的实际值  */
#define A 10
char value;
char filter()
{
   char  new_value;
   new_value = get_ad();
   if ( ( new_value - value > A ) || ( value - new_value > A )
      return value;
   return new_value;
}
2、中位值滤波法
/*  N值可根据实际情况调整
    排序采用冒泡法*/
#define N  11
char filter()
{
   char value_buf[N];
   char count,i,j,temp;
   for ( count=0;count<N;count++)
   {
      value_buf[count] = get_ad();
      delay();
   }
   for (j=0;j<N-1;j++)
   {
      for (i=0;i<N-j;i++)
      {
         if ( value_buf>value_buf[i+1] )
         {
            temp = value_buf;
            value_buf = value_buf[i+1];  
             value_buf[i+1] = temp;
         }
      }
   }
   return value_buf[(N-1)/2];
}      
3、算术平均滤波法
/*
*/
#define N 12
char filter()
{
   int  sum = 0;
   for ( count=0;count<N;count++)
   {
      sum + = get_ad();
      delay();
   }
   return (char)(sum/N);
}
4、递推平均滤波法(又称滑动平均滤波法)
/*
*/
#define N 12  
char value_buf[N];
char i=0;
char filter()
{
   char count;
   int  sum=0;
   value_buf[i++] = get_ad();
   if ( i == N )   i = 0;
   for ( count=0;count<N,count++)
      sum = value_buf[count];
   return (char)(sum/N);
}
5、中位值平均滤波法(又称防脉冲干扰平均滤波法)
/*
*/
#define N 12
char filter()
{
   char count,i,j;
   char value_buf[N];
   int  sum=0;
   for  (count=0;count<N;count++)
   {
      value_buf[count] = get_ad();
      delay();
   }
   for (j=0;j<N-1;j++)
   {
      for (i=0;i<N-j;i++)
      {
         if ( value_buf>value_buf[i+1] )
         {
            temp = value_buf;
            value_buf = value_buf[i+1];  
             value_buf[i+1] = temp;
         }
      }
   }
   for(count=1;count<N-1;count++)
      sum += value[count];
   return (char)(sum/(N-2));
}
6、限幅平均滤波法
/*
*/   
略 参考子程序1、3
7、一阶滞后滤波法
/* 为加快程序处理速度假定基数为100,a=0~100 */
#define a 50
char value;
char filter()
{
   char  new_value;
   new_value = get_ad();
   return (100-a)*value + a*new_value;  
}
8、加权递推平均滤波法
/* coe数组为加权系数表,存在程序存储区。*/
#define N 12
char code coe[N] = {1,2,3,4,5,6,7,8,9,10,11,12};
char code sum_coe = 1+2+3+4+5+6+7+8+9+10+11+12;
char filter()
{
   char count;
   char value_buf[N];
   int  sum=0;
   for (count=0,count<N;count++)
   {
      value_buf[count] = get_ad();
      delay();
   }
   for (count=0,count<N;count++)
      sum += value_buf[count]*coe[count];
   return (char)(sum/sum_coe);
}
9、消抖滤波法
#define N 12
char filter()
{
   char count=0;
   char new_value;
   new_value = get_ad();
   while (value !=new_value);
   {
      count++;
      if (count>=N)   return new_value;
       delay();
      new_value = get_ad();
   }
   return value;     
}
稀饭放姜 回答时间:2017-5-13 21:25:31
楼主没有看ADC的介绍,看你配置是手工切换采样通道,通道切换的时候,需要丢弃切换后的第一次采样数据,或者切换通道前让ADC进入低功耗,切换后再次唤醒。

如果不想这么麻烦,就配置通道扫描+DMA。
善良2016 回答时间:2017-5-15 09:57:01
zhuoyemp4 发表于 2017-5-12 11:29
从你的程序来看,你只是采样了一次,严格来说一次采样的值在工程应用中是不可取的,通常是做多次采样后再滤 ...

非常感谢!滤波算法看应用场合。我之所以这么快采样,而且不能有滤波(或滤波很小),我是准备做电流环的,电流环控制周期100us.
善良2016 回答时间:2017-5-15 09:59:45
稀饭放姜 发表于 2017-5-13 21:25
楼主没有看ADC的介绍,看你配置是手工切换采样通道,通道切换的时候,需要丢弃切换后的第一次采样数据,或 ...

嗯。看过了。用通道扫描+DMA确实是最有效的办法。但stm8s没有DMA方式。而且207芯片只有ADC2,还不支持通道扫描。
稀饭放姜 回答时间:2017-5-15 21:54:35
善良2016 发表于 2017-5-15 09:59
嗯。看过了。用通道扫描+DMA确实是最有效的办法。但stm8s没有DMA方式。而且207芯片只有ADC2,还不支持通 ...

那你就只能通过启动和停止ADC的使能再切换通道,或者丢弃第一次采集的数据。
善良2016 回答时间:2017-5-16 09:32:32
稀饭放姜 发表于 2017-5-15 21:54
那你就只能通过启动和停止ADC的使能再切换通道,或者丢弃第一次采集的数据。 ...

是的,丢弃第一次采集的数据。但这也导致采集次数增加,用时变长,我测试了下,采集4次,大概用时16us。假如还要做电流环,一个pid用时更多,100us中断根本不够,看起来stm8s做不了电流环。
奶牛咖啡2012 回答时间:2017-9-25 10:53:29
STM8S系列不存在切换通道后第一次转换结果需要忽略的问题,
STM8S中文参考手册与英文原版有多处不符,应以英文原版为准

所属标签

相似问题

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版