久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 22879|回復: 35
收起左側

51單片機入門經驗分享7-更加實用的ADC轉換程序

  [復制鏈接]
ID:74187 發表于 2018-10-13 09:22 | 顯示全部樓層 |閱讀模式
                              更加實用的ADC轉換程序


    來接著繼續分享單片機的一些學習經歷,上一次,我們寫了一個測試電壓的程序,但是這樣的程序是不實用的,所以我們這一節,來介紹個比較實用的程序,還是測電池電壓,然后我們解釋一下這個代碼,這一節狠狠狠重要。。。
     先把代碼獻上,然后我們再來分析
  1. /*******************************************************************************
  2. * 文件名: ADC轉換器使用
  3. * 描  述: 電池電壓
  4. * 功  能:中斷方式
  5. * 作  者:大核桃
  6. * 版本號:1.0.1(2017.05.23)
  7. *******************************************************************************/
  8. #include "stc15w.h"//頭文件
  9. #include "intrins.h"



  10. /*******************************************************************************
  11. * 文件名: 重定義
  12. * 描  述:   
  13. * 功  能:
  14. * 作  者:大核桃
  15. * 版本號:1.0.1(2017.05.23)
  16. *******************************************************************************/
  17. typedef unsigned char uint8;
  18. typedef unsigned int  uint16;
  19. typedef unsigned long uint32;

  20. #define ADC_POWER   0x80            //ADC電源控制位
  21. #define ADC_FLAG    0x10            //ADC完成標志
  22. #define ADC_START   0x08            //ADC起始控制位
  23. #define ADC_SPEEDLL 0x00            //540個時鐘
  24. //#define ADC_SPEEDL  0x20            //360個時鐘
  25. //#define ADC_SPEEDH  0x40            //180個時鐘
  26. //#define ADC_SPEEDHH 0x60            //90個時鐘

  27. /*******************************************************************************
  28. * 文件名:全局變量定義區域
  29. * 描  述:
  30. * 功  能:
  31. * 作  者:大核桃
  32. * 版本號:1.0.1(2015.03.03)
  33. *******************************************************************************/
  34. uint8 val,ch;
  35. uint16 temp;
  36. bit flag_ad2 = 0;//電壓采集完成標志
  37. bit flag_coll1 = 0;//數據采集間隔
  38. uint16 Adresult_val = 0;//采集的AD數值xx
  39. uint8 ad_count = 0; //采集AD的次數計數器

  40. /*******************************************************************************
  41. * 文件名:共陽數碼管真值表
  42. * 描  述:
  43. * 功  能:
  44. * 作  者:大核桃
  45. * 版本號:1.0.1(2015.03.03)
  46. *******************************************************************************/
  47. code uint8 LedChar[] = {
  48.         0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
  49.         0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0xff,0xc1
  50. };

  51. /*******************************************************************************
  52. * 文件名:單獨位定義
  53. * 描  述:   
  54. * 功  能:
  55. * 作  者:大核桃
  56. * 版本號:1.0.1(2017.05.23)
  57. *******************************************************************************/
  58. sbit LED0 = P1^0;//第1組LED
  59. sbit LED1 = P1^1;//第2組LED
  60. sbit LED2 = P1^2;//第3組LED                                 
  61. sbit LED3 = P1^3;//第4組LED
  62. sbit LED4 = P1^4;//第5組LED
  63. sbit LED5 = P3^2;//第6組LED
  64. sbit LED6 = P0^0;//第7組LED
  65. sbit LED7 = P0^1;//第8組LED

  66. sbit LEDS1 = P3^3;//數碼管1
  67. sbit LEDS2 = P3^4;//數碼管2
  68. sbit LEDS3 = P3^6;//數碼管3
  69. sbit LEDS4 = P3^7;//數碼管4

  70. /*******************************************************************************
  71. * 文件名:函數前置聲明
  72. * 描  述:   
  73. * 功  能:
  74. * 作  者:大核桃
  75. * 版本號:1.0.1(2017.05.23)
  76. *******************************************************************************/
  77. void Mcu_Port_Init();
  78. void LedScan();
  79. void Time0_Init();//定時器0
  80. void InitADC(void);
  81. uint16 VolTage_Monitor(uint8 times); //AD轉換與查表處理程序

  82. /*******************************************************************************
  83. * 文件名
  84. * 描  述: 主函數  
  85. * 功  能:入口
  86. * 作  者:大核桃
  87. * 版本號:1.0.1(2017.05.23)
  88. *******************************************************************************/
  89. void main(void)
  90. {                                       
  91.         Mcu_Port_Init();//IO上電初始化
  92.         Time0_Init();
  93.         InitADC();

  94.         while(1)
  95.         {
  96.                 VolTage_Monitor(16);//采集16次數據
  97.         }
  98. }

  99. /*******************************************************************************
  100. * 文件名:void LedScan()
  101. * 描  述: LED刷新
  102. * 功  能:
  103. * 作  者:大核桃
  104. * 版本號:1.0.1(2017.05.23)
  105. *******************************************************************************/
  106. void LedScan()
  107. {
  108.         static uint8 i = 0;

  109.         P2 = 0Xff;
  110.         switch(i)
  111.         {
  112.                 case 0: LEDS4 = 0;LEDS1 = 1;P2 = 0x7f & LedChar[16];i++;break;
  113.                 case 1: LEDS1 = 0;LEDS2 = 1;P2 = LedChar[val / 10 % 10];i++;break;
  114.                 case 2: LEDS2 = 0;LEDS3 = 1;P2 = LedChar[val % 10];i++;break;
  115.                 case 3: LEDS3 = 0;LEDS4 = 1;P2 = LedChar[17];i = 0;break;

  116.                 default:break;
  117.         }
  118. }

  119. /*******************************************************************************
  120. * 文件名:void InitADC(void)
  121. * 描  述: //初始化 AD 轉換
  122. * 功  能:
  123. * 作  者:大核桃
  124. * 版本號:1.0.1(2015.03.03)
  125. *******************************************************************************/
  126. void InitADC(void)
  127. {
  128.         P1ASF = 0xE0; //設置 P1 口為模擬口
  129.         ADC_RES = 0; //清除結果寄存器
  130.         CLK_DIV |= 0x20; //ADRJ 為 1,ADC_RES 存放高兩位結果,ADC_RESL 存放低 8 位結果
  131.     //ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START;
  132.         ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START;                    //ADC上電并延時
  133. }

  134. /*******************************************************************************
  135. * 文件名:void adc_isr() interrupt 5 using 1
  136. * 描  述: 中斷服務程序
  137. * 功  能:
  138. * 作  者:大核桃
  139. * 版本號:1.0.1(2015.03.03)
  140. *******************************************************************************/
  141. void adc_isr() interrupt 5 using 1
  142. {
  143.         EADC = 1;//開ADC中斷

  144.         ADC_CONTR &= !ADC_FLAG; //清除ADC中斷標志
  145.         temp = ADC_RES;
  146.         temp <<= 8;
  147.         temp |= ADC_RESL;
  148.         flag_ad2 = 1; //電壓采集完成標志
  149.         ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | 5;

  150.         EADC = 0;//關閉中斷               

  151. }

  152. /*******************************************************************************
  153. * 文件名:VolTage_Monitor(void);
  154. * 描  述: 電壓結果計算
  155. * 功  能:模編程塊化
  156. * 作  者:大核桃
  157. * 版本號:1.0.1(2015.03.03)
  158. *******************************************************************************/
  159. uint16 VolTage_Monitor(uint8 times) //AD轉換與查表處理程序
  160. {
  161.    if(flag_coll1) //每次采集AD的時間間隔標志位
  162.    {
  163.                 if(ad_count < times)//連續采集16次后再把求總數據的平均值
  164.                 {
  165.                         if(flag_ad2 == 1)   //完成一次AD采樣
  166.                         {
  167.                                 flag_ad2 = 0;  //清除完成一次采樣的標志位

  168.                                 Adresult_val = Adresult_val + temp;
  169.                                 ad_count++;
  170.                                 ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START | 5;
  171.                         }
  172.                 } //右移動一位數據就相當于整除以2
  173.                 else  //已經采集完16次數據,這個時候把總累加數據除以16就可以求得平均值了
  174.                 {
  175.                         Adresult_val >>= 4;
  176.                         val = ((Adresult_val) * 2 * (3.3 / 1023) * 10);//放大10
  177.                         Adresult_val = 0; //AD暫存清零
  178.                         temp = 0;        //把采集AD的結果清零
  179.                         ad_count = 0;     //把采集次數重新清零
  180.                 }
  181.    }

  182.    return  val;//返回采集的電壓數值
  183. }

  184. /*******************************************************************************
  185. * 文件名:void Time0_Init()
  186. * 描  述: 定時器0初始化
  187. * 功  能:1毫秒@11.0592MHz
  188. * 作  者:大核桃
  189. * 版本號:1.0.1(2017.05.23)
  190. *******************************************************************************/
  191. void Time0_Init(void)
  192. {
  193.         AUXR |= 0x80;   //定時器時鐘1T模式
  194.         TMOD &= 0xF0;        //設置定時器模式
  195.         TL0 = 0xCD;                //設置定時初值
  196.         TH0 = 0xD4;                //設置定時初值
  197.         ET0 = 1;
  198.         TR0 = 1;                //定時器0開始計時
  199.         EA = 1;               
  200. }
  201. /*******************************************************************************
  202. * 文件名:
  203. * 描  述: 中斷函數
  204. * 功  能:1毫秒@11.0592MHz
  205. * 作  者:大核桃
  206. * 版本號:1.0.1(2017.05.23)
  207. *******************************************************************************/
  208. void ET0_IRQHandler() interrupt 1
  209. {
  210.         static uint8 tmrcoll1 = 0;//數據采集間隔

  211.         EADC = 0;  //在定時中斷中禁止AD中斷

  212.     TL0 = 0xCD;                //設置定時初值
  213.         TH0 = 0xD4;                //設置定時初值

  214.         tmrcoll1++;//數據采集時間累加
  215.         if(tmrcoll1 >= 2) // 2 = 2ms                                                                                                                                                                           //1
  216.         {
  217.             tmrcoll1 = 0;
  218.                 flag_coll1 = 1;//數據采集間隔標志位 2ms讀取一次數據
  219.         }

  220.         LedScan();

  221.         EADC = 1;  //在定時中斷中打開AD中斷
  222.                         
  223. }

  224. /*******************************************************************************
  225. * 文件名:void Mcu_Port_Init()
  226. * 描  述: io初始化
  227. * 功  能:
  228. * 作  者:大核桃
  229. * 版本號:1.0.1(2017.05.23)
  230. *******************************************************************************/
  231. void Mcu_Port_Init()
  232. {
  233.         IE = 0xa8;//允許AD轉換
  234.         //將P0口低二位配置為推挽輸出
  235.         //234567位配置位高阻輸入
  236.         P0M1 = 0xFC;//1111 1100
  237.         P0M0 = 0X03;//0000 0011
  238.         //P0 = 0X01;//第6個
  239.         //P0 = 0X02;//第7個
  240.         //高3位配置高阻輸入,用作模擬口
  241.         //其他配置推挽輸出,驅動LED
  242.         P1M1 = 0xE0;//1110 0000
  243.         P1M0 = 0X1F;//0001 1111
  244.         //P2口配置準雙向口
  245.         P2M1 = 0X00;
  246.         P2M0 = 0X00;
  247.         P2 = 0Xff; //上電為1111 1111


  248. //        //P54,P55口為推挽輸出
  249.         P5M1 = 0X00;
  250.         P5M0 = 0X00;
  251.         P5 = 0xFF;

  252.         //P37,P36,3.2,P3.3 P3.4口為推挽輸出
  253.         P3M1 = 0X00;
  254.         P3M0 = 0XFC;
  255.         P3 = 0X23; //0010 0111//第5個LED端口
  256.         
  257.         LED0 = 0;//第1組LED,如果使能請置為1
  258.         LED1 = 0;
  259.         LED2 = 0;
  260.         LED3 = 0;
  261.         LED4 = 0;
  262.         LED5 = 0;
  263.         LED6 = 0;
  264.         LED7 = 0;        
  265. }
