找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1722|回复: 18
打印 上一主题 下一主题
收起左侧

单片机ADC多路转换,有些程序语句不理解,求解释

  [复制链接]
跳转到指定楼层
楼主
ID:686513 发表于 2022-2-10 09:37 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
后面注释是我自己加上去的,不知道理解的对不对?还有if(count0<32)          //如果通道0转换次数小于32 这个语句有没有数据滤波功能,这有32可以是任意值吗?

单片机源程序如下:
#include "adc.h"
#include "delay.h"

typedef unsigned char u8;
typedef unsigned int u16;

unsigned long int ADC_DATA0;        //           ADC0数据
unsigned long int ADC_DATA1;        //           ADC1数据
unsigned long int ADC_DATA2;        //           ADC2数据

u8  count0;        //        ADC通道0转换次数记录
u8  count1;        //        ADC通道1转换次数记录
u8  count2;        //        ADC通道2转换次数记录
u8  ADC_LINE;        //        ADC通道记录

//ADC口初始化
void STC8ADC_INIT()                         //STC8ADC初始化
{
  P1M0=0x00;
  P1M1=0x07;        //设定P1.4567通道为高阻
//         P_SW2|=0X80;    //打开特殊功能寄存器
//   ADCTIM=0X3F;    //设置ADC内部时序
//   P_SW2&=0X7F;    //关闭特殊功能寄存器
  ADCCFG=0x2f;          //设置ADC的时钟和转换结果存放格式
  ADC_CONTR=0x80;//选择ADC通道
  ADC_LINE=0x80;
  DelayXms(10);
  ADC_CONTR=ADC_CONTR|0x40;        //启动ADC
  EADC=1;
}               

void ADC_ISR()interrupt 5
{
        ADC_CONTR=ADC_CONTR&0xdf;        //清除中断标志位
//=============================================================================================================
        if(ADC_LINE==0x80)        //选择通道0
                {  
                if(count0<32)          //如果通道0转换次数小于32
                        {                        
                                 ADC_DATA0=0x00;    //ADC0数据清零
                                 count0=0x00;       //通道0转换次数清零
                        }
                        ADC_DATA0=ADC_DATA0+(ADC_RES*256+ADC_RESL);        //ADC结果处理
                        count0++;            //通道0转换次数加1
                        ADC_LINE=0x81;       //切换下一通道(通道1)
                        ADC_CONTR=ADC_LINE;   //下一通道值赋给配置寄存器
                }
//====================================================================
else if(ADC_LINE==0x81)      //选择通道1
                {  
                if(count1<32)            //如果通道1转换次数小于32
                        {
                                 ADC_DATA1=0x00;      //ADC1数据清零
                                 count1=0x00;         //通道1转换次数清零
                        }
                        ADC_DATA1=ADC_DATA1+(ADC_RES*256+ADC_RESL);        //ADC结果处理
                        count1++;                //通道1转换次数加1
                        ADC_LINE=0x82;           //切换下一通道(通道2)
                        ADC_CONTR=ADC_LINE;      //下一通道值赋给配置寄存器
                }
//=====================================================================
else if(ADC_LINE==0x82)     //选择通道2
                {  
                if(count2<32)            //如果通道2转换次数小于32
                        {
                                 ADC_DATA2=0x00;      //ADC2数据清零
                                 count2=0x00;         //通道2转换次数清零
                        }
                        ADC_DATA2=ADC_DATA2+(ADC_RES*256+ADC_RESL);        //ADC结果处理
                        count2++;              //通道2转换次数加1
                        ADC_LINE=0x80;         //切换下一通道(通道0)
                        ADC_CONTR=ADC_LINE;    //下一通道值赋给配置寄存器
                }

//=============================================================================================================                                   
        ADC_CONTR=ADC_CONTR|0x40;        //启动ADC
}


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏5 分享淘帖 顶2 踩
回复

使用道具 举报

