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

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

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

單片機iic連續讀取epprom出錯的問題解決

[復制鏈接]
跳轉到指定樓層
樓主
現象:單個讀取字符正確,連續讀取字符出錯環境:stc89c52單片機  24C02的epprom
我的解決辦法:
IIC_wirte 8bit時等待ack,如無ack,則stop-->start 重新發起信號,結果解決問題,下面貼出代碼:

  1. #include <reg52.h>
  2. #include "intrins.h"
  3. #include "type.h"
  4. #include "i2c.h"

  5. sbit SCL=P2^1;
  6. sbit SDA=P2^0;

  7. #define IIC_WRITE 0xA0
  8. #define IIC_READ 0xA1

  9. static void delay10Us(u16 i)
  10. {
  11.         while(i--);
  12. }

  13. /*******************************************************************************
  14. * 函數名         : Delay10us()
  15. * 函數功能                   : 延時10us
  16. * 輸入           : 無
  17. * 輸出                  : 無
  18. *******************************************************************************/
  19. /*
  20. void Delay10us()
  21. {
  22. }
  23. */
  24. /*******************************************************************************
  25. * 函數名         : I2cStart()
  26. * 函數功能                 : 起始信號:在SCL時鐘信號在高電平期間SDA信號產生一個下降沿
  27. * 輸入           : 無
  28. * 輸出                  : 無
  29. * 備注           : 起始之后SDA和SCL都為0
  30. *******************************************************************************/

  31. void I2cStart()
  32. {
  33.         SCL=0;
  34.         delay10Us(1);
  35.         SDA=1;
  36.         SCL=1;
  37.         delay10Us(1);//建立時間是SDA保持時間>4.7us
  38.         SDA=0;
  39.         delay10Us(1);//保持時間是>4us
  40. }
  41. /*******************************************************************************
  42. * 函數名         : I2cStop()
  43. * 函數功能                 : 終止信號:在SCL時鐘信號高電平期間SDA信號產生一個上升沿
  44. * 輸入           : 無
  45. * 輸出                  : 無
  46. * 備注           : 結束之后保持SDA和SCL都為1;表示總線空閑
  47. *******************************************************************************/

  48. void I2cStop()
  49. {
  50.         SCL=0;
  51.         delay10Us(1);
  52.         SDA=0;
  53.         SCL=1;
  54.         delay10Us(1);
  55.         SDA=1;
  56.         delay10Us(1);
  57. }
  58. /*******************************************************************************
  59. * 函數名         : I2cSendByte(unsigned char dat)
  60. * 函數功能                 : 通過I2C發送一個字節。在SCL時鐘信號高電平期間,保持發送信號SDA保持穩定
  61. * 輸入           : num
  62. * 輸出                  : 0或1。發送成功返回1,發送失敗返回0
  63. * 備注           : 發送完一個字節SCL=0,SDA=1
  64. *******************************************************************************/

  65. unsigned char I2cSendByte(unsigned char dat)
  66. {
  67.         unsigned char a=0,b=0;//最大255,一個機器周期為1us,最大延時255us。        
  68.         SCL=0;
  69.         delay10Us(1);
  70.         for(a=0;a<8;a++)//要發送8位,從最高位開始
  71.         {
  72.                 SDA = dat>>7;         //起始信號之后SCL=0,所以可以直接改變SDA信號
  73.                 dat = dat<<1;
  74.                 delay10Us(1);
  75.                 SCL=1;
  76.                 delay10Us(2);
  77.                 SCL=0;
  78.                 delay10Us(1);               
  79.         }
  80.         SDA=1;
  81.         delay10Us(1);
  82.         SCL=1;
  83.         while(SDA)//等待應答,也就是等待從設備把SDA拉低
  84.         {
  85.                 b++;
  86.                 if(b>200)         //如果超過2000us沒有應答發送失敗,或者為非應答,表示接收結束
  87.                 {
  88.                         return 0;
  89.                 }
  90.                 delay10Us(1);
  91.         }
  92.         
  93.          return 1;               
  94. }
  95. /*******************************************************************************
  96. * 函數名         : I2cReadByte()
  97. * 函數功能                   : 使用I2c讀取一個字節
  98. * 輸入           : 無
  99. * 輸出                  : dat
  100. * 備注           : 接收完一個字節SCL=0,SDA=1.
  101. *******************************************************************************/

  102. unsigned char I2cReadByte()
  103. {
  104.         unsigned char a=0,dat=0;
  105.         SCL = 0;
  106.         delay10Us(1);
  107.         SDA=1;                        //起始和發送一個字節之后SCL都是0
  108.         delay10Us(1);
  109.         for(a=0;a<8;a++)//接收8個字節
  110.         {
  111.                 SCL=1;
  112.                 delay10Us(2);
  113.                 dat<<=1;
  114.                 dat|=SDA;
  115.                 SCL=0;
  116.                 delay10Us(1);
  117.         }
  118.         return dat;               
  119. }


  120. /*******************************************************************************
  121. * 函數名         : void At24c02Write(unsigned char addr,unsigned char dat)
  122. * 函數功能                   : 往24c02的一個地址寫入一個數據
  123. * 輸入           : 無
  124. * 輸出                  : 無
  125. *******************************************************************************/

  126. void At24c02Write(unsigned char addr,unsigned char dat)
  127. {
  128.         unsigned char ret;
  129. again:
  130.         I2cStart();
  131.         ret = I2cSendByte(IIC_WRITE);//發送寫器件地址
  132.         if(!ret){
  133.                 I2cStop();
  134.                 goto again;
  135.         }
  136.         ret = I2cSendByte(addr);//發送要寫入內存地址
  137.         if(!ret){
  138.                 I2cStop();
  139.                 goto again;
  140.         }
  141.         ret = I2cSendByte(dat);        //發送數據
  142.         if(!ret){
  143.                 I2cStop();
  144.                 goto again;
  145.         }
  146.         I2cStop();
  147. }

  148. /*******************************************************************************
  149. * 函數名         : unsigned char At24c02Read(unsigned char addr)
  150. * 函數功能                   : 讀取24c02的一個地址的一個數據
  151. * 輸入           : 無
  152. * 輸出                  : 無
  153. *******************************************************************************/

  154. unsigned char At24c02Read(unsigned char addr)
  155. {
  156.         unsigned char num;
  157.         unsigned char ret;
  158. again:
  159.         I2cStart();
  160.         ret = I2cSendByte(IIC_WRITE); //發送器件寫地址
  161.         if(!ret){
  162.                 I2cStop();
  163.                 goto again;
  164.         }
  165.         ret = I2cSendByte(addr); //發送要讀取的地址
  166.         if(!ret){
  167.                 I2cStop();
  168.                 goto again;
  169.         }
  170.         I2cStart();
  171.         ret = I2cSendByte(IIC_READ); //發送讀器件地址
  172.         if(!ret){
  173.                 I2cStop();
  174.                 goto again;
  175.         }
  176.         num=I2cReadByte(); //讀取數據
  177.         NoAck();
  178.         I2cStop();
  179.         return num;        
  180. }

  181. /*
  182. 非應答
  183. */
  184. void NoAck(void)
  185. {
  186.         SCL=0;
  187.         SDA=1;
  188.         delay10Us(1);
  189.         SCL=1;
  190.         delay10Us(2);
  191. }

  192. /*
  193. 應答信號
  194. */
  195. void Ack(void)
  196. {
  197.         SCL=0;
  198.         SDA=0;
  199.         delay10Us(1);
  200.         SCL=1;
  201.         delay10Us(2);
  202. }
  203. /*******************************************************************************
  204. * 函數名         : unsigned char At24c02Read(unsigned char addr)
  205. * 函數功能                   : 讀取24c02的一個地址的一個數據
  206. * 輸入           : 無
  207. * 輸出                  : -1:error 0:success
  208. *******************************************************************************/

  209. void At24c02ReadBytes(unsigned char addr,unsigned char *dat,unsigned char n)
  210. {
  211.         //unsigned char num = n;
  212.         unsigned char ret;
  213. again:
  214.         I2cStart();
  215.         ret=I2cSendByte(0xa0); //發送寫器件地址
  216.         if(!ret){
  217.                 I2cStop();
  218.                 goto again;
  219.         }
  220.         ret=I2cSendByte(addr); //發送要讀取的地址
  221.         if(!ret){
  222.                 I2cStop();
  223.                 goto again;
  224.         }
  225.         I2cStart();
  226.         ret=I2cSendByte(0xa1); //發送讀器件地址
  227.         if(!ret){
  228.                 I2cStop();
  229.                 goto again;
  230.         }
  231.         if(addr + n >256)
  232.         {
  233.                 n = 256 - addr;
  234.         }
  235.         while(n--)
  236.         {
  237.                 *dat = I2cReadByte(); //讀取數據
  238.                 if(n!=0) Ack();
  239.                 dat++;
  240.         }
  241.         I2cStop();
  242.         //return num;        
  243. }

  244. /*******************************************************************************
  245. * 函數名         : unsigned char At24c02Read(unsigned char addr)
  246. * 函數功能                   : 讀取24c02的一個地址的一個數據
  247. * 輸入           : 無
  248. * 輸出                  : 無
  249. *******************************************************************************/

  250. /*******************************************************************************
  251. * 函數名         : void At24c02ReadBytes2(unsigned char addr,unsigned char *dat,unsigned char n)
  252. * 函數功能                 : 從地址addr開始,連續讀取n個字符,讀取字符放入dat中
  253. * 輸入           : 無
  254. * 輸出                  : 無
  255. *******************************************************************************/

  256. void At24c02ReadBytes2(unsigned char addr,unsigned char *dat,unsigned char n)
  257. {
  258.         unsigned char i;
  259.         for(i=0;i<n;i++)
  260.                 dat[i]= At24c02Read(addr+i);
  261. }
  262. /*******************************************************************************
  263. * 函數名         : void At24c02ReadBytes2(unsigned char addr,unsigned char *dat,unsigned char n)
  264. * 函數功能                 : 將dat中的字符寫入addr開始的epprom中去,寫入n個
  265. * 輸入           : 無
  266. * 輸出                  : 無
  267. *******************************************************************************/

  268. void At24c02WriteBytes(unsigned char addr,unsigned char *dat,unsigned char n)
  269. {
  270.         unsigned char i;
  271.         for(i=0;i<n;i++)
  272.         {
  273.                 At24c02Write(addr+i,dat[i]);
  274.         }
  275. }