復制代碼


先來介紹一些基本的理論知識,不然的話,可能有些東西無法搞懂。
     關于ADC的參考電壓
因為我們的電子時鐘是鋰電池供電的,電壓是3.7V的,我們這里用了一個3.3V的穩壓芯片662K,輸出3.3V直接作為單片機的電源,也作為ADC的參考電壓,這里我們簡化了設計,沒有用外部的參考電壓源,對于一個簡單的來說,這樣也是可以的。
     關于ADC的位數和分辨率
在這里,我們選擇ADC工作在10位方式,10位的ADC,是從0-1023,那么分辨率也就是3.3/1023 = 0.0032258064516129V,大概一個分辨率3mv左右。
     關于轉換時間和轉換速率
轉換時間和轉換速率是倒數的關系,所謂的轉換時間,指的是ADC從開始啟動,到ADC轉換完成出結果,這個時間該怎么去計算呢?我們在程序中選擇了時鐘頻率是11.0592MHZ,那么我們ADC的時鐘頻率也就是11.0592MHZ了,在程序中,我們選擇了540個時鐘周期完成一個ADC轉換,轉換速率也就是20KHZ左右,轉換時間大約是48US左右
    關于采樣頻率和采樣周期
采樣頻率和采樣周期也是互為倒數的關系,這個和上面的轉換時間,轉換速率非常容易讓人搞迷糊,關于采樣頻率,有一個采樣定理,叫奈奎斯特采樣定律,這個定律說的是,采樣頻率不能低于輸入ADC的信號的最高頻率的2倍,舉個例子,比如上面這樣的情況,我們選擇540個時鐘周期完成一次ADC轉換,那么轉換速率是20KHZ,那么也就是說,如果我們要保證信號采集的是完整的波形,那么這個輸入的信號不能超過10KHZ,你想想看,如果輸入的信號大于10KHZ,而你轉換速率是20KHZ,如果采樣頻率小于20KHZ,那么可能你還沒有完成一個完整的ADC轉換過程,或者采集的波形不是完整的,那么這樣的ADC的結果跟實際值比較會存在嚴重的失真,這樣是不被允許的。

   好了,經過以上知識的鋪墊,再來看程序代碼就應該比較容易懂了,在程序中,我們選擇了在ADC進中斷前打開EADC,處理完數據后,要關閉EADC這個ADC轉換中斷使能標志位,防止其他中斷或者任務打斷ADC的采集。我們在任務中選擇的采樣頻率是500HZ,也就是2MS啟動ADC采集依次數據,連續采集16次,因為我們所采集的電壓信號的變化頻率沒有那么快速,所以,我們這里是可以這樣用的,當啟動了一次AD轉換之后,進行計數,如果小于16次,那么一直在IF里面執行,當系統檢測到完成一個AD轉換,將AD轉換完成標志位清零,將讀取的相關通道的ADC數值累加,繼續采集,如果采集完成了,那么進行取平均運算,然后將結果計算出來,賦值給相關的變量就可以了,然后對相關的變量或者緩沖區清零,這樣,顯示在數碼管上的電壓結果是比較穩定的。和前面那個例子不一樣,我們這個例子用的是STC15W單片機定時器0的1T模式,也就是說比原來快了12倍,這個移植的時候一定要注意。
   好了,今天就到這里吧,源碼奉獻上。
