找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2020|回复: 16
收起左侧

关于stc15w108单片机ad平均值怎么写好?望高手指点

  [复制链接]
ID:65237 发表于 2021-10-7 23:18 来自手机 | 显示全部楼层 |阅读模式
手上有15w408as想做个检测电压的 ,PWM输出控制  MOS管开关 再串一个0.33欧姆电阻到地 电源24伏供电.电流200ma 检测0.33上的电压去控制pwm脉宽让MOS管电流保持在200左右 现在是ad检测值想做个平均 如用for循环 5次 平均 是连续检测5次了 还是等ad检测时间到了算一次 等5次ad检测完成的值加在一起平均,戓更好的检测方法 望指高点
回复

使用道具 举报

ID:752974 发表于 2021-10-8 10:23 | 显示全部楼层
每次启动AD,连续转换需要的次数,然后关掉ad,处理数据,数字滤波可以用平均值法,或裁判法,即去掉一个最大的,去掉一个最小的,再取平均值。
回复

使用道具 举报

ID:514901 发表于 2021-10-8 10:33 | 显示全部楼层
连续采集20次AD,去掉头尾5次的AD值,中间10次的取平均值,这样求出来的数据比较稳定
回复

使用道具 举报

ID:624769 发表于 2021-10-8 13:48 | 显示全部楼层
一般不会取5次……, 大多10次以上的, 不然没有平均的意义。
正常做法,一共取10次, 前两次抛弃, 第三次开始,每次累加,结束后右移三位,搞定收工。
回复

使用道具 举报

ID:130230 发表于 2021-10-8 15:01 | 显示全部楼层
平滑移动滤波,每次进一个出一个。然后取最近10次的平均值。
回复

使用道具 举报

ID:65237 发表于 2021-10-8 21:19 来自手机 | 显示全部楼层
munuc_w 发表于 2021-10-8 10:23
每次启动AD,连续转换需要的次数,然后关掉ad,处理数据,数字滤波可以用平均值法,或裁判法,即去掉一个最 ...

你的意思是不是,如以10次为例正常ad起动10次,把这每次得到的值依次加在一起,放在一个变量中 然后除以10得到他的平均值
回复

使用道具 举报

ID:65237 发表于 2021-10-8 21:20 来自手机 | 显示全部楼层
郑汉松 发表于 2021-10-8 10:33
连续采集20次AD,去掉头尾5次的AD值,中间10次的取平均值,这样求出来的数据比较稳定

谢谢老师
回复

使用道具 举报

ID:65237 发表于 2021-10-8 21:30 来自手机 | 显示全部楼层
188610329 发表于 2021-10-8 13:48
一般不会取5次……, 大多10次以上的, 不然没有平均的意义。
正常做法,一共取10次, 前两次抛弃, 第三 ...

为什么是右移三位了  不明白望指点 10位ad满是1024丢前二后三剩下5次的总和,最大是5120右移3位得5不明白
回复

使用道具 举报

ID:213173 发表于 2021-10-8 21:34 | 显示全部楼层
ADC.C文件,适合STC15W408AS
  1. #include <STC15F2K60S2.H>
  2. #include <intrins.H>
  3. #define uchar unsigned char
  4. #define uint unsigned int
  5. /*----------------------------
  6.         ADC操作相关的宏定义
  7. ----------------------------*/
  8. #define ADC_POWER   0x80            //ADC power control bit
  9. #define ADC_FLAG    0x10            //ADC complete flag
  10. #define ADC_START   0x08            //ADC start control bit
  11. #define ADC_SPEEDLL 0x00            //420 clocks
  12. #define ADC_SPEEDL  0x20            //280 clocks
  13. #define ADC_SPEEDH  0x40            //140 clocks
  14. #define ADC_SPEEDHH 0x60            //70 clocks

  15. uint ADC_mV;

  16. void Init_ADC();                                //初始化ADC
  17. uint GetADCResult(uchar CHA);        //获取AD通道转换结果
  18. void ADC_Average();                                //ADC平均值

  19. /*-----------------------------------------------------------------------------
  20.   InitADC 初始化ADC
  21. -----------------------------------------------------------------------------*/
  22. void Init_ADC()
  23. {
  24.         P1ASF=0x08;                                                //设置P1.3通道端口作为模拟输入
  25.         ADC_RES=0;                                                //清除ADC_RES存储器以前的结果
  26.         ADC_RESL=0;
  27.         ADC_CONTR=ADC_POWER|ADC_SPEEDLL;//ADC 开启电源、转换速度 1000 0000
  28.         delayms(1);                                                //上电延时1ms                                                                                       
  29. }
  30. /*----------------------------------------------------------------------------
  31. Get ADC Result(获取ADC结果)
  32. ----------------------------------------------------------------------------*/
  33. uint GetADCResult(uchar CHA)                //获取ADC结果
  34. {
  35.         ADC_CONTR=ADC_POWER|ADC_SPEEDLL|CHA|ADC_START;//启动转换1000 1000
  36.     _nop_();                        //延时确保正确读到ADC_CONTR寄存器的值
  37.     _nop_();
  38.     _nop_();
  39.     _nop_();
  40.         while(!(ADC_CONTR & ADC_FLAG));        //等待ADC转换完成标志置位 1001 1000
  41.         ADC_CONTR &=~ADC_FLAG;                        //关闭ADC
  42.         return ADC_RES<<2|ADC_RESL ;                //返回十位ADC结果
  43. }
  44. /*-------------------------------
  45.   1ms延时子程序(11.0592MHz 1T)
  46. -------------------------------*/
  47. void delayms(uint k)
  48. {
  49.         uint i,j;
  50.         for(i=k;i>0;i--)
  51.                 for(j=829;j>0;j--);
  52. }
  53. /*-------------------------------
  54.   ADC平均值
  55. -------------------------------*/
  56. void ADC_Average()
  57. {
  58.         static uint temp;
  59.         static uchar count=0;
  60.         temp+=GetADCResult(n);//n=0~7
  61.         count++;
  62.         if(count>=10)                                        //累计数十次采样
  63.         {
  64.                 count=0;                                        //计数器清0
  65. //                ADCV=VCC*10bitAD/1024;                //换算公式
  66.                 ADCmV=(5000*(long)temp/1024+5)/10;//四舍五入
  67.                 temp=0;
  68.         }
  69. }
