找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 9840|回復(fù): 4
打印 上一主題 下一主題
收起左側(cè)

單片機(jī)+PCF8591實(shí)現(xiàn)數(shù)字電壓表的仿真+代碼

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
制作數(shù)字電壓表(2學(xué)時(shí))

一、實(shí)驗(yàn)?zāi)康模?/p>

1. 了解I2C串行總線工作原理及通信協(xié)議

2. 了解ADC0804、DAC0832、PCF8591與AT89S51的接口設(shè)計(jì)

3. 掌握ADC0804、DAC0832、PCF8591的編程方法

4. 能夠熟練運(yùn)用數(shù)模轉(zhuǎn)換模塊

二、實(shí)驗(yàn)要求:

1. 數(shù)字電壓表:在AT89C52系統(tǒng)中采用PCF8591芯片,測(cè)量0-5V范圍內(nèi)的直流電壓,并在2位數(shù)碼管上顯示電壓值。

三、實(shí)驗(yàn)設(shè)備:(PROTEUS元件表)


四、實(shí)驗(yàn)報(bào)告:

1.描述實(shí)驗(yàn)過(guò)程(重要步驟用屏幕截圖表示)。

2.給出在PROTEUS中設(shè)計(jì)的單片機(jī)系統(tǒng)電路圖

3.畫(huà)出程序流程圖

4.給出在KEIL中編寫(xiě)的源程序。

5.描述在proteus中仿真運(yùn)行程序的實(shí)驗(yàn)現(xiàn)象

五、實(shí)驗(yàn)總結(jié)