007 實用的AD轉換器的使用.rar (50.8 KB, 下載次數: 259)



     



評分

參與人數 1黑幣 +3 收起 理由
tab001 + 3

查看全部評分

回復

使用道具 舉報

ID:413430 發表于 2018-10-22 14:14 | 顯示全部樓層
感謝分享
回復

使用道具 舉報

ID:416567 發表于 2018-10-28 09:27 | 顯示全部樓層
感謝分享............
回復

使用道具 舉報

ID:284702 發表于 2018-11-10 23:55 | 顯示全部樓層
感謝分享............
回復

使用道具 舉報

ID:427566 發表于 2018-11-16 10:19 | 顯示全部樓層
謝謝大佬
回復

使用道具 舉報

ID:426444 發表于 2018-11-20 15:30 來自手機 | 顯示全部樓層
感謝,能派上用場了
回復

使用道具 舉報

ID:434952 發表于 2018-11-28 16:49 | 顯示全部樓層
感謝分享
回復

使用道具 舉報

ID:116662 發表于 2018-11-28 22:06 | 顯示全部樓層
多謝師傅知識分享,公開者大公無私,贊一個
回復

使用道具 舉報

ID:435900 發表于 2018-11-29 17:17 | 顯示全部樓層
樓主,val = ((Adresult_val) * 2 * (3.3 / 1023) * 10);//放大10 這里為什么要*2呢
回復

