標題: 單片機IIC總線與數(shù)碼管程序問題 [打印本頁]

作者: 放眼天下    時間: 2019-2-10 17:44
標題: 單片機IIC總線與數(shù)碼管程序問題
  我的程序是通過AT24C02寫入和讀取數(shù)據(jù),并由四個獨立按鍵控制數(shù)碼管顯示出來。按鍵1是保存目前的數(shù)據(jù),按鍵2是顯示上次保存的數(shù)據(jù),按鍵3是+1功能,按鍵4是清零功能,開始的時候,數(shù)碼管會顯示4個0,然后按3  +1,按1,保存數(shù)據(jù),按4清零,并按2 ,顯示數(shù)據(jù),前面的都沒有問題,就是按2的時候,不管保存的數(shù)據(jù)是多少,數(shù)碼管都顯示的是0006(6的最下面一橫還沒有),這是為什么呢?單片機代碼如下,初學51,請多指教!

  1. /**************************************************************************************
  2. *                              EEPROM-IIC實驗                                                                                                  *
  3. 實現(xiàn)現(xiàn)象:下載程序后數(shù)碼管后4位顯示0,按K1保存顯示的數(shù)據(jù),按K2讀取上次保存的數(shù)據(jù),
  4.                   按K3顯示數(shù)據(jù)加一,按K4顯示數(shù)據(jù)清零。最大能寫入的數(shù)據(jù)是255.
  5. 注意事項:由于P3.2口跟紅外線共用,所以做按鍵實驗時為了不讓紅外線影響實驗效果,最好把紅外線先取下來。                                                                                                                                                                  
  6. ***************************************************************************************/

  7. #include "reg52.h"                         //此文件中定義了單片機的一些特殊功能寄存器
  8. #include "i2c.h"      

  9. typedef unsigned int u16;          //對數(shù)據(jù)類型進行聲明定義
  10. typedef unsigned char u8;

  11. sbit LSA=P2^2;
  12. sbit LSB=P2^3;
  13. sbit LSC=P2^4;

  14. sbit k1=P3^1;
  15. sbit k2=P3^0;
  16. sbit k3=P3^2;
  17. sbit k4=P3^3;         //定義按鍵端口

  18. char num=0;
  19. u8 disp[4];
  20. u8 code smgduan[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

  21. /*******************************************************************************
  22. * 函 數(shù) 名         : delay
  23. * 函數(shù)功能                   : 延時函數(shù),i=1時,大約延時10us
  24. *******************************************************************************/
  25. void delay(u16 i)
  26. {
  27.         while(i--);      
  28. }


  29. /*******************************************************************************
  30. * 函數(shù)名         :Keypros()
  31. * 函數(shù)功能                 :按鍵處理函數(shù)
  32. * 輸入           : 無
  33. * 輸出                  : 無
  34. *******************************************************************************/
  35. void Keypros()
  36. {
  37.         if(k1==0)
  38.         {
  39.                 delay(1000);  //消抖處理
  40.                 if(k1==0)
  41.                 {
  42.                         At24c02Write(1,num);   //在地址1內(nèi)寫入數(shù)據(jù)num
  43.                 }
  44.                 while(!k1);
  45.         }
  46.         if(k2==0)
  47.         {
  48.                 delay(1000);  //消抖處理
  49.                 if(k2==0)
  50.                 {
  51.                         num=At24c02Read(1);          //讀取EEPROM地址1內(nèi)的數(shù)據(jù)保存在num中
  52.                 }
  53.                 while(!k2);
  54.         }
  55.         if(k3==0)
  56.         {
  57.                 delay(100);  //消抖處理
  58.                 if(k3==0)
  59.                 {
  60.                         num++;           //數(shù)據(jù)加1
  61.                         if(num>255)num=0;
  62.                 }
  63.                 while(!k3);
  64.         }
  65.         if(k4==0)
  66.         {
  67.                 delay(1000);  //消抖處理
  68.                 if(k4==0)
  69.                 {
  70.                         num=0;                 //數(shù)據(jù)清零
  71.                 }
  72.                 while(!k4);
  73.         }               
  74. }

  75. /*******************************************************************************
  76. * 函數(shù)名         :datapros()
  77. * 函數(shù)功能                 :數(shù)據(jù)處理函數(shù)
  78. * 輸入           : 無
  79. * 輸出                  : 無
  80. *******************************************************************************/
  81. void datapros()
  82. {
  83.         disp[0]=smgduan[num/1000];//千位
  84.         disp[1]=smgduan[num%1000/100];//百位
  85.         disp[2]=smgduan[num%1000%100/10];//個位
  86.         disp[3]=smgduan[num%1000%100%10];               
  87. }


  88. /*******************************************************************************
  89. * 函數(shù)名         :DigDisplay()
  90. * 函數(shù)功能                 :數(shù)碼管顯示函數(shù)
  91. * 輸入           : 無
  92. * 輸出                  : 無
  93. *******************************************************************************/
  94. void DigDisplay()
  95. {
  96.         u8 i;
  97.         for(i=0;i<4;i++)
  98.         {
  99.                 switch(i)         //位選,選擇點亮的數(shù)碼管,
  100.                 {
  101.                         case(0):
  102.                                 LSA=0;LSB=0;LSC=0; break;//顯示第0位
  103.                         case(1):
  104.                                 LSA=1;LSB=0;LSC=0; break;//顯示第1位
  105.                         case(2):
  106.                                 LSA=0;LSB=1;LSC=0; break;//顯示第2位
  107.                         case(3):
  108.                                 LSA=1;LSB=1;LSC=0; break;//顯示第3位      
  109.                 }
  110.                 P0=disp[3-i];//發(fā)送數(shù)據(jù)
  111.                 delay(100); //間隔一段時間掃描      
  112.                 P0=0x00;//消隱
  113.         }               
  114. }

  115. /*******************************************************************************
  116. * 函 數(shù) 名       : main
  117. * 函數(shù)功能                 : 主函數(shù)
  118. * 輸    入       : 無
  119. * 輸    出             : 無
  120. *******************************************************************************/
  121. void main()
  122. {      
  123.         while(1)
  124.         {
  125.                 Keypros();         //按鍵處理函數(shù)
  126.                 datapros();         //數(shù)據(jù)處理函數(shù)
  127.                 DigDisplay();//數(shù)碼管顯示函數(shù)               
  128.         }               
  129. }



  130. #include"i2c.h"

  131. /*******************************************************************************
  132. * 函數(shù)名         : Delay10us()
  133. * 函數(shù)功能                   : 延時10us
  134. * 輸入           : 無
  135. * 輸出                  : 無
  136. *******************************************************************************/

  137. void Delay10us()
  138. {
  139.         unsigned char a,b;
  140.         for(b=1;b>0;b--)
  141.                 for(a=2;a>0;a--);

  142. }
  143. /*******************************************************************************
  144. * 函數(shù)名         : I2cStart()
  145. * 函數(shù)功能                 : 起始信號:在SCL時鐘信號在高電平期間SDA信號產(chǎn)生一個下降沿
  146. * 輸入           : 無
  147. * 輸出                  : 無
  148. * 備注           : 起始之后SDA和SCL都為0
  149. *******************************************************************************/

  150. void I2cStart()
  151. {
  152.         SDA=1;
  153.         Delay10us();
  154.         SCL=1;
  155.         Delay10us();//建立時間是SDA保持時間>4.7us
  156.         SDA=0;
  157.         Delay10us();//保持時間是>4us
  158.         SCL=0;                       
  159.         Delay10us();               
  160. }
  161. /*******************************************************************************
  162. * 函數(shù)名         : I2cStop()
  163. * 函數(shù)功能                 : 終止信號:在SCL時鐘信號高電平期間SDA信號產(chǎn)生一個上升沿
  164. * 輸入           : 無
  165. * 輸出                  : 無
  166. * 備注           : 結(jié)束之后保持SDA和SCL都為1;表示總線空閑
  167. *******************************************************************************/

  168. void I2cStop()
  169. {
  170.         SDA=0;
  171.         Delay10us();
  172.         SCL=1;
  173.         Delay10us();//建立時間大于4.7us
  174.         SDA=1;
  175.         Delay10us();               
  176. }
  177. /*******************************************************************************
  178. * 函數(shù)名         : I2cSendByte(unsigned char dat)
  179. * 函數(shù)功能                 : 通過I2C發(fā)送一個字節(jié)。在SCL時鐘信號高電平期間,保持發(fā)送信號SDA保持穩(wěn)定
  180. * 輸入           : num
  181. * 輸出                  : 0或1。發(fā)送成功返回1,發(fā)送失敗返回0
  182. * 備注           : 發(fā)送完一個字節(jié)SCL=0,SDA=1
  183. *******************************************************************************/

  184. unsigned char I2cSendByte(unsigned char dat)
  185. {
  186.         unsigned char a=0,b=0;//最大255,一個機器周期為1us,最大延時255us。               
  187.         for(a=0;a<8;a++)//要發(fā)送8位,從最高位開始
  188.         {
  189.                 SDA=dat>>7;         //起始信號之后SCL=0,所以可以直接改變SDA信號
  190.                 dat=dat<<1;
  191.                 Delay10us();
  192.                 SCL=1;
  193.                 Delay10us();//建立時間>4.7us
  194.                 SCL=0;
  195.                 Delay10us();//時間大于4us               
  196.         }
  197.         SDA=1;
  198.         Delay10us();
  199.         SCL=1;
  200.         while(SDA)//等待應答,也就是等待從設備把SDA拉低
  201.         {
  202.                 b++;
  203.                 if(b>200)         //如果超過2000us沒有應答發(fā)送失敗,或者為非應答,表示接收結(jié)束
  204.                 {
  205.                         SCL=0;
  206.                         Delay10us();
  207.                         return 0;
  208.                 }
  209.         }
  210.         SCL=0;
  211.         Delay10us();
  212.         return 1;               
  213. }
  214. /*******************************************************************************
  215. * 函數(shù)名         : I2cReadByte()
  216. * 函數(shù)功能                   : 使用I2c讀取一個字節(jié)
  217. * 輸入           : 無
  218. * 輸出                  : dat
  219. * 備注           : 接收完一個字節(jié)SCL=0,SDA=1.
  220. *******************************************************************************/

  221. unsigned char I2cReadByte()
  222. {
  223.         unsigned char a=0,dat=0;
  224.         SDA=1;                        //起始和發(fā)送一個字節(jié)之后SCL都是0
  225.         Delay10us();
  226.         for(a=0;a<8;a++)//接收8個字節(jié)
  227.         {
  228.                 SCL=1;
  229.                 Delay10us();
  230.                 dat<<=1;
  231.                 dat|=SDA;
  232.                 Delay10us();
  233.                 SCL=0;
  234.                 Delay10us();
  235.         }
  236.         return dat;               
  237. }


  238. /*******************************************************************************
  239. * 函數(shù)名         : void At24c02Write(unsigned char addr,unsigned char dat)
  240. * 函數(shù)功能                   : 往24c02的一個地址寫入一個數(shù)據(jù)
  241. * 輸入           : 無
  242. * 輸出                  : 無
  243. *******************************************************************************/

  244. void At24c02Write(unsigned char addr,unsigned char dat)
  245. {
  246.         I2cStart();
  247.         I2cSendByte(0xa0);//發(fā)送寫器件地址
  248.         I2cSendByte(addr);//發(fā)送要寫入內(nèi)存地址
  249.         I2cSendByte(dat);        //發(fā)送數(shù)據(jù)
  250.         I2cStop();
  251. }
  252. /*******************************************************************************
  253. * 函數(shù)名         : unsigned char At24c02Read(unsigned char addr)
  254. * 函數(shù)功能                   : 讀取24c02的一個地址的一個數(shù)據(jù)
  255. * 輸入           : 無
  256. * 輸出                  : 無
  257. *******************************************************************************/

  258. unsigned char At24c02Read(unsigned char addr)
  259. {
  260.         unsigned char num;
  261.         I2cStart();
  262.         I2cSendByte(0xa0); //發(fā)送寫器件地址
  263.         I2cSendByte(addr); //發(fā)送要讀取的地址
  264.         I2cStart();
  265.         I2cSendByte(0xa1); //發(fā)送讀器件地址
  266.         num=I2cReadByte(); //讀取數(shù)據(jù)
  267.         I2cStop();
  268.         return num;      
  269. }



  270. #ifndef __I2C_H_
  271. #define __I2C_H_

  272. #include <reg52.h>

  273. sbit SCL=P2^1;
  274. sbit SDA=P2^0;

  275. void I2cStart();
  276. void I2cStop();
  277. unsigned char I2cSendByte(unsigned char dat);
  278. unsigned char I2cReadByte();
  279. void At24c02Write(unsigned char addr,unsigned char dat);
  280. unsigned char At24c02Read(unsigned char addr);

  281. #endif
復制代碼








歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1