沙发
ID:313048 发表于 2022-2-10 10:37 | 只看该作者
这里是做一个累加,2个通道连续都采样32次之后则清除ADC的数据。32你可以自己选择。
回复

使用道具 举报

板凳
ID:807651 发表于 2022-2-10 13:48 | 只看该作者
这个数值32应该是ad采样32次后用来求平均值(滤波),每32次清零重新计数,这个数值可以根据使用调整
回复

使用道具 举报

地板
ID:686513 发表于 2022-2-10 18:00 | 只看该作者
AUG 发表于 2022-2-10 10:37
这里是做一个累加,2个通道连续都采样32次之后则清除ADC的数据。32你可以自己选择。

也就是说只是获取了32次ADC结果,但没有对这32次结果处理?
回复

使用道具 举报

5#
ID:686513 发表于 2022-2-10 18:00 | 只看该作者
wd1988 发表于 2022-2-10 13:48
这个数值32应该是ad采样32次后用来求平均值(滤波),每32次清零重新计数,这个数值可以根据使用调整

也就是说只是获取了32次ADC结果,但没有对这32次结果处理?
回复

使用道具 举报

6#
ID:956872 发表于 2022-2-10 19:07 | 只看该作者
zhth1979 发表于 2022-2-10 18:00
也就是说只是获取了32次ADC结果,但没有对这32次结果处理?

为啥要加<32这句判断。这句判断的意义是什么?
回复

使用道具 举报

7#
ID:807651 发表于 2022-2-11 10:26 | 只看该作者
zhth1979 发表于 2022-2-10 18:00
也就是说只是获取了32次ADC结果,但没有对这32次结果处理?


是的,结合代码的时意思  ADC_DATA0 变量存着32次ad采样的值。
回复

使用道具 举报

8#
ID:686513 发表于 2022-2-11 11:44 | 只看该作者

本来想三路ADC,每路读32次结果在mian函数里求平均的,但感觉又好像不对,现在也不知道从哪处理比较合适?这个程序也是仿坛友的。
回复

使用道具 举报

9#
ID:807651 发表于 2022-2-11 13:52 | 只看该作者
zhth1979 发表于 2022-2-11 11:44
本来想三路ADC,每路读32次结果在mian函数里求平均的,但感觉又好像不对,现在也不知道从哪处理比较合适 ...

                       if(count2<32)            //如果通道2转换次数小于32
                        {
                                 ADC_DATA22 =ADC_DATA2/32;//可以放在清零前 用ADC_DATA22 存着求平均后的值
                                 ADC_DATA2=0x00;      //ADC2数据清零
                                 count2=0x00;         //通道2转换次数清零
                        }
回复

使用道具 举报