使用道具 舉報

ID:417062 發表于 2018-12-10 08:10 | 顯示全部樓層
厲害了額 小學生這么難的
回復

使用道具 舉報

ID:76133 發表于 2018-12-24 16:01 | 顯示全部樓層
感謝分享
回復

使用道具 舉報

ID:393577 發表于 2018-12-28 09:46 | 顯示全部樓層
仗義 發表于 2018-12-10 08:10
厲害了額 小學生這么難的

誰讓我們是從幼兒園畢業200多月的寶寶呢
回復

使用道具 舉報

ID:461280 發表于 2019-1-3 20:10 | 顯示全部樓層
厲害厲害
回復

使用道具 舉報

ID:461889 發表于 2019-1-23 10:13 | 顯示全部樓層

感謝分享
回復

使用道具 舉報

ID:477934 發表于 2019-2-20 17:25 | 顯示全部樓層
有一點用,先下了
回復

使用道具 舉報

ID:485529 發表于 2019-3-6 13:46 | 顯示全部樓層
MARK,多謝樓主分享
回復

使用道具 舉報

ID:524764 發表于 2019-5-10 15:39 | 顯示全部樓層
感謝,謝謝分享
回復

使用道具 舉報

ID:404572 發表于 2019-8-22 12:52 | 顯示全部樓層
感謝分享
回復

