找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1941|回復: 8
打印 上一主題 下一主題
收起左側

關于atmega16單片機AD換路問題(新手求教)

[復制鏈接]
跳轉到指定樓層
樓主
ID:511864 發(fā)表于 2019-5-7 16:04 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
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空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復

使用道具 舉報

沙發(fā)
ID:484435 發(fā)表于 2019-5-7 17:57 | 只看該作者
謝謝分享
回復

使用道具 舉報

板凳
ID:176854 發(fā)表于 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 發(fā)表于 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后數據才會更新嗎)另外這是我的初始化函數,選擇的是連續(xù)轉換模式,自動觸發(fā)使能等
  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) ; //自動觸發(fā)使能, 64分頻,ADC使能
  6.     SFIOR  &=~ ((1<<2)|(1<<1)|(1<<0));
  7.     ADCSRA |=  (1<<6) ; //開始轉換

  8. }
復制代碼

因為第一次接觸有很多不懂,還請不吝賜教,謝謝!
回復

使用道具 舉報

5#
ID:176854 發(fā)表于 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, 下載次數: 27)

QQ截圖20190509090828.png
回復

使用道具 舉報

6#
ID:176854 發(fā)表于 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) ; //自動觸發(fā)使能, 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 發(fā)表于 2019-5-9 09:42 | 只看該作者
我改的不保證能運行,有問題的話再改改看
回復

使用道具 舉報

8#
ID:511864 發(fā)表于 2019-5-10 00:26 | 只看該作者
jjjjjjir 發(fā)表于 2019-5-9 09:42
我改的不保證能運行,有問題的話再改改看

感謝大佬的點撥!但是弄了幾個小時問題依然存在,數據顯示出現了其他問題,我看技術手冊中說的最后一句話的意思是不是要舍棄儲存的第一個值呢,或者是什么其他的意思?
ADC 輸入通道 選擇模擬通道時請注意以下指導方針:
在連續(xù)轉換模式下,總是在第一次轉換開始之前選定通道。在 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) ; //自動觸發(fā)使能, 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 發(fā)表于 2019-5-10 17:28 | 只看該作者
我這是菜鳥,不是大佬。
附上參考資料http://www.torrancerestoration.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) ; //自動觸發(fā)使能, 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]);
    }
}

回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表