10#
ID:401564 发表于 2022-2-11 16:38 | 只看该作者
你这代码怎么像是我当初学C语言时的代码?
给你一段我改过之后的代码
注释全在里面了,实际验证过的/*──────────────────────────────────────────────────────────────────────────────────Stc8a4k_Adc.c文件
编写:YGG
完成日期:20211120
功能:Stc8a系列单片机的ADC功能,采用中断方式进行ADC
完成状态:已经完成
──────────────────────────────────────────────────────────────────────────────────*/
#include "Stc8a.h"
#include "Stc8a_Adc.h"
#define         ADC_P10 0x80
#define         ADC_P11 0x81
#define         ADC_P12 0x82
#define         ADC_P13 0x83
#define         ADC_P14 0x84
#define         ADC_P15 0x85
#define         ADC_P16 0x86
#define         ADC_P17 0x87
#define         ADC_P1f 0x8f
#define     ADC_COUNT 32
//──────────────────────────────────────────────────────────────────────────────────────────────────
unsigned         char                  ADC_LINE;                                        //ADC通道记录
unsigned         int                 ADC_AN0;                                        //ADC0数据
unsigned          int                 ADC_AN1;                                        //ADC1数据        
//──────────────────────────────────────────────────────────────────────────────────────────────────
void Stc8a_Adc_Init()                                                                 //ADC初始化
{
        unsigned int i;
        P1M1|=0x03;                                                                                //p1.0和p1.1用作ADC端口
        ADC_CONTR=0x80;                                                                        //打开adc电源
        ADCCFG=0x2f;                                                                        //设定ADC转换结果保存格式,ADC时钟选择最慢       
        for(i=10000;i>0;i--);                                                         //延时一段时间
        ADC_CONTR=ADC_P10;                                                                //选择P1.f端口ADC
        ADC_LINE=ADC_P10;                                                                //默认启动的ADC通道
        ADC_CONTR|=0x40;                                                                //启动ADC
        EADC=1;                                                                                        //ADC中断允许
}
//─────────────────────────────────────────────────────────────────────────────────────────────
void ADC_ISR()interrupt 5                                                        //ADC中断处理
{               
        static unsigned char                          count0;                        //ADC通道6转换次数记录
        static unsigned char                          count1;                        //ADC通道f转换次数记录,内部参考电压通道
        static unsigned long int                 ADC_DATA0;                //ADC0数据,累加
        static unsigned long int                 ADC_DATA1;                //ADCf数据,累加       
        ADC_CONTR&=~0x20;                                                                //清除中断标志位
        //──────────────────────────────────────────────────────────────────────────
        if(ADC_LINE==ADC_P10)                                                          //检测触发ADC中断的通道
                {  
                        if(count0>=ADC_COUNT)                                         //检测ADC转换次数
                                {
                                         ADC_AN0=ADC_DATA0/ADC_COUNT;          //取平均值
                                         ADC_DATA0=0x00;                                          //清除ADC累加结果
                                         count0=0x00;                                          //清除ADC转换次数记录
                                }
                        ADC_DATA0+=ADC_RES*256+ADC_RESL;                //ADC结果累加
                        count0++;                          
                        ADC_CONTR=ADC_LINE=ADC_P11;                                //选择下一个ADC通道
                }
        //──────────────────────────────────────────────────────────────────────────
        else if(ADC_LINE==ADC_P11)
                {  
                        if(count1>=ADC_COUNT)
                                {
                                         ADC_AN1=ADC_DATA1/ADC_COUNT;
                                         ADC_DATA1=0x00;
                                         count1=0x00;
                                }
                        ADC_DATA1+=ADC_RES*256+ADC_RESL;       
                        count1++;                                                          
                        ADC_CONTR=ADC_LINE=ADC_P10;
                }
        //──────────────────────────────────────────────────────────────────────────                 
        ADC_CONTR|=0x40;                                                                //启动ADC
}
//─────────────────────────────────────────────────────────────────────────────────────────────

回复

使用道具 举报