使用道具 舉報

ID:613800 發表于 2019-10-8 22:59 | 顯示全部樓層
感謝。分享。
回復

使用道具 舉報

ID:76612 發表于 2019-11-15 10:53 | 顯示全部樓層
感謝分享
回復

使用道具 舉報

ID:626079 發表于 2019-11-22 16:59 | 顯示全部樓層

感謝分享
回復

使用道具 舉報

ID:646449 發表于 2019-12-5 09:16 | 顯示全部樓層
哭了,這帖子太好了
回復

使用道具 舉報

ID:610633 發表于 2020-2-17 15:55 | 顯示全部樓層
為什么放大10呢?
回復

使用道具 舉報

ID:294865 發表于 2020-2-27 15:49 | 顯示全部樓層
這個注示寫的太好了,條理清楚。不懂的人都很容易看懂。
回復

使用道具 舉報

ID:727207 發表于 2020-4-11 22:00 | 顯示全部樓層

感謝分享.感謝分享.
回復

使用道具 舉報

ID:736629 發表于 2020-4-24 00:32 | 顯示全部樓層
謝謝樓主分享。。。。。。
回復

使用道具 舉報

ID:305511 發表于 2020-5-14 15:56 | 顯示全部樓層
非常感謝分享!
回復

使用道具 舉報

ID:747667 發表于 2020-5-20 10:57 來自手機 | 顯示全部樓層
謝謝分享
回復

使用道具 舉報

ID:805324 發表于 2020-7-19 10:05 來自手機 | 顯示全部樓層
LowHuang 發表于 2018-11-29 17:17
樓主,val = ((Adresult_val) * 2 * (3.3 / 1023) * 10);//放大10 這里為什么要*2呢

應該是外圍分壓比
回復

使用道具 舉報

ID:822728 發表于 2020-9-24 15:21 來自手機 | 顯示全部樓層
我想知道怎么接線
回復

使用道具 舉報

ID:824534 發表于 2020-9-29 11:14 | 顯示全部樓層
如果有多個ADC,進行采集,是否進行I/o口切換,還是并行操作
回復

使用道具 舉報

ID:356562 發表于 2021-2-12 08:29 | 顯示全部樓層
正在學習STC芯片的AD,很好的資料。
回復

使用道具 舉報

ID:46228 發表于 2021-4-29 22:55 來自手機 | 顯示全部樓層
現在才接觸adc,做電陶爐熱電偶+lm358,溫度達到500度,關閉繼電器這樣的工程,遺憾的是,能力有限,這么長時間了,還是實現不了,真是絕望啊
回復

使用道具 舉報

ID:976070 發表于 2021-11-17 21:57 | 顯示全部樓層
正在學習AD轉換,很好資料。
回復

使用道具 舉報

ID:1049825 發表于 2022-10-31 18:52 | 顯示全部樓層
你他娘的是個天才,還能與大家分享,贊一個.
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产一区二区三区四区五区3d | 国产精品18久久久久久久 | 黄色三级在线播放 | 国产成人在线视频 | 亚洲一区二区三 | 色欧美日韩 | 欧美综合一区二区三区 | 亚洲视频网 | 影音先锋中文字幕在线观看 | av中文在线 | 欧美一级www片免费观看 | 亚洲欧美日韩精品久久亚洲区 | 99久久免费精品视频 | 欧洲成人 | 玖玖操 | 一区二区三区四区国产精品 | 亚洲小说图片 | 色婷婷综合久久久中文字幕 | 精品国产乱码久久久久久影片 | 亚洲免费影院 | 欧美男人天堂 | 久久久无码精品亚洲日韩按摩 | 日韩av资源站 | 国产农村妇女毛片精品久久麻豆 | 91精品久久久久久久 | 午夜视频在线视频 | 成人在线一区二区 | 欧美一区二区三区在线 | 在线观看视频你懂得 | 成人在线 | 一区二区三区在线免费观看 | 国产福利小视频 | 激情国产 | 四虎成人在线播放 | 亚洲国产一区在线 | 颜色网站在线观看 | 国产天天操| av喷水 | 亚洲aⅴ | 国产欧美一区二区精品久导航 | 国产四区 |