找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1212|回复: 6
收起左侧

单片机ADC多路转换程序调试又不会了,请大伙帮忙指点

[复制链接]
ID:686513 发表于 2022-8-31 15:23 | 显示全部楼层 |阅读模式
这个是一路的程序(中断方式),SGADCON 赋每一路的值都没有问题,现在我想三路轮流采集就不行了。
#include "adc.h"
bit ADready;   //24bit ADC转换完成标志位
unsigned long idata        ADcode_pre;

void ADC_24bit_InIt()  //24位ADC初始化
{
        EIE &= 0xfb;                        //关闭SG ADC 中断        
        
        SGADCON = 0xc2;                //1100 0010  开启ADC 正常工作 通道0 关闭64倍运放  输出速率 10HZ   通道1:0xd2   通道3:0xf2

        SGADCON2  = 0x41;                // 0100 0011 VCOM 输出电压控制位 输出1.5V

        SGADCON3X = 0x99;                //1001 1001  CCEN=1 1和2负输入不反  GCLK=8  ACLK=4  FCCH=1

        SGADCON4X = 0x30;                //0011 0000  不输出基准电流  开启内部BUF 开启BUF_LCAP属性 GREF不放大 关闭上下拉电流
        
        SGADCON5X = 0x31;                //0001 1101  滤波模式3  不丢弃

        PD_CON    = 0x66;                //0110 0110 解锁P1.1 1.2 锁定P4.2 P4.3仅为输入模式 解锁写权限 开启内部LDO 同步休眠 开启温度模块
               
        //EA = 1;                                        //打开总中断(总中断在main函数中打开)
        EIE |= 0x04;                        //打开SG ADC 中断        
}

void data_receive()                                //从寄存器中获取ADC内码
{
        union  ADpattern idata temp;
        //--ADcode_pre--赋值
        temp.b[1] = SGADC3;
        temp.b[2] = SGADC2;
        temp.b[3] = SGADC1;
        temp.b[0] = 0;                                //获取24位ADC数据内码
//        temp.w ^= 0x800000;                        // 因为输出为双极性,+0x800000将负端平移上来
        temp.w &= 0x00ffffff;                //对25-32位清零
        ADcode_pre = temp.w;
}

//内部 24bit SG ADC 中断,读取adc数据
static void sgadc_serve() interrupt 7
{               
        EIE &= 0xfb;                         //禁止中断
        data_receive(); //读取 SDI0818 的 转换数据
        ADready = 1;
        EXIF &= 0xbf;
        EIE |= 0x04;                 //打开中断
}

unsigned long Filter_ADdata()                //读取adc转换数据,对其进行适当的平滑、滤波。
{
        unsigned long d;
// -- 将 中断服务程序读取出的ADC原始信息 从 缓冲 Buffer 中取出  -----
        EIE &= 0xfb;        // 关闭adc中断,读取 ADC原始位信息 时 禁止 中断服务程序 改写
        d = ADcode_pre;
        ADready = 0;        // 表示 ADC数据已被 处理程序 响应
        EIE |= 0x04;        // 打开中断
        d >>= 2;                // 将ADC数据右移两位,简单滤波
        return d;
}

unsigned long Air_ADC_average()                                //气压传感器ADC通道
{
        unsigned long ADC_code = 0;
        unsigned char j;
        unsigned long  ADcode_filter_buff[10];        //用来求平均
        
        while(~ADready);                        //等待AD转换完成标志
        for(j=9;j>0;j--)
        {
                ADcode_filter_buff[j] = ADcode_filter_buff[j-1];
        }
        ADcode_filter_buff[0] =Filter_ADdata();        //获取最新ADC内码
        for(j=0;j<10;j++)
        {
                ADC_code += ADcode_filter_buff[j];   //10次ADC内码相加
        }
        ADC_code /= 10;                        //求平均
        return ADC_code;
}
下面是.H文件
#ifndef        __ADC_H_
#define        __ADC_H_
#include "SDI5229.h"
                                                                           
void ADC_24bit_InIt();
void data_receive();

unsigned long Filter_ADdata();
unsigned long Air_ADC_average();

union ADpattern                                //定义联合体,数据可以采用字节和字两种方式访问;
{
        unsigned long        w ;
        unsigned char   b[4];
};

#endif

----------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------
下面是我尝试用switch中切换通道,但没成功。
#include "adc.h"
float line0,line1,line2;                     //三通道结果
bit ADready;                                 //24bit ADC转换完成标志位
unsigned long idata        ADcode_pre;            


void ADC_Setchannel(unsigned char channel)
  {
          switch(channel)
            {
                 case 0:  SGADCON &= 0xc2;  break;
                case 1:  SGADCON &= 0xd2;  break;
                case 2:  SGADCON &= 0xf2;  break;
                default:break;
          }
  }

void ADC_24bit_InIt(unsigned char channel)  //24位ADC初始
{
        EIE &= 0xfb;                        //关闭SG ADC 中断        
        SGADCON &= 0xcf;                //清除ADC通道选择位      
        ADC_Setchannel(channel);   //用此函数代替选通道寄存器
        SGADCON2  = 0x41;                // 0100 0011 VCOM 输出电压控制位 输出1.5V
        SGADCON3X = 0x99;                //1001 1001  CCEN=1 1和2负输入不反  GCLK=8  ACLK=4  FCCH=1
        SGADCON4X = 0x30;                //0011 0000  不输出基准电流  开启内部BUF 开启BUF_LCAP属性 GREF不放大 关闭上下接电流   
        SGADCON5X = 0x31;                //0001 1101  滤波模式3  不丢弃
        PD_CON    = 0x66;                //0110 0110 解锁P1.1 1.2 锁定P4.2 P4.3仅为输入模式 解锁写权限 开启内部LDO 同步休眠 开启温度模块              
        //EA = 1;                                        //打开总中断 (main函数里打开)
        EIE |= 0x04;                        //打开SG ADC 中断        
}

void data_receive()                                //从寄存器中获取ADC内码
{
        union  ADpattern idata temp;
        //--ADcode_pre--赋值
        temp.b[1] = SGADC3;
        temp.b[2] = SGADC2;
        temp.b[3] = SGADC1;
        temp.b[0] = 0;                                //获取24位ADC数据内码
//        temp.w ^= 0x800000;                        // 因为输出为双极性,+0x800000将负端平移上来
        temp.w &= 0x00ffffff;                //对25-32位清零
        ADcode_pre = temp.w;
}


//内部 24bit SG ADC 中断,读取adc数据
static void sgadc_serve() interrupt 7
{               
        EIE &= 0xfb;                         //禁止中断
        data_receive(); //读取 SDI0818 的 转换数据
        ADready = 1;
        EXIF &= 0xbf;
        EIE |= 0x04;                 //打开中断
}


unsigned long Filter_ADdata()                //读取adc转换数据,对其进行适当的平滑、滤波。
{
        unsigned long d;
// -- 将 中断服务程序读取出的ADC原始信息 从 缓冲 Buffer 中取出  -----
        EIE &= 0xfb;        // 关闭adc中断,读取 ADC原始位信息 时 禁止 中断服务程序 改写
        d = ADcode_pre;
        ADready = 0;        // 表示 ADC数据已被 处理程序 响应
        EIE |= 0x04;        // 打开中断
        d >>= 2;                // 将ADC数据右移两位,简单滤波
        return d;
}
unsigned long Air_ADC_average()                                //气压传感器ADC通道

{
        unsigned long ADC_code = 0;
        unsigned char j;
        unsigned long  ADcode_filter_buff[10];        //用来求平均
        
        while(~ADready);                        //等待AD转换完成标志
        for(j=9;j>0;j--)
        {
                ADcode_filter_buff[j] = ADcode_filter_buff[j-1];
        }
        ADcode_filter_buff[0] =Filter_ADdata();        //获取最新ADC内码
        for(j=0;j<10;j++)
        {
                ADC_code += ADcode_filter_buff[j];   //10次ADC内码相加
        }
        ADC_code /= 10;                        //求平均
        return ADC_code;
}

void ADC_channel(unsigned char channel)

  {
                switch(channel)
                {
                        case 0: line0 = Air_ADC_average();  break;  //通道0结果
                        case 1: line1 = Air_ADC_average();  break;  //通道1结果
                        case 2: line2 = Air_ADC_average();  break;  //通道2结果
                        default:break;
                }
  }

这是adc.h文件
#ifndef        __ADC_H_
#define        __ADC_H_


#include "SDI5229.h"


extern float line0;
extern float line1;
extern float line2;
void ADC_channel(unsigned char channel);


void ADC_Setchannel(unsigned char channel);                                                                           
void ADC_24bit_InIt(unsigned char channel);
void data_receive();


unsigned long Filter_ADdata();
unsigned long Air_ADC_average();


union ADpattern                                //定义联合体,数据可以采用字节和字两种方式访问;
{
        unsigned long        w ;
        unsigned char   b[4];
};
#endif

main函数中调用
        while(1)
           {
                         if(ADCflag==1)      //定时1S标志位   1S切换一个通道
                         {
                         ADCflag=0;
                         ADC_24bit_InIt(channel);
                         ADC_channel(channel);
                         channel++;
                         if(channel>2)        
                                 channel=0;
                         }
                        
      ADCBat = line0;
1.png





回复

使用道具 举报

ID:123289 发表于 2022-8-31 17:28 | 显示全部楼层
建议:
1、每个通道编写一个程序。
2、将各个程序轮流执行。
回复

使用道具 举报

ID:146878 发表于 2022-8-31 23:24 | 显示全部楼层
  case 0:  SGADCON &= 0xc2;  break;
  case 1:  SGADCON &= 0xd2;  break;
  case 2:  SGADCON &= 0xf2;  break;
  改
  case 0:  SGADCON = 0xc2;  break;
  case 1:  SGADCON = 0xd2;  break;
  case 2:  SGADCON = 0xf2;  break;
回复

使用道具 举报

ID:686513 发表于 2022-9-1 07:56 | 显示全部楼层
pdwdzz 发表于 2022-8-31 23:24
case 0:  SGADCON &= 0xc2;  break;
  case 1:  SGADCON &= 0xd2;  break;
  case 2:  SGADCON &= 0xf2 ...

之前就是没有与,不行才改现在这样的,也是不行!
回复

使用道具 举报

ID:686513 发表于 2022-9-1 07:59 | 显示全部楼层
yzwzfyz 发表于 2022-8-31 17:28
建议:
1、每个通道编写一个程序。
2、将各个程序轮流执行。

那样的话,1.太繁琐不简洁  2.编译后data内存也会占用更多。
回复

使用道具 举报

ID:123289 发表于 2022-9-1 10:59 | 显示全部楼层
【那样的话,1.太繁琐不简洁  2.编译后data内存也会占用更多。】
不要以为这样很蠢。在你不会做的时间很有用,道理上说得通。
当你做了,就会知道它是如何蠢的,知道它蠢之后,你就进步了,离成功也就不远了。
回复

使用道具 举报

ID:401564 发表于 2022-9-1 23:53 | 显示全部楼层
zhth1979 发表于 2022-9-1 07:59
那样的话,1.太繁琐不简洁  2.编译后data内存也会占用更多。

如果不是你程序实在写不下了,目前的主要问题并不是代码占用空间大的问题
首先要保证代码能不能正确执行,这才是关键
这个片子有30K的内存,个人感觉,超过30K的8位机程序并不是很多
等到功能正常了,再想办法精简代码
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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