單片機(jī)源程序如下:


  1. /**********************BST-M51實(shí)驗(yàn)開(kāi)發(fā)板例程************************
  2. *  平臺(tái):BST-M51 + Keil U4 + STC89C52
  3. *  名稱:AD串口讀取實(shí)驗(yàn)
  4. *  公司:深圳市亞博軟件開(kāi)發(fā)有限公司      
  5. *  日期:2015-6
  6. *  晶振:11.0592MHZ
  7. ******************************************************************/
  8. #include<reg52.h>    //包含單片機(jī)寄存器的頭文件
  9. #include <intrins.h>

  10. #define  AddWr 0x90    //PCF8591 地址

  11. // 變量定義
  12. unsigned char AD_CHANNEL=0;
  13. unsigned char  D[32];
  14. unsigned char code table[10]={0xC0,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};   //共陽(yáng)極數(shù)碼管0~9顯示的數(shù)值表
  15. unsigned int data dis[3]={0x00,0x00,0x00};  //用以計(jì)算存儲(chǔ)輸出電壓的3元素?cái)?shù)組

  16. sbit scl=P2^0;       //I2C  時(shí)鐘
  17. sbit sda=P2^1;       //I2C  數(shù)據(jù)
  18. bit ack;                 /*應(yīng)答標(biāo)志位*/
  19. sbit C1=P2^6;//數(shù)碼管位選
  20. sbit C2=P2^7;//數(shù)碼管位選
  21. sbit Dp=P2^5;//小數(shù)點(diǎn)

  22. unsigned char date;

  23. /*******************************************************************
  24.                      起動(dòng)總線函數(shù)              
  25. 函數(shù)原型: void  Start_I2c();
  26. 功能:     啟動(dòng)I2C總線,即發(fā)送I2C起始條件.
  27. ********************************************************************/
  28. void Start_I2c()
  29. {
  30.   sda=1;         /*發(fā)送起始條件的數(shù)據(jù)信號(hào)*/
  31.   _nop_();
  32.   scl=1;
  33.   _nop_();        /*起始條件建立時(shí)間大于4.7us,延時(shí)*/
  34.   _nop_();
  35.   _nop_();
  36.   _nop_();
  37.   _nop_();   
  38.   sda=0;         /*發(fā)送起始信號(hào)*/
  39.   _nop_();        /* 起始條件鎖定時(shí)間大于4μs*/
  40.   _nop_();
  41.   _nop_();
  42.   _nop_();
  43.   _nop_();      
  44.   scl=0;       /*鉗住I2C總線,準(zhǔn)備發(fā)送或接收數(shù)據(jù) */
  45.   _nop_();
  46.   _nop_();
  47. }

  48. /*******************************************************************
  49.                       結(jié)束總線函數(shù)              
  50. 函數(shù)原型: void  Stop_I2c();
  51. 功能:     結(jié)束I2C總線,即發(fā)送I2C結(jié)束條件.
  52. ********************************************************************/
  53. void Stop_I2c()
  54. {
  55.   sda=0;      /*發(fā)送結(jié)束條件的數(shù)據(jù)信號(hào)*/
  56.   _nop_();       /*發(fā)送結(jié)束條件的時(shí)鐘信號(hào)*/
  57.   scl=1;      /*結(jié)束條件建立時(shí)間大于4μs*/
  58.   _nop_();
  59.   _nop_();
  60.   _nop_();
  61.   _nop_();
  62.   _nop_();
  63.   sda=1;      /*發(fā)送I2C總線結(jié)束信號(hào)*/
  64.   _nop_();
  65.   _nop_();
  66.   _nop_();
  67.   _nop_();
  68. }

  69. /*******************************************************************
  70.                  字節(jié)數(shù)據(jù)發(fā)送函數(shù)              
  71. 函數(shù)原型: void  I2C_SendByte(UCHAR c);
  72. 功能:     將數(shù)據(jù)c發(fā)送出去,可以是地址,也可以是數(shù)據(jù),發(fā)完后等待應(yīng)答,并對(duì)
  73.           此狀態(tài)位進(jìn)行操作.(不應(yīng)答或非應(yīng)答都使ack=0)   
  74.            發(fā)送數(shù)據(jù)正常,ack=1; ack=0表示被控器無(wú)應(yīng)答或損壞。
  75. ********************************************************************/
  76. void  I2C_SendByte(unsigned char  c)
  77. {
  78. unsigned char  i;

  79. for(i=0;i<8;i++)  /*要傳送的數(shù)據(jù)長(zhǎng)度為8位*/
  80.     {
  81.      if((c<<i)&0x80)sda=1;   /*判斷發(fā)送位*/
  82.        else  sda=0;               
  83.      _nop_();
  84.      scl=1;               /*置時(shí)鐘線為高,通知被控器開(kāi)始接收數(shù)據(jù)位*/
  85.       _nop_();
  86.       _nop_();             /*保證時(shí)鐘高電平周期大于4μs*/
  87.       _nop_();
  88.       _nop_();
  89.       _nop_();        
  90.      scl=0;
  91.     }

  92.     _nop_();
  93.     _nop_();
  94.     sda=1;                /*8位發(fā)送完后釋放數(shù)據(jù)線,準(zhǔn)備接收應(yīng)答位*/
  95.     _nop_();
  96.     _nop_();  
  97.     scl=1;
  98.     _nop_();
  99.     _nop_();
  100.     _nop_();
  101.     if(sda==1)ack=0;   
  102.        else ack=1;        /*判斷是否接收到應(yīng)答信號(hào)*/
  103.     scl=0;
  104.     _nop_();
  105.     _nop_();
  106. }

  107. /*******************************************************************
  108.                  字節(jié)數(shù)據(jù)接收函數(shù)              
  109. 函數(shù)原型: UCHAR  I2C_RcvByte();
  110. 功能:        用來(lái)接收從器件傳來(lái)的數(shù)據(jù),并判斷總線錯(cuò)誤(不發(fā)應(yīng)答信號(hào)),
  111.           發(fā)完后請(qǐng)用應(yīng)答函數(shù)應(yīng)答從機(jī)。
  112. ********************************************************************/   
  113. unsigned char   I2C_RcvByte()
  114. {
  115.   unsigned char  retc=0,i;
  116.   sda=1;                     /*置數(shù)據(jù)線為輸入方式*/
  117.   for(i=0;i<8;i++)
  118.       {
  119.         _nop_();         
  120.         scl=0;                  /*置時(shí)鐘線為低,準(zhǔn)備接收數(shù)據(jù)位*/
  121.         _nop_();
  122.         _nop_();                 /*時(shí)鐘低電平周期大于4.7μs*/
  123.         _nop_();
  124.         _nop_();
  125.         _nop_();
  126.         scl=1;                  /*置時(shí)鐘線為高使數(shù)據(jù)線上數(shù)據(jù)有效*/
  127.         _nop_();
  128.         _nop_();
  129.         retc=retc<<1;
  130.         if(sda==1)retc=retc+1;  /*讀數(shù)據(jù)位,接收的數(shù)據(jù)位放入retc中 */
  131.         _nop_();
  132.         _nop_();
  133.       }
  134.   scl=0;   
  135.   _nop_();
  136.   _nop_();
  137.   return(retc);
  138. }

  139. /********************************************************************
  140.                      應(yīng)答子函數(shù)
  141. 函數(shù)原型:  void Ack_I2c(bit a);
  142. 功能:      主控器進(jìn)行應(yīng)答信號(hào)(可以是應(yīng)答或非應(yīng)答信號(hào),由位參數(shù)a決定)
  143. ********************************************************************/
  144. void Ack_I2c(bit a)
  145. {
  146.   if(a==0)sda=0;              /*在此發(fā)出應(yīng)答或非應(yīng)答信號(hào) */
  147.   else sda=1;                                                          /*0為發(fā)出應(yīng)答,1為非應(yīng)答信號(hào) */
  148.   _nop_();
  149.   _nop_();
  150.   _nop_();     
  151.   scl=1;
  152.   _nop_();
  153.   _nop_();                    /*時(shí)鐘低電平周期大于4μs*/
  154.   _nop_();
  155.   _nop_();
  156.   _nop_();
  157.   scl=0;                     /*清時(shí)鐘線,住I2C總線以便繼續(xù)接收*/
  158.   _nop_();
  159.   _nop_();   
  160. }

  161. /************************************************************
  162. * 函數(shù)名        : Pcf8591_DaConversion
  163. * 函數(shù)功能      : PCF8591的輸出端輸出模擬量
  164. * 輸入          : addr(器件地址),channel(轉(zhuǎn)換通道),value(轉(zhuǎn)換的數(shù)值)
  165. * 輸出                       : 無(wú)
  166. ******************* *****************************************/
  167. bit Pcf8591_DaConversion(unsigned char addr,unsigned char channel,  unsigned char Val)
  168. {
  169.    Start_I2c();              //啟動(dòng)總線
  170.    I2C_SendByte(addr);            //發(fā)送器件地址
  171.    if(ack==0)return(0);
  172.    I2C_SendByte(0x40|channel);              //發(fā)送控制字節(jié)
  173.    if(ack==0)return(0);
  174.    I2C_SendByte(Val);            //發(fā)送DAC的數(shù)值
  175.    if(ack==0)return(0);
  176.    Stop_I2c();               //結(jié)束總線
  177.    return(1);
  178. }

  179. /************************************************************
  180. * 函數(shù)名        : Pcf8591_SendByte
  181. * 函數(shù)功能                            : 寫(xiě)入一個(gè)控制命令
  182. * 輸入          : addr(器件地址),channel(轉(zhuǎn)換通道)
  183. * 輸出                       : 無(wú)
  184. ************************************************************/
  185. bit PCF8591_SendByte(unsigned char addr,unsigned char channel)
  186. {
  187.    Start_I2c();              //啟動(dòng)總線
  188.    I2C_SendByte(addr);            //發(fā)送器件地址
  189.    if(ack==0)return(0);
  190.    I2C_SendByte(0x40|channel);              //發(fā)送控制字節(jié)
  191.    if(ack==0)return(0);
  192.    Stop_I2c();               //結(jié)束總線
  193.    return(1);
  194. }

  195. /************************************************************
  196. * 函數(shù)名                     : PCF8591_RcvByte
  197. * 函數(shù)功能                 : 讀取一個(gè)轉(zhuǎn)換值
  198. * 輸入          :
  199. * 輸出          : dat
  200. ************************************************************/
  201. unsigned char PCF8591_RcvByte(unsigned char addr)
  202. {
  203.    unsigned char dat;

  204.    Start_I2c();          //啟動(dòng)總線
  205.    I2C_SendByte(addr+1);      //發(fā)送器件地址
  206.    if(ack==0)return(0);
  207.    dat=I2C_RcvByte();          //讀取數(shù)據(jù)0

  208.    Ack_I2c(1);           //發(fā)送非應(yīng)答信號(hào)
  209.    Stop_I2c();           //結(jié)束總線
  210.    return(dat);
  211. }
  212. /*------------------------------------------------
  213.                  串口初始化函數(shù)
  214. ------------------------------------------------*/
  215. void init_com(void)
  216. {
  217. EA=1;        //開(kāi)總中斷
  218. ES=1;        //允許串口中斷
  219. ET1=1;        //允許定時(shí)器T1的中斷
  220. TMOD=0x20;   //定時(shí)器T1,在方式2中斷產(chǎn)生波特率
  221. PCON=0x00;   //SMOD=0
  222. SCON=0x50;   // 方式1 由定時(shí)器控制
  223. TH1=0xfd;    //波特率設(shè)置為9600
  224. TL1=0xfd;
  225. TR1=1;       //開(kāi)定時(shí)器T1運(yùn)行控制位

  226. }
  227. /*------------------------------------------------
  228.                   延時(shí)函數(shù)
  229. ------------------------------------------------*/
  230. void delay(unsigned char i)
  231. {
  232.   unsigned char j,k;
  233.   for(j=i;j>0;j--)
  234.     for(k=125;k>0;k--);
  235. }
  236. /*------------------------------------------------
  237. 把讀取值轉(zhuǎn)換成一個(gè)一個(gè)的字符,給串口顯示
  238. ------------------------------------------------*/
  239. void To_ascii(unsigned char num)
  240. {            
  241.               SBUF=num/100+'0';                                               
  242.               delay(200);                             
  243.               SBUF=num/10%10+'0';                                            
  244.               delay(200);            
  245.               SBUF=num%10+'0';
  246.               delay(200);
  247. }
  248. /*------------------------------------------------
  249.                     主函數(shù)
  250. ------------------------------------------------*/
  251. main()
  252. {

  253.               init_com();
  254.               while(1)
  255.               {
  256.               /********以下AD-DA處理*************/
  257.               PCF8591_SendByte(AddWr,0);              //啟動(dòng)轉(zhuǎn)換
  258.               D[0]=PCF8591_RcvByte(AddWr);  //讀轉(zhuǎn)換完的數(shù)字信號(hào),ADC0 模數(shù)轉(zhuǎn)換1      光敏電阻            
  259.               /********以下將AD的值通過(guò)串口發(fā)送出去*************/
  260.               dis[1]=D[0]/51;   //每刻度值為5/256V,所以電壓值為輸出的8位數(shù)字值*5/256V,計(jì)算輸出電壓的整數(shù)值
  261.               dis[2]=D[0]%51;   //dis[2]位中間暫存數(shù)據(jù)位
  262.               dis[2]=dis[2]*10;   
  263.               dis[0]=dis[2]/51;    //計(jì)算輸出電壓的小數(shù)值            
  264.             
  265.               C1=0;                //關(guān)閉第二位數(shù)碼管
  266.               C2=1;                //打開(kāi)第一位數(shù)碼管
  267.                  Dp=1;                //打開(kāi)小數(shù)點(diǎn)
  268.               P1=table[dis[0]];    //顯示整數(shù)部分及小數(shù)點(diǎn)
  269.               delay(10);           //延時(shí)一定時(shí)間
  270.                                          
  271.      C2=0;                //關(guān)閉第一位數(shù)碼管
  272.               C1=1;                //打開(kāi)第二位數(shù)碼管
  273.               Dp=0;                //關(guān)閉小數(shù)點(diǎn)
  274.               P1=table[dis[1]];     //顯示小數(shù)部分
  275.             
  276.               /*delay(200);            
  277.               To_ascii(D[0]);
  278.               SBUF='\n';
  279.               delay(200);
  280.               if(RI)
  281.               {
  282.                             date=SBUF;    //單片機(jī)接受
  283.                             SBUF=date;    //單片機(jī)發(fā)送
  284.                             RI=0;
  285.               }*/            
  286.    }
  287. }
復(fù)制代碼


所有資料51hei提供下載:

實(shí)驗(yàn)九制作數(shù)字電壓表.rar (419.46 KB, 下載次數(shù): 209)




評(píng)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

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

使用道具 舉報(bào)

沙發(fā)
ID:362692 發(fā)表于 2020-1-3 15:10 來(lái)自手機(jī) | 只看該作者
程序還不錯(cuò),借鑒的一部分
回復(fù)

使用道具 舉報(bào)

板凳
ID:743707 發(fā)表于 2020-5-4 16:02 來(lái)自手機(jī) | 只看該作者
這個(gè)圖可以有清楚的嗎
回復(fù)

使用道具 舉報(bào)

地板
ID:782630 發(fā)表于 2020-6-17 22:24 | 只看該作者
正在學(xué),感謝分享
回復(fù)

使用道具 舉報(bào)

5#
ID:585455 發(fā)表于 2020-9-13 15:33 | 只看該作者
正在學(xué)習(xí)pcf8591;很棒的資料。
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表