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

QQ登錄

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

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

單片機(jī)+AT24C02為啥讀寫(xiě)錯(cuò)誤?

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
  1. /****************************************************************
  2. AT24C前四位固定為1010 A1-A2由管腳電平默認(rèn)接地,最后一位表示讀寫(xiě)操作所以AT24C讀地址0xa1 寫(xiě)地址0xa0
  3. 寫(xiě)AT24C02的時(shí)候從器件地址為10100 0000,(0xa0),讀AT24C02的時(shí)候從器件地址為10100 0001,(0xa1)
  4. ***************************************************************/
  5. #include<reg51.h>
  6. #include <intrins.h>
  7. #define uint unsigned int
  8. #define uchar unsigned char
  9.         #define AT24C02_ADDRESS  0xA0 //0xA0 1010 00000寫(xiě)地址
  10. uint Count;
  11. uint Set_Count;
  12. //        unsigned  int Count;
  13. //      unsigned  int Set_Count;
  14. uint Num_L;
  15. uint Num_H;

  16. uint num1;
  17. uint  num2;

  18. char yiwei_Count;//移位計(jì)數(shù)

  19. sbit I2C_SCL= P1^6;
  20. sbit I2C_SDA= P1^7;

  21. sbit Start_Dianji=P3^0; //電機(jī)啟動(dòng)_dianji
  22. sbit  forward=P3^1; //正轉(zhuǎn)檢測(cè)
  23. //sbit  back=P3^1;    //反轉(zhuǎn)檢測(cè)
  24. sbit  run=P3^7;      //運(yùn)行信號(hào)
  25. sbit  jia_up=P1^0;// 增加鍵
  26. sbit  jian_down=P1^1;//減少鍵
  27. sbit  yiwei_up=P1^2; //移位鍵
  28. sbit  qingling=P1^3; //清零鍵
  29. uchar code ledcode[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};         //共陰數(shù)碼管編碼0-9
  30. uchar data Ledbuff[8]={1};//顯示緩沖區(qū)

  31. #define I2CDelay_us(){_nop_();_nop_();_nop_();_nop_();}//voidI2CDelay_us
  32. /***********************
  33. AT24C初始化
  34. *************************/
  35. void I2C_init()
  36. {
  37.         I2C_SCL=1;
  38.   //    I2CDelay_us(4);
  39.         I2C_SDA=1;//首先確保SCL SDA都是高電平
  40.   // I2CDelay_us(4);
  41.         
  42. }

  43. /***********************
  44. 產(chǎn)生總線起始信號(hào)
  45. *************************/
  46. void I2C_Start(void )
  47. {
  48.   I2C_SDA=1;//首先確保SCL SDA都是高電平
  49. //  I2CDelay_us(5);
  50.         I2C_SCL=1; //確保SCL高電平
  51.   //   I2CDelay_us(5);
  52.         I2C_SDA=0;//先在SCL為高時(shí)拉低SDA,即為起始信號(hào)
  53. //    I2CDelay_us(5);
  54.         I2C_SCL=0; //在拉低 SCL,鉗住I2C總線準(zhǔn)備發(fā)送或接收數(shù)據(jù)
  55. }
  56. /***********************
  57. 產(chǎn)生總線停止信號(hào):先拉低SDA在拉低SCL
  58. *************************/

  59.   void I2C_Stop(void )
  60. {
  61.         I2C_SDA=0;//首先確保SCL SDA都是低電平
  62.         I2C_SCL=1; //先拉高 SCL
  63.         I2C_SDA=1;//在拉高 SDA
  64.    /*
  65. I2C_SCL=0;
  66. I2C_SDA=0;
  67. //    I2CDelay_us(4);
  68.    I2C_SCL=1;
  69. I2C_SDA=1;
  70. //   I2CDelay_us(4);
  71.    */
  72. }
  73. /*******************************************************************************
  74. *@brief I2C發(fā)送一個(gè)字節(jié)數(shù)據(jù)
  75. *@param Byte要發(fā)送的字節(jié)
  76. *@retval 無(wú)
  77. 起始信號(hào)后必須送一個(gè)從機(jī)地址(7)位,1-7位為要接收器件的地址,第八位讀寫(xiě)位0發(fā)送1接收,第9位ACK應(yīng)答位,
  78. 緊接著為第一個(gè)數(shù)據(jù)字節(jié),然后一位應(yīng)答位ACK后面繼續(xù)第二個(gè)數(shù)據(jù)字節(jié)
  79. **********************************************************************************/
  80. void  I2C_SendByte(unsigned char Byte)
  81. {
  82. unsigned char i;
  83.         for(i=0;i<8;i++)
  84.            {
  85.                 I2C_SDA=Byte&(0x80>>i);
  86.                 I2C_SCL=1; //先拉高 SCL
  87.                   I2C_SCL=0; //SCL        
  88.              }
  89. }
  90. /***********************************************************************************************
  91. *@brief I2C讀取 接收一個(gè)字節(jié)
  92. *@param 無(wú)
  93. *@retval  讀取 接收到的一個(gè)字節(jié)數(shù)據(jù)
  94. ********************************************************************************************/
  95. unsigned char I2C_ReceiveByte(void)
  96. {
  97. unsigned char i,Byte=0x00;//
  98.         I2C_SDA=1; //
  99.         for(i=0;i<8;i++)
  100.         {
  101.         I2C_SCL=1; //先拉高 SCL
  102.         if(I2C_SDA){Byte |= (0x80>>i); }
  103.         I2C_SCL=0; //SCL        
  104.         }
  105. return Byte;
  106. }
  107. /*********************
  108. *@brief I2C發(fā)送應(yīng)答Ack
  109. *@param AckBit應(yīng)答位 0為應(yīng)答(成功) 1為非應(yīng)答(失。
  110. *@retval 無(wú)
  111. ************************/
  112. void I2C_SendAck(unsigned char AckBit)
  113. {

  114.         I2C_SDA=AckBit;
  115.         I2C_SCL=1; //先拉高 SCL
  116.         I2C_SCL=0; //SCL        
  117. }
  118. /*********************
  119. *@brief I2C接收應(yīng)答位
  120. *@param 無(wú)
  121. *@retval AckBit應(yīng)答位 0為應(yīng)答(成功) 1為非應(yīng)答(失。
  122. ************************/
  123. unsigned char I2C_ReceiveAck(void)
  124. {
  125. unsigned char AckBit;
  126.         I2C_SDA=1;
  127.         I2C_SCL=1; //先拉高 SCL
  128.   AckBit=I2C_SDA;
  129.         I2C_SCL=0; //SCL
  130. return AckBit; //返回值
  131. }
  132. /**********向AT24C寫(xiě)數(shù)據(jù)***********
  133. *@brief AT24C寫(xiě)入一個(gè)字節(jié)
  134. *@param WordAddress要寫(xiě)入字節(jié)的地址
  135. *@param Data要寫(xiě)入的數(shù)據(jù)
  136. *@retval無(wú)
  137. 寫(xiě)多字節(jié)時(shí),寫(xiě)入一個(gè)字節(jié)。在寫(xiě)一個(gè)字節(jié)前,必須延時(shí)5ms
  138. ************************/
  139. void AT24C_WriteByte(unsigned char WordAddress,Data)
  140. {
  141.   I2C_Start();//啟動(dòng)總線
  142.   I2C_SendByte(AT24C02_ADDRESS);//發(fā)送寫(xiě)操作地址+寫(xiě)數(shù)據(jù)(0xa0)
  143.         I2C_ReceiveAck();                      //等待應(yīng)答
  144.         I2C_SendByte(WordAddress);//要寫(xiě)入的地址
  145.         I2C_ReceiveAck();       //等待應(yīng)答完成
  146.    I2C_SendByte(Data);  //要寫(xiě)入的數(shù)據(jù),第一字節(jié) ,第二字節(jié)注意:每個(gè)字節(jié)都回應(yīng)一個(gè)應(yīng)答位0,如果沒(méi)有回應(yīng)說(shuō)明寫(xiě)入不成功
  147.         I2C_ReceiveAck();       //等待完成  注意:每個(gè)字節(jié)都回應(yīng)一個(gè)應(yīng)答位0,如果沒(méi)有回應(yīng)說(shuō)明寫(xiě)入不成功
  148.         I2C_Stop(); //發(fā)送結(jié)束信號(hào):停止總線
  149. }
  150. /************從AT24C中讀出數(shù)據(jù)*********
  151. *@brief AT24C讀取一個(gè)字節(jié)
  152. *@param WordAddress要讀出字節(jié)的地址
  153. *@param 無(wú)
  154. *@retval要讀出的數(shù)據(jù)
  155. ************************/
  156. unsigned char AT24C_ReadByte(unsigned char WordAddress) //void
  157. {
  158.         unsigned char Data;
  159.   I2C_Start();                    //發(fā)送起始信號(hào):啟動(dòng)總線
  160.    I2C_SendByte(AT24C02_ADDRESS);  //接上首字節(jié),發(fā)送器件寫(xiě)操作地址+寫(xiě)數(shù)據(jù)(0xa0)這里寫(xiě)操作時(shí)維綸把所要讀的數(shù)據(jù)地址AT24C02_ADDRESS通知讀取哪個(gè)地址信息
  161.         I2C_ReceiveAck(); //等待完成應(yīng)答
  162.         I2C_SendByte(WordAddress);//發(fā)送要讀取內(nèi)存的地址(WORD ADDRESS)
  163.         I2C_ReceiveAck();       //等待應(yīng)答完成
  164.          I2C_Start();//在次啟動(dòng)總線
  165.         I2C_SendByte(AT24C02_ADDRESS| 0x01);  //對(duì)E2PROM進(jìn)行讀操作(0XA1)E2PROM會(huì)自動(dòng)向主機(jī)發(fā)回?cái)?shù)據(jù),讀取一個(gè)字節(jié)后回應(yīng)一個(gè)應(yīng)答位,后會(huì)繼續(xù)傳送下一個(gè)地址的數(shù)據(jù)0xa1
  166.         I2C_ReceiveAck();       //等待完成
  167.         Data= I2C_ReceiveByte();  //要讀出的數(shù)據(jù)到Data
  168.    I2C_SendAck(1);       //等待完成::如果不想讀了,就發(fā)送一個(gè)非應(yīng)答位NAK(1),發(fā)送結(jié)束,停止總線
  169.         I2C_Stop(); //停止總線
  170.         return Data ;//返回值
  171. }

  172. /***********************************/
  173. void delayms(uint ms)

  174. {
  175. uchar k;
  176. while(ms--)
  177. {
  178.   for(k = 0; k < 120; k++);
  179. }
  180. }
  181. void display()                        //顯示程序display(uchar a,b,c,d,e)        char i;
  182. {
  183.         static unsigned char i = 0;         
  184.         switch(i)//使用多分支選擇語(yǔ)句 i=count display 0x代表16進(jìn)制
  185.         {
  186.                 case(0):Ledbuff[7]=Set_Count/1000;break;   //取設(shè)定千位字符送緩存
  187.                 case(1):Ledbuff[6]=Set_Count/100%10;break; //取設(shè)定百位字符送緩沖
  188.                 case(2):Ledbuff[5]=Set_Count/10%10;break;   //取設(shè)定十位字符送緩沖
  189.                 case(3):Ledbuff[4]=Set_Count%10;break;     //取設(shè)定個(gè)位字符送緩存
  190.                   
  191.                 case(4):Ledbuff[3]=Count/1000;break;         //取計(jì)數(shù)千位字符送緩存
  192.                 case(5):Ledbuff[2]=Count/100%10;break;
  193.                 case(6):Ledbuff[1]=Count/10%10;break;
  194.                 case(7):Ledbuff[0]=Count%10;break;
  195.         }
  196.         P0=0x00;   //消陰:段碼全部低電平關(guān)閉
  197.         P2=~(0x01<<i); //P2位選,左移i位取反
  198.         P0=ledcode[Ledbuff[i]];  //P0字符刷新顯示
  199.         delayms(1); //顯示2MS
  200.         i=++i%8;   //自加1
  201. }
  202. /*
  203. void  Adjust(void)        //按鍵設(shè)定匝數(shù),用P2.4個(gè)位-P2.7(千位)前四位數(shù)碼管顯示
  204.   {        
  205.            
  206.                 if(yiwei_up==0) //移位按鍵按下
  207.                   {
  208.                          while(!yiwei_up); //等待移位按鍵松開(kāi)
  209.                          if(yiwei_Count<3) //移位
  210.                            {
  211.                             yiwei_Count +=1;
  212.                            }
  213.                    else       //如果>3
  214.           {                 
  215.             yiwei_Count=0;       //設(shè)定位在個(gè)位
  216.           }                                
  217.                    }
  218.                
  219.                 if(Set_Count>=0 && Set_Count<9999)//最大9999yiwei_Count=0; //設(shè)定加 jia_up==0
  220.                   {
  221.                                   if (jia_up==0)   //增加按鍵按下                                                     
  222.                                          {        
  223.                                            while(!jia_up);//等待加按鍵松開(kāi)
  224.                                                   {
  225.                              if (yiwei_Count==0)        //               
  226.                              {
  227.                                      Set_Count += 1;         //設(shè)定+1
  228.                              }
  229.                                                           if (yiwei_Count==1&&Set_Count<9990)
  230.                                                                  {
  231.                                      Set_Count += 10;         //設(shè)定+1
  232.                               }
  233.                                                           if (yiwei_Count==2&&Set_Count<9900)
  234.                                                                  {
  235.                                      Set_Count += 100;         //設(shè)定+1
  236.                              }        
  237.                                                                 if (yiwei_Count==3 && Set_Count<9000)
  238.                                                                  {
  239.                                      Set_Count += 1000;         //設(shè)定+1
  240.                              }
  241.                                                   }        
  242.                                          }        
  243.                  if (jian_down==0)   //減少按鍵按下                                                     
  244.                                 {        
  245.                                            while(!jian_down);//等待按鍵松開(kāi)
  246.                                                  {
  247.                              if (yiwei_Count==0&&Set_Count>1)        //        移位在個(gè)位        
  248.                               {
  249.                                       Set_Count -= 1;         //設(shè)定+1
  250.                               }
  251.                                                           if (yiwei_Count==1&&Set_Count>9)
  252.                                                                    {
  253.                                       Set_Count -= 10;         //設(shè)定+1
  254.                                }
  255.                                                           if (yiwei_Count==2 && Set_Count>99)
  256.                                                                    {
  257.                                       Set_Count -= 100;         //設(shè)定+1
  258.                                }        
  259.                                                                  if (yiwei_Count==3 && Set_Count>999)
  260.                                                                    {
  261.                                        Set_Count -= 1000;         //設(shè)定+1
  262.                                }
  263.                                                  }        
  264.                                                  //寫(xiě)入數(shù)據(jù)
  265. /*        AT24C_WriteByte(0,Set_Count%256);
  266.         delayms(5) ; //顯示2MS
  267.         AT24C_WriteByte(1,Set_Count/256);
  268.         delayms(5); //顯示2MS
  269.                                         }        
  270.                 */        
  271. /**********************************************************
  272. 主函數(shù)
  273. **********************************************************/               
  274. void main()
  275. {
  276.         I2C_init();
  277. //        init();        //初始化24C02
  278.         //        num=5678;          //num為小于等于65535的整數(shù)。   */
  279.         Set_Count=1234;

  280.        Num_H  =Set_Count/256;  //1234/256就簡(jiǎn)單了,高位:取的是整數(shù)倍,不被整除的部分自然就被剔除了1234/256=4
  281.         Num_L =Set_Count%256;  //%256是取余,低位:也就是你把前面的數(shù)值除以256取余,商跟除數(shù)則是256的整數(shù)倍部分1234%256=210  ;4*256=1024  %256=1234-1024=210
  282.         AT24C_WriteByte(0,Num_L);
  283.    delayms(10); //顯示2MS
  284.         AT24C_WriteByte(1,Num_H  );
  285.    delayms(10); //顯示2MS

  286.         num1=AT24C_ReadByte(0);        //用地址0單元存儲(chǔ)num十六進(jìn)制表示時(shí)的低兩位
  287.         num2=AT24C_ReadByte(1);        //用地址0單元存儲(chǔ)num十六進(jìn)制表示時(shí)的高兩位
  288.         Count=num2*256+num1;
  289.    //寫(xiě)入24C02
  290.               //       AT24C_WriteByte(0,Set_Count%256); //低8位寫(xiě)入0x00
  291.    /*
  292.     AT24C_WriteByte(0,120); //低8位寫(xiě)入0x00
  293.                        delayms(5); //顯示2MS

  294.         //              AT24C_WriteByte(1,Set_Count/256); //高8位寫(xiě)入0x01
  295.       AT24C_WriteByte(1,0); //高8位寫(xiě)入0x01
  296.                       delayms(5); //顯示2MS

  297.         //讀取數(shù)據(jù)  /*

  298.         Num_L = AT24C_ReadByte(0);
  299.         Num_H  |=AT24C_ReadByte(1)<<8;
  300.        Count= Num_H+Num_L;
  301. */
  302. while(1)
  303.         {
  304. /* Adjust();        
  305.           if (jia_up==0)   //增加按鍵按下                                                     
  306.                  {        
  307.                  while(!jia_up);//等待加按鍵松開(kāi)
  308.                   {   
  309.                      Set_Count += 1;         //設(shè)定+1
  310.                   }
  311.                }
  312.          if (jian_down==0)   //減少按鍵按下                                                     
  313.                 {        
  314.                          while(!jian_down);//等待按鍵松開(kāi)
  315.                                  {         
  316.                                    Set_Count -= 1;         //設(shè)定+1
  317.                                  }
  318.                   }
  319.                   if(yiwei_up==0) //保存按鍵按下,向AT24C寫(xiě)入數(shù)據(jù)
  320.                   {
  321.                          while(!yiwei_up); //等待移位按鍵松開(kāi)                        
  322.                            {
  323.                            AT24C_WriteByte(0,Set_Count%256);
  324.                        delayms(6) ; //顯示2MS
  325.                       AT24C_WriteByte(1,Set_Count/256);
  326.                       delayms(6); //顯示2MS
  327.                            }
  328.                 }           
  329.                
  330.                 if( qingling==0) //讀取按鍵按下
  331.                   {
  332.                          while(! qingling); //等待移位按鍵松開(kāi)                        
  333.                            {
  334.                              Count=AT24C_ReadByte(0);
  335.                              Count |=AT24C_ReadByte(1)<<8;
  336.                           // Count  = Num_H+Num_L;
  337.                            }
  338.                 }        */   
  339.         display();               
  340.      }
  341. }
復(fù)制代碼

gongyang.rar

19.96 KB, 下載次數(shù): 2

仿真文件

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

使用道具 舉報(bào)

沙發(fā)
ID:161164 發(fā)表于 2023-8-1 14:37 | 只看該作者

回復(fù)

使用道具 舉報(bào)

板凳
ID:1064915 發(fā)表于 2023-8-31 09:52 | 只看該作者
AT24C02程序沒(méi)問(wèn)題
回復(fù)

使用道具 舉報(bào)

地板
ID:313517 發(fā)表于 2023-9-3 15:22 | 只看該作者
你自己看看是不是符號(hào)IIC協(xié)議規(guī)范,用示波器看看電平的高低情況,有無(wú)過(guò)充超標(biāo),看看開(kāi)始結(jié)束時(shí)序,讀寫(xiě)時(shí)序?qū)Σ粚?duì)
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

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