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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

單片機AD轉換 PCF8591數顯電壓表代碼Proteus仿真原理圖

[復制鏈接]
跳轉到指定樓層
樓主
以單片機為核心器件,組成一個簡單數字電壓表。
(1)采用1路模擬量輸入,能夠測量0-10V(20v、30v、40v)之間的直流電壓值。
(2)電壓顯示可采用LCD1602顯示,能夠顯示兩位小數。
簡易數字電壓表的制作,主要涉及數據(電壓)測量、A/D轉換及控制顯示方面的知識。
(1)A/D轉換采用PCF8591實現。
(2)電壓顯示采用LCD1602。
(3)單片機選用AT89C5.

仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)


單片機源程序如下:
  1. #include <reg52.h>   
  2. #include <intrins.h>   //包含函數_nop_()定義的頭文件
  3. #define u8 unsigned char
  4. #define u16 unsigned int
  5.         
  6. #define AddWr 0x90   //PCF8591寫地址
  7. #define AddRd 0x91   //PCF8591讀地址
  8. #define w_com P0
  9.         
  10. sbit RS=P2^2;
  11. sbit RW=P2^3;
  12. sbit E=P2^4;
  13. sbit Sda=P1^2;        //定義IIC總線引腳
  14. sbit Scl=P1^1;
  15. u8 datetab[10];    //存入電壓值
  16. u8 ADtemp;   //通道轉換后存入的數值
  17. float V_1602;
  18. u16 num=0;

  19. unsigned long num_pow(u8 m,u8 n)          //指數運算
  20. {
  21.         unsigned long result=1;
  22.         while(n--) result*=m;
  23.         return result;
  24. }

  25. void float2str(u8 str[],double floa,u8 len1,u8 len2)         //浮點型轉字符型數組
  26. {
  27.         u8 i=0,j=0;
  28.         u16 zhengshu=floa;
  29.         u16 xiaoshu=(floa-zhengshu)*num_pow(10,len2);
  30.         while(len1--)
  31.         {
  32.                 str[len1]=zhengshu%10+0x30;
  33.                 zhengshu=zhengshu /10;
  34.                 i++;
  35.         }
  36.         str[i]='.';
  37.         while(len2--)
  38.         {
  39.                 str[i+len2+1]=xiaoshu%10+0x30;
  40.                 xiaoshu=xiaoshu/10;
  41.                 j++;
  42.         }
  43.         str[i+j+1]='\0';
  44. }


  45. /*------------------------------------------------
  46. 啟動IIC總線
  47. ------------------------------------------------*/
  48.   void Start(void)
  49.   {
  50.    Sda=1;
  51.    _nop_();
  52.    Scl=1;
  53.    _nop_();
  54.    Sda=0;        //sda負跳變
  55.    _nop_();
  56.    Scl=0;
  57.   }
  58. /*------------------------------------------------
  59. 停止IIC總線
  60. ------------------------------------------------*/
  61.   void Stop(void)
  62.   {
  63.    Sda=0;
  64.    _nop_();
  65.    Scl=1;
  66.    _nop_();
  67.    Sda=1;        //sda正跳變
  68.    _nop_();
  69.    Scl=0;
  70.    }
  71. /*------------------------------------------------
  72.    IIC總線應答
  73. ------------------------------------------------*/
  74.    void Ack(void)
  75.    {
  76.     Sda=0;         //scl高電平期間sda輸出低電平
  77.                 _nop_();
  78.                 Scl=1;         
  79.                 _nop_();
  80.                 Scl=0;
  81.                 _nop_();
  82.         }
  83. /*------------------------------------------------
  84. IIC總線非應答
  85. ------------------------------------------------*/
  86.         void NoAck(void)
  87.         {
  88.          Sda=1;          //scl高電平期間sda輸出高電平
  89.          _nop_();
  90.          Scl=1;           
  91.          _nop_();
  92.          Scl=0;
  93.          _nop_();
  94.          }
  95. /*------------------------------------------------
  96. 向PCF8591發送1字節數據(/地址/控制命令等)
  97. ------------------------------------------------*/
  98. void Send(u8 Data)
  99. {
  100.           u8 BitCounter=8;   //定義發送位數為8
  101.           do
  102.           {
  103.                  Scl=0;
  104.                  _nop_();
  105.                  if((Data&0x80)==0x80)        //逐位判別1/0后送至SDA
  106.                     Sda=1;        //scl低電平期間數據送至sda線                        
  107.                  else
  108.                     Sda=0;
  109.                   Scl=1;        //scl變高輸出數據(寫入pcf8591)                        
  110.                   Data=Data<<1;
  111.                   BitCounter--;
  112.           }while(BitCounter);
  113.           Scl=0;
  114. }
  115. /*------------------------------------------------
  116. 從PCF8591讀入1字節(例如A/D轉換結果)
  117. ------------------------------------------------*/
  118. u8 Read(void)
  119. {
  120.                    u8 temp=0;
  121.                    u8 BitCounter=8;
  122.                    Sda=1;                        //拉高數據線
  123.                    do
  124.                    {
  125.                           temp=temp<<1;        //逐位移入temp
  126.                         Scl=0;                        
  127.                   _nop_();
  128.                           Scl=1;         //scl變高采樣sda線
  129.                           _nop_();
  130.                           if(Sda)                        //判別SDA線上為1/0
  131.                      temp=temp|0x01;
  132.                           else
  133.                      temp=temp&0xfe;
  134.                           BitCounter--;         
  135.              }while(BitCounter);               
  136.              return(temp);                //返回值為讀入的字節
  137. }

  138. void DACconversion(u8 sla,u8 c, u8 Val)    //8591輸出一個數據
  139. {
  140.         Start();//啟動總線
  141.         Send(sla);//發送器件地址
  142.                  Ack();        
  143.         Send(c);//發送控制字節
  144.                  Ack();        
  145.         Send(Val);//發送DAC的數值
  146.                  Ack();        
  147.         Stop();//結束總線
  148. }


  149. /*----------------------------------------------------------
  150. 啟動PCF8591 Chl 通道A/D轉換并讀取轉換結果
  151. --------------------------------------------------------------*/
  152. u8 ReadADC(u8 Chl)
  153.         {
  154.                  u8 Data;
  155.                  Start();                //開始信號
  156.                  Send(AddWr);                   //發寫地址(0x90)
  157.                  Ack();                           //等待 PCF8591應答        
  158.                  Send(0x40|Chl);         //寫入控制字并啟動 Chl通道A/D轉換
  159.                  Ack();                           //等待 PCF8591應答
  160.                  Start();                           //重發開始信號
  161.                  Send(AddRd);           //寫入讀地址
  162.                  Ack();
  163.                  Data=Read();            //讀取A/D轉換結果(注意是上次的)
  164.                  NoAck();                //發非應答信號
  165.                  Stop();                           //停止總線操作
  166.                  return Data;            //返回A/D轉換結果
  167.         }

  168. void delay(u16 i)
  169. {

  170.         while(i--);

  171. }

  172. void LCD_busy(void)
  173. {
  174.     u8 temp;
  175.     do{
  176.         temp =0xff;  
  177.         E = 0;
  178.         RS= 0;   
  179.         RW = 1;
  180.         E =1;
  181.         temp = w_com;  
  182.                         }while(temp&0x80);  // 如果 BF =1 則持續檢查
  183.         E = 0;
  184. }


  185. void write_command(u8 com)
  186. {
  187.     LCD_busy();
  188.    E= 0;
  189.    RS =0;
  190.    RW =0;
  191.    w_com = com;
  192.    E =1;  
  193.    delay(100);
  194.    E = 0;

  195. }


  196. void write_data(u8 com)
  197. {
  198.   LCD_busy();
  199.   E=0;   
  200.   RS= 1;
  201.   RW =0;
  202.   w_com = com;
  203.   E=1;
  204.   delay(100);
  205.   E =0;

  206.   }

  207.         
  208.         
  209.         
  210.         
  211.         void lcd_initial(void)
  212. {
  213.         write_command(0x38);    //8位數據接口,雙行顯示
  214.         delay(100);
  215.   write_command(0x0c);    //開顯示屏
  216.         delay(100);
  217.          write_command(0x01);    //清屏
  218.         delay(100);
  219.   write_command(0x06);                 //光標移動
  220.         delay(100);
  221.   
  222.   }

  223.         
  224. void string(u8 y,u8 x, u8 *s)     //x表示行,y表示列
  225. {
  226.          if (x==1)
  227.          {
  228.                 write_command(0xc0|y);          //因為DDRAM尋址指令是 0x80開頭。
  229.          }
  230.          else
  231.                 write_command(0x80|y);
  232.          
  233.          while(*s != '\0')
  234.         {
  235.           write_data(*s++);
  236.         }
  237. }

  238. void string_word(u8 y,u8 x,u8 num)     
  239. {
  240.          if (x==1)
  241.          {
  242.                 write_command(0xc0|y);          //因為DDRAM尋址指令是 0x80開頭。
  243.          }
  244.          else
  245.                 write_command(0x80|y);
  246.          
  247.                 write_data(num);

  248. }        
  249.         

  250. void main()
  251. {
  252.         lcd_initial();
  253.                 while(1)
  254.                 {
  255.                 ADtemp=ReadADC(1);              //讀取通道1 A/D轉換結果                        
  256.                 V_1602=ADtemp*(10.0/256);          //計算電壓值     10.0 20.0  30.0 40.0
  257.                 float2str(datetab,V_1602,2,2);   //顯示整數位與小數位的個數
  258.                 string(5,0,datetab);                        //顯示的位置和內容
  259.                 string_word(10,0,'V');            //顯示單位
  260.                 delay(10000);
  261.                 }
  262. }
  263.         