復制代碼
上訴代碼的關鍵點在 I2cSendByte 這個方法有返回值,當I2cSendByte的返回值是1說明成功
1、在At24c02Write函數中利用goto語句來處理出錯;
2、At24c02Read 利用goto語句來處理地址寫出錯
3、At24c02ReadBytes 同上
總結:
1、在iic的連續read過程一定要有ACK
2、起始信號之后的器件地址寫,存儲器地址、器件地址讀 這三個地址時,確保收到epprom發來的ack

單片機交流學習群:

評分

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

查看全部評分

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

使用道具 舉報

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

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 在线欧美亚洲 | 亚洲国产精品一区二区三区 | 日韩免费 | 亚洲精品无人区 | 国产日韩一区二区 | 一级黄色片网站 | 综合色影院 | 久久国产精品久久久久 | 久久国产精品一区二区三区 | 亚洲 中文 欧美 | 国产精品精品视频一区二区三区 | 中文字幕 国产精品 | 国产成人综合一区二区三区 | 一区二区日本 | 91精品在线看 | 欧美激情综合色综合啪啪五月 | 欧美在线视频一区二区 | 午夜三级网站 | 日韩av网址在线观看 | 亚洲成人综合在线 | 91精品久久久久久久 | 美女视频一区 | 涩在线| 国产一区二区三区在线看 | 中文字幕视频一区二区 | 99精品一区二区三区 | 中文字幕黄色大片 | 国产精品国产馆在线真实露脸 | 亚洲一区自拍 | 亚洲乱码一区二区三区在线观看 | 国产日产精品一区二区三区四区 | 午夜在线免费观看视频 | 99re热精品视频国产免费 | 精品国产免费人成在线观看 | 一区二区三区国产好的精 | 日韩成人在线观看 | 久久国产精品免费 | 午夜激情视频在线 | 国产精品免费一区二区三区四区 | 午夜性色a√在线视频观看9 | 在线91|