复制代码
回复

使用道具 举报

ID:752974 发表于 2021-10-9 08:33 | 显示全部楼层
阿飞7812 发表于 2021-10-8 21:19
你的意思是不是,如以10次为例正常ad起动10次,把这每次得到的值依次加在一起,放在一个变量中 然后除以1 ...

是的,就是这个意思。
回复

使用道具 举报

ID:65237 发表于 2021-10-9 21:28 来自手机 | 显示全部楼层
wulin 发表于 2021-10-8 21:34
ADC.C文件,适合STC15W408AS

十分感谢
回复

使用道具 举报

ID:624769 发表于 2021-10-9 21:54 | 显示全部楼层
阿飞7812 发表于 2021-10-8 21:30
为什么是右移三位了  不明白望指点 10位ad满是1024丢前二后三剩下5次的总和,最大是5120右移3位得5不明白

右移3位,相当于 除以8,但是效率比除以8高很多,取10次舍弃前2次,剩下的8次累加后右移3位就是平均值,16次累加右移4位,也是一样的性质。
回复

使用道具 举报

ID:401564 发表于 2021-10-9 23:06 | 显示全部楼层
188610329 发表于 2021-10-9 21:54
右移3位,相当于 除以8,但是效率比除以8高很多,取10次舍弃前2次,剩下的8次累加后右移3位就是平均值,1 ...

其实是一样的
在Keil中,C的位移在编译时并不是位移,而是加法减法之类的
除以8和右移3位编译之后的汇编代码是一样的,效率是一样的
你试一下就知道了
回复

使用道具 举报

ID:908826 发表于 2021-10-10 10:53 | 显示全部楼层
给我你的邮箱,我有个数字滤波的pdf可以给你分享。
回复

使用道具 举报

ID:554500 发表于 2021-10-12 16:14 | 显示全部楼层

连续取10个样(多取一些也可以),然后就行大小排序。
最后取中间两个相加,再除以2就可以了。


// 经典冒泡排序
void BubbleSort(u16 *arr, u8 n)
{
        int i = 0, j =0;
        for(i = 0; i < n; i++)
        for(j = 0; j < n - 1 - i; j++)
        {
                if(arr[j] > arr[j + 1])
                {
                        arr[j] = arr[j] ^ arr[j+1];
                        arr[j+1] = arr[j] ^ arr[j+1];
                        arr[j] = arr[j] ^ arr[j+1];
                }
        }
}

void ADC_Read_Switch()
{
        u16 xdata val[10];
        u8  xdata j;
       
        for(j=0;j<10;j++)
                val[j]=ADC_START(ADC_CH0); //通道0,连续采样5次
        BubbleSort(val,10); //排序
        AD0=(val[4] + val[5])/2;
}


回复

使用道具 举报

ID:956872 发表于 2021-10-13 10:03 | 显示全部楼层
wulin 发表于 2021-10-8 21:34
ADC.C文件,适合STC15W408AS

我用的408AS,用这程序编译了,为啥百位后面会跳变。还有最大有0.6V多的误差。最高只能显示4.99V。
回复

使用道具 举报

ID:65237 发表于 2021-10-17 10:34 | 显示全部楼层
Y_G_G 发表于 2021-10-9 23:06
其实是一样的
在Keil中,C的位移在编译时并不是位移,而是加法减法之类的
除以8和右移3位编译之后的汇编 ...

谢谢 我试试
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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