復制代碼

Keil代碼與Proteus8.13版本的仿真下載(注意不能兼容其他版本 只能用8.13打開):
程序+Proteus8.13仿真圖.7z (74.12 KB, 下載次數: 77)

評分

參與人數 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 日韩伦理一区二区 | 开操网 | 成人黄色电影在线播放 | 精品videossex高潮汇编 | 少妇一区在线观看 | 丝袜一区二区三区 | 紧缚调教一区二区三区视频 | 五月天婷婷激情 | 欧美一级片在线观看 | 日韩精品在线看 | 久久精品亚洲国产奇米99 | 久久9久 | 特级做a爰片毛片免费看108 | 欧美一级免费看 | 国产va| 天天碰夜夜操 | 精品国产乱码久久久久久久久 | 日日操夜夜操天天操 | 国产一区三区在线 | 99亚洲精品视频 | 国产美女久久 | 成人在线中文 | 午夜黄色 | 羞羞网站免费观看 | 日日夜夜天天干 | 一区二区精品电影 | 国产大毛片 | www.久久.com | 91精品国产综合久久婷婷香蕉 | 欧美不卡 | 欧美日韩在线一区二区三区 | 日韩一区二区三区精品 | 成年人视频在线免费观看 | 国产视频福利一区 | 精品欧美一区二区中文字幕视频 | 亚洲欧美中文日韩在线v日本 | 日韩在线中文字幕 | 精品一区国产 | 日韩成人av在线 | 一区二区在线看 | 国产电影一区二区在线观看 |