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

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管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版