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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1824|回復: 3
收起左側

單片機+AT24C02為啥讀寫錯誤?

[復制鏈接]
ID:611626 發表于 2023-8-1 12:59 | 顯示全部樓層 |閱讀模式
  1. /****************************************************************
  2. AT24C前四位固定為1010 A1-A2由管腳電平默認接地,最后一位表示讀寫操作所以AT24C讀地址0xa1 寫地址0xa0
  3. 寫AT24C02的時候從器件地址為10100 0000,(0xa0),讀AT24C02的時候從器件地址為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寫地址
  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;//移位計數

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

  21. sbit Start_Dianji=P3^0; //電機啟動_dianji
  22. sbit  forward=P3^1; //正轉檢測
  23. //sbit  back=P3^1;    //反轉檢測
  24. sbit  run=P3^7;      //運行信號
  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};         //共陰數碼管編碼0-9
  30. uchar data Ledbuff[8]={1};//顯示緩沖區

  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. 產生總線起始信號
  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為高時拉低SDA,即為起始信號
  53. //    I2CDelay_us(5);
  54.         I2C_SCL=0; //在拉低 SCL,鉗住I2C總線準備發送或接收數據
  55. }
  56. /***********************
  57. 產生總線停止信號:先拉低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發送一個字節數據
  75. *@param Byte要發送的字節
  76. *@retval 無
  77. 起始信號后必須送一個從機地址(7)位,1-7位為要接收器件的地址,第八位讀寫位0發送1接收,第9位ACK應答位,
  78. 緊接著為第一個數據字節,然后一位應答位ACK后面繼續第二個數據字節
  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讀取 接收一個字節
  92. *@param 無
  93. *@retval  讀取 接收到的一個字節數據
  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發送應答Ack
  109. *@param AckBit應答位 0為應答(成功) 1為非應答(失敗)
  110. *@retval 無
  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接收應答位
  120. *@param 無
  121. *@retval AckBit應答位 0為應答(成功) 1為非應答(失敗)
  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寫數據***********
  133. *@brief AT24C寫入一個字節
  134. *@param WordAddress要寫入字節的地址
  135. *@param Data要寫入的數據
  136. *@retval無
  137. 寫多字節時,寫入一個字節。在寫一個字節前,必須延時5ms
  138. ************************/
  139. void AT24C_WriteByte(unsigned char WordAddress,Data)
  140. {
  141.   I2C_Start();//啟動總線
  142.   I2C_SendByte(AT24C02_ADDRESS);//發送寫操作地址+寫數據(0xa0)
  143.         I2C_ReceiveAck();                      //等待應答
  144.         I2C_SendByte(WordAddress);//要寫入的地址
  145.         I2C_ReceiveAck();       //等待應答完成
  146.    I2C_SendByte(Data);  //要寫入的數據,第一字節 ,第二字節注意:每個字節都回應一個應答位0,如果沒有回應說明寫入不成功
  147.         I2C_ReceiveAck();       //等待完成  注意:每個字節都回應一個應答位0,如果沒有回應說明寫入不成功
  148.         I2C_Stop(); //發送結束信號:停止總線
  149. }
  150. /************從AT24C中讀出數據*********
  151. *@brief AT24C讀取一個字節
  152. *@param WordAddress要讀出字節的地址
  153. *@param 無
  154. *@retval要讀出的數據
  155. ************************/
  156. unsigned char AT24C_ReadByte(unsigned char WordAddress) //void
  157. {
  158.         unsigned char Data;
  159.   I2C_Start();                    //發送起始信號:啟動總線
  160.    I2C_SendByte(AT24C02_ADDRESS);  //接上首字節,發送器件寫操作地址+寫數據(0xa0)這里寫操作時維綸把所要讀的數據地址AT24C02_ADDRESS通知讀取哪個地址信息
  161.         I2C_ReceiveAck(); //等待完成應答
  162.         I2C_SendByte(WordAddress);//發送要讀取內存的地址(WORD ADDRESS)
  163.         I2C_ReceiveAck();       //等待應答完成
  164.          I2C_Start();//在次啟動總線
  165.         I2C_SendByte(AT24C02_ADDRESS| 0x01);  //對E2PROM進行讀操作(0XA1)E2PROM會自動向主機發回數據,讀取一個字節后回應一個應答位,后會繼續傳送下一個地址的數據0xa1
  166.         I2C_ReceiveAck();       //等待完成
  167.         Data= I2C_ReceiveByte();  //要讀出的數據到Data
  168.    I2C_SendAck(1);       //等待完成::如果不想讀了,就發送一個非應答位NAK(1),發送結束,停止總線
  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)//使用多分支選擇語句 i=count display 0x代表16進制
  185.         {
  186.                 case(0):Ledbuff[7]=Set_Count/1000;break;   //取設定千位字符送緩存
  187.                 case(1):Ledbuff[6]=Set_Count/100%10;break; //取設定百位字符送緩沖
  188.                 case(2):Ledbuff[5]=Set_Count/10%10;break;   //取設定十位字符送緩沖
  189.                 case(3):Ledbuff[4]=Set_Count%10;break;     //取設定個位字符送緩存
  190.                   
  191.                 case(4):Ledbuff[3]=Count/1000;break;         //取計數千位字符送緩存
  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;   //消陰:段碼全部低電平關閉
  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)        //按鍵設定匝數,用P2.4個位-P2.7(千位)前四位數碼管顯示
  204.   {        
  205.            
  206.                 if(yiwei_up==0) //移位按鍵按下
  207.                   {
  208.                          while(!yiwei_up); //等待移位按鍵松開
  209.                          if(yiwei_Count<3) //移位
  210.                            {
  211.                             yiwei_Count +=1;
  212.                            }
  213.                    else       //如果>3
  214.           {                 
  215.             yiwei_Count=0;       //設定位在個位
  216.           }                                
  217.                    }
  218.                
  219.                 if(Set_Count>=0 && Set_Count<9999)//最大9999yiwei_Count=0; //設定加 jia_up==0
  220.                   {
  221.                                   if (jia_up==0)   //增加按鍵按下                                                     
  222.                                          {        
  223.                                            while(!jia_up);//等待加按鍵松開
  224.                                                   {
  225.                              if (yiwei_Count==0)        //               
  226.                              {
  227.                                      Set_Count += 1;         //設定+1
  228.                              }
  229.                                                           if (yiwei_Count==1&&Set_Count<9990)
  230.                                                                  {
  231.                                      Set_Count += 10;         //設定+1
  232.                               }
  233.                                                           if (yiwei_Count==2&&Set_Count<9900)
  234.                                                                  {
  235.                                      Set_Count += 100;         //設定+1
  236.                              }        
  237.                                                                 if (yiwei_Count==3 && Set_Count<9000)
  238.                                                                  {
  239.                                      Set_Count += 1000;         //設定+1
  240.                              }
  241.                                                   }        
  242.                                          }        
  243.                  if (jian_down==0)   //減少按鍵按下                                                     
  244.                                 {        
  245.                                            while(!jian_down);//等待按鍵松開
  246.                                                  {
  247.                              if (yiwei_Count==0&&Set_Count>1)        //        移位在個位        
  248.                               {
  249.                                       Set_Count -= 1;         //設定+1
  250.                               }
  251.                                                           if (yiwei_Count==1&&Set_Count>9)
  252.                                                                    {
  253.                                       Set_Count -= 10;         //設定+1
  254.                                }
  255.                                                           if (yiwei_Count==2 && Set_Count>99)
  256.                                                                    {
  257.                                       Set_Count -= 100;         //設定+1
  258.                                }        
  259.                                                                  if (yiwei_Count==3 && Set_Count>999)
  260.                                                                    {
  261.                                        Set_Count -= 1000;         //設定+1
  262.                                }
  263.                                                  }        
  264.                                                  //寫入數據
  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. 主函數
  273. **********************************************************/               
  274. void main()
  275. {
  276.         I2C_init();
  277. //        init();        //初始化24C02
  278.         //        num=5678;          //num為小于等于65535的整數。   */
  279.         Set_Count=1234;

  280.        Num_H  =Set_Count/256;  //1234/256就簡單了,高位:取的是整數倍,不被整除的部分自然就被剔除了1234/256=4
  281.         Num_L =Set_Count%256;  //%256是取余,低位:也就是你把前面的數值除以256取余,商跟除數則是256的整數倍部分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單元存儲num十六進制表示時的低兩位
  287.         num2=AT24C_ReadByte(1);        //用地址0單元存儲num十六進制表示時的高兩位
  288.         Count=num2*256+num1;
  289.    //寫入24C02
  290.               //       AT24C_WriteByte(0,Set_Count%256); //低8位寫入0x00
  291.    /*
  292.     AT24C_WriteByte(0,120); //低8位寫入0x00
  293.                        delayms(5); //顯示2MS

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

  297.         //讀取數據  /*

  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);//等待加按鍵松開
  308.                   {   
  309.                      Set_Count += 1;         //設定+1
  310.                   }
  311.                }
  312.          if (jian_down==0)   //減少按鍵按下                                                     
  313.                 {        
  314.                          while(!jian_down);//等待按鍵松開
  315.                                  {         
  316.                                    Set_Count -= 1;         //設定+1
  317.                                  }
  318.                   }
  319.                   if(yiwei_up==0) //保存按鍵按下,向AT24C寫入數據
  320.                   {
  321.                          while(!yiwei_up); //等待移位按鍵松開                        
  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); //等待移位按鍵松開                        
  333.                            {
  334.                              Count=AT24C_ReadByte(0);
  335.                              Count |=AT24C_ReadByte(1)<<8;
  336.                           // Count  = Num_H+Num_L;
  337.                            }
  338.                 }        */   
  339.         display();               
  340.      }
  341. }
復制代碼

gongyang.rar

19.96 KB, 下載次數: 2

仿真文件

回復

使用道具 舉報

ID:161164 發表于 2023-8-1 14:37 | 顯示全部樓層
51hei_Cap_.png
回復

使用道具 舉報

ID:1064915 發表于 2023-8-31 09:52 | 顯示全部樓層
AT24C02程序沒問題
回復

使用道具 舉報

ID:313517 發表于 2023-9-3 15:22 | 顯示全部樓層
你自己看看是不是符號IIC協議規范,用示波器看看電平的高低情況,有無過充超標,看看開始結束時序,讀寫時序對不對
回復

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 尤物在线 | 美女福利视频一区 | 伊人色综合久久天天五月婷 | 精品国产乱码久久久久久牛牛 | 欧美在线国产精品 | 午夜影院网站 | 在线观看国产精品一区二区 | 久久久久久艹 | 日本一区二区高清不卡 | 手机av在线 | 亚洲精品国产综合区久久久久久久 | 国产精品久久久久久久白浊 | 欧美精品二区 | 欧美成人在线网站 | 国产成人免费视频网站高清观看视频 | 欧美在线高清 | 国产日韩欧美精品一区二区三区 | 毛片a | 国产福利91精品一区二区三区 | 久久久久久久国产精品视频 | 免费一看一级毛片 | 久久久精品一区二区三区 | 久久久久久久久久久久91 | 精品一二区| 亚洲精品3 | 欧美成人a∨高清免费观看 91伊人 | 超碰婷婷| 久久中文视频 | 国产精品一区在线 | 亚洲欧美日韩国产综合 | 一区二区精品在线 | 亚洲国产欧美国产综合一区 | 日韩成人精品视频 | 久久久久99 | 国产精品久久久久久久久大全 | 国产一区91精品张津瑜 | 亚洲一区二区三区桃乃木香奈 | 亚洲美女天堂网 | 精品一区二区三区免费视频 | 国产福利在线 | 成人av免费网站 |