11#
ID:686513 发表于 2022-2-12 20:52 | 只看该作者
Y_G_G 发表于 2022-2-11 16:38
你这代码怎么像是我当初学C语言时的代码?
给你一段我改过之后的代码
注释全在里面了,实际验证过的/*── ...

if(count0>=ADC_COUNT)                       //检测ADC转换次数             这样写转换次数不是没有限制了吗?后面为什么还是除32,不应该是 if(count0<ADC_COUNT) 吗?
回复

使用道具 举报

12#
ID:686513 发表于 2022-2-12 20:54 | 只看该作者

感觉这样是对的,但我把32改成50次或100次结果为什么不一样,相差很多!
回复

使用道具 举报

13#
ID:401564 发表于 2022-2-12 23:13 | 只看该作者
zhth1979 发表于 2022-2-12 20:52
if(count0>=ADC_COUNT)                       //检测ADC转换次数             这样写转换次数不是没有 ...

不是有这句吗?
count1=0x00;
/32是因为这是累加32次的结果,想要真实的数字量,就要/32
代码是肯定没有问题的,实际在STC8A4K单片机上运行过的
回复

使用道具 举报

14#
ID:879809 发表于 2022-2-13 22:32 | 只看该作者
不对啊,count0没到32就被清零了。
回复

使用道具 举报

15#
ID:807651 发表于 2022-2-14 11:56 | 只看该作者
zhth1979 发表于 2022-2-12 20:54
感觉这样是对的,但我把32改成50次或100次结果为什么不一样,相差很多!

                        if(count2<32)            //如果通道2转换次数小于32
                        {
                                 ADC_DATA2=0x00;      //ADC2数据清零
                                 count2=0x00;         //通道2转换次数清零
                        }
                       之前没注意看  代码这 转换次数count2 是不是要 count2 > 32   不是累加 次数吗 ?
                       还是你的 count2初始值时32想要累减的。
                       if(count2>32)            //如果通道2转换次数大于32
                        {
                                 ADC_DATA2=0x00;      //ADC2数据清零
                                 count2=0x00;         //通道2转换次数清零
                        }
                        不然  count2 , ADC_DATA2 一直清零。
                        然后你的AD值获取在清零后面,所以你改32 50 100得到不一样的值,实际可能只是获取一次ad值。
回复

使用道具 举报

16#
ID:686513 发表于 2022-3-4 08:53 | 只看该作者
Y_G_G 发表于 2022-2-12 23:13
不是有这句吗?
count1=0x00;
/32是因为这是累加32次的结果,想要真实的数字量,就要/32

查了一下,这个程序就是仿您的,您之前的程序是if(count0<32) 而后面却也是 count0++;   现在这个程序是  if(count0>=ADC_COUNT) 也是 count0++;  两者都能获得ADC值,前者稳定,但它却不能随传感器的变化而变化,后者可以,但值会跳动。是不是平均滤波不行?您能不能在后者的基础上帮我改写成中位置滤波?
回复

使用道具 举报

17#
ID:401564 发表于 2022-3-4 17:12 | 只看该作者
zhth1979 发表于 2022-3-4 08:53
查了一下,这个程序就是仿您的,您之前的程序是if(count0=ADC_COUNT) 也是 count0++;  两者都能获得ADC值 ...

前面的是我刚学C语言的时候写的,没有认真的验证过,也不知道有没有不对的地方
后面10#的是我验证过的,肯定是对的了
至于跳动是肯定会有的,不管用什么滤波方式,都会跳动的,我之前就是用的中位滤波,后来发现没什么效果,就改为平均滤波了
回复

使用道具 举报

18#
ID:488334 发表于 2022-3-4 18:46 | 只看该作者
if(count1<32)                                                                      //如果通道1转换次数小于32
{
      ADC_DATA1=0x00;                                                         //ADC1数据清零
      count1=0x00;                                                                //通道1转换次数清零
}
ADC_DATA1=ADC_DATA1+(ADC_RES*256+ADC_RESL);        //ADC结果处理
count1++;                                                                         //通道1转换次数加1
ADC_LINE=0x82;                                                                 //切换下一通道(通道2)
ADC_CONTR=ADC_LINE;                                                      //下一通道值赋给配置寄存器

这个三个一样功能的代码的条件是不是有问题呢,count1<32条件每次进来判断都是对的,count1计数和AD采集值都清零了。
count1<32这个条件如果要取平均值应该是反过来:count1>=32,当条件成立,就在if里面进行平均取值,和其他处理。

一般来说AD取值都是用平均值的,AD跳动不管哪个芯片都会有,比如近几年来很火的芯海科技,我用过他的芯片,有时候还不如国产的AD芯片(有时候误差在0.1V左右,不过我想误差缩减到0.05V左右,就采用了其他的芯片),只是看人的接受范围,误差在0.1V内一般都是默认可以接受的。
回复

使用道具 举报

19#
ID:686513 发表于 2022-4-29 14:45 | 只看该作者

你说的对,已经改过来了,现在正常了!
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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