找回密码
 立即注册

QQ登录

只需一步,快速开始

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

关于atmega16单片机AD换路问题(新手求教)

[复制链接]
跳转到指定楼层
楼主
atmega16单片机如何判断adch是否被读出呢 ? 通过换路读取了两个值
void get_information(void)///获取ADC信息
{
  unsigned char i=0;

  DDRA=0x00;
  PORTA=0x00;

  for(i=0;i<2;i++)      //读取两路路adc
  {
      init_adc(i); //换路初始化
      while(1)
       {
            if(ADCSRA&(1<<4))//判断是否转换完成
            {
                adcinit[i]=ADCH; //adc暂寄存数
                adc[i]=datapro(adcinit[i],i); //将adc转化后的结果存入数组
                break;
            }

       }
  }

  DDRA=0x00;
  PORTA=0x00;

}

但是结果是adc[0]和adc[1]里面的值是一样的,是不是没有对adch判断是否被读出所导致的呢
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:484435 发表于 2019-5-7 17:57 | 只看该作者
谢谢分享
回复

使用道具 举报

板凳
ID:176854 发表于 2019-5-8 10:21 | 只看该作者
if(ADCSRA&(1<<4))//判断是否转换完成
            {
                ADCSRA &=~(1<<4);
                adcinit[i]=ADCH; //adc暂寄存数
                adc[i]=datapro(adcinit[i],i); //将adc转化后的结果存入数组
                break;
            }

每次读完将中断标志位清零
回复

使用道具 举报

地板
ID:511864 发表于 2019-5-8 23:45 | 只看该作者

非常感谢您的回答,但是问题依然和以前一样
  1.   for(i=0;i<2;i++)      //读取两路路adc
  2.   {
  3.       init_adc(i);
  4.       while(1)
  5.        {
  6.             if(ADCSRA&(1<<4))//判断是否转换完成
  7.             {
  8.                 adcinit[i]=ADCH;
  9.                 adc[i]=datapro(adcinit[i],i);
  10.                 break;
  11.             }

  12.        }
  13.        ADCSRA |= (1<<4);
  14.   }
复制代码

这是我按照您的意思修改的函数,请问下是不是AD采样存在时钟周期所导致的换路后的第一个值要舍弃呢(不知道该怎么舍弃,是读完ADCH后数据才会更新吗)另外这是我的初始化函数,选择的是连续转换模式,自动触发使能等
  1.   void init_adc(int n)
  2. {
  3.     DDRA   &=~ ((1<<0)|(1<<1));      //模拟量输入管脚PA1设置为输入
  4.     ADMUX  |=  (1<<6)|(1<<n);      //参考电压选择AVCC  PA15
  5.     ADCSRA |=  (1<<7)|(1<<5)|(1<<2)|(1<<1) ; //自动触发使能, 64分频,ADC使能
  6.     SFIOR  &=~ ((1<<2)|(1<<1)|(1<<0));
  7.     ADCSRA |=  (1<<6) ; //开始转换

  8. }
复制代码

因为第一次接触有很多不懂,还请不吝赐教,谢谢!
回复

使用道具 举报

5#
ID:176854 发表于 2019-5-9 09:14 | 只看该作者
手册上说切换到差分增益通道或参考源改变后  ,才舍弃第一次转换结果,转换通道应该不需要舍弃(不知道我是否看漏)。还有你现在并不是转换结果左对齐 所以要先读 ADCL,再读 ADCH 。
建议将 while(1) break;去除,意义不明。



QQ截图20190509085901.png (150.68 KB, 下载次数: 20)

QQ截图20190509085901.png

QQ截图20190509090828.png (82.97 KB, 下载次数: 26)

QQ截图20190509090828.png
回复

使用道具 举报

6#
ID:176854 发表于 2019-5-9 09:33 | 只看该作者
void init_adc(int n)
{
    DDRA   &=~ ((1<<0)|(1<<1));      //模拟量输入管脚PA1设置为输入
    ADMUX  |=  (1<<6)|(
1<<5)|(1<<n);      //参考电压选择AVCC  PA15 ,转换结果左对齐,精度只有8位,请注意!!!!!
    ADCSRA |=  (1<<7)|(1<<5)|(1<<2)|(1<<1) ; //自动触发使能, 64分频,ADC使能
    SFIOR  &=~ ((1<<2)|(1<<1)|(1<<0));
    ADCSRA |=  (1<<6) ; //开始转换

}



void get_information(void)///获取ADC信息
{
  unsigned char i=0,a=0;
  DDRA=0x00;
  PORTA=0x00;

  for(i=0;i<2;i++)      //读取两路路adc
  {
      init_adc(i); //换路初始化
      while((ADCSRA&(1<< 6)));//判断是否转换完成
      adcinit[ i]=ADCH; //adc暂寄存数
      adc[ i]=datapro(adcinit,i); //将adc转化后的结果存入数组
      nop();nop();nop();nop();nop();//
nop();nop();nop();nop();nop();//在 ADSC 置位后的一个 ADC时钟周期就可以选择新的模拟输入通道了
   }

  DDRA=0x00;
  PORTA=0x00;

}


凭经验该的,你试试看吧,红色的就是我做了修改
回复

使用道具 举报

7#
ID:176854 发表于 2019-5-9 09:42 | 只看该作者
我改的不保证能运行,有问题的话再改改看
回复

使用道具 举报

8#
ID:511864 发表于 2019-5-10 00:26 | 只看该作者
jjjjjjir 发表于 2019-5-9 09:42
我改的不保证能运行,有问题的话再改改看

感谢大佬的点拨!但是弄了几个小时问题依然存在,数据显示出现了其他问题,我看技术手册中说的最后一句话的意思是不是要舍弃储存的第一个值呢,或者是什么其他的意思?
ADC 输入通道 选择模拟通道时请注意以下指导方针:
在连续转换模式下,总是在第一次转换开始之前选定通道。在 ADSC 置位后的一个 ADC
时钟周期就可以选择新的模拟输入通道了。但是最简单的办法是等待转换结束后再改变
通道。然而,此时新一次转换已经自动开始了,下一次的转换结果反映的是以前选定的模
拟输入通道。以后的转换才是针对新通道的。
  1.   void init_adc(int n)
  2. {
  3.     DDRA   &=~ ((1<<0)|(1<<1));      //模拟量输入管脚PA1设置为输入
  4.     ADMUX  |=  (1<<6)|(1<<n);      //参考电压选择AVCC  PA15
  5.     ADCSRA |=  (1<<7)|(1<<5)|(1<<2)|(1<<1) ; //自动触发使能, 64分频,ADC使能
  6.     SFIOR  &=~ ((1<<2)|(1<<1)|(1<<0));
  7.     ADCSRA |=  (1<<6) ; //开始转换

  8. }

  9. ///数据处理
  10. unsigned int datapro(volatile unsigned char m)
  11. {
  12.         a=5*m/1024.0;
  13.         Vin=a*1000;
  14.         return Vin;
  15. }

  16. void get_information(void)
  17. {
  18.   unsigned char i=0;

  19.   DDRA=0x00;
  20.   PORTA=0x00;

  21.   for(i=0;i<2;i++)      //读取两路路adc
  22.   {
  23.       init_adc(i);
  24.       while(1)
  25.        {
  26.             if(ADCSRA&(1<<4))//判断是否转换完成
  27.             {
  28.                 adcinit[i]= ADCL | ADCH << 8;
  29.                 adc[i]=datapro(adcinit[i]);
  30.                 break;
  31.             }

  32.        }
  33. //       nop();nop();nop();nop();nop();
  34. //       nop();nop();nop();nop();nop();//在 ADSC 置位后的一个 ADC时钟周期就可以选择新的模拟输入通道了
  35.   }

  36.   DDRA=0x00;
  37.   PORTA=0x00;

  38. }

  39.   void main(void)
  40. {
  41.       HC595_init();
  42.     while(1)
  43.     {
  44.             get_information();
  45.             adc_tube_show(adc[0],adc[1]);
  46.     }
  47. }
复制代码
结果是目前数码管显示是AD采集的第一个数字而且固定不变了,并且数码管上显示的两个数字还是相同的,实在找不到问题出在哪了(另外那个while(1)break;作用应该是和while(ADCSRA&(1<<6));一样的吧)请大佬赐教,感谢!

回复

使用道具 举报

9#
ID:176854 发表于 2019-5-10 17:28 | 只看该作者
我这是菜鸟,不是大佬。
附上参考资料http://www.51hei.com/bbs/dpj-34695-1.html  

void init_adc(int n)
{
    DDRA   &=~ ((1<<0)|(1<<1));      //模拟量输入管脚PA1设置为输入
    ADMUX  |=  (1<<6)|(1<<n);      //参考电压选择AVCC  PA15
    ADCSRA |=  (1<<7)|(1<<5)|(1<<2)|(1<<1) ; //自动触发使能, 64分频,ADC使能
    SFIOR  &=~ ((1<<2)|(1<<1)|(1<<0));
    ADCSRA |=  (1<<6) ; //开始转换

}

///数据处理
unsigned int datapro(volatile unsigned int m)
{
        a=5*m/1024.0;
        Vin=a*1000;
        return Vin;
}

void get_information(void)
{
  unsigned char temp1,temp2;
  unsigned char i=0;

  DDRA=0x00;
  PORTA=0x00;

  for(i=0;i<2;i++)      //读取两路路adc
  {
      init_adc(i);
      while(1)
       {
            if(ADCSRA&(1<<4))//判断是否转换完成
            {
                ADCSRA &=~(1<<4);//建议还要将中断标志位清零,根据手册进入中断是会硬件清单,但是没有进入中断的话最好软件清零
                temp1 = ADCH;
                temp2 = ADCL;
                adcinit[ i]= temp2 | temp1 << 8; //adcinit[ i]这个数字必须定义为unsigned int[ i]
                adc[ ]=datapro(adcinit[ i]);
                break;
            }

       }
//       nop();nop();nop();nop();nop();
//       nop();nop();nop();nop();nop();//在 ADSC 置位后的一个 ADC时钟周期就可以选择新的模拟输入通道了
  }

  DDRA=0x00;
  PORTA=0x00;

}

  void main(void)
{
      HC595_init();
    while(1)
    {
            get_information();
            adc_tube_show(adc[0],adc[1]);
    }
}

回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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