標(biāo)題: 我的單片機(jī)+iic程序怎么讀寫(xiě)不了? 搞了好幾天搞不明白 [打印本頁(yè)]

作者: YANGTAIHUAN    時(shí)間: 2022-3-11 19:41
標(biāo)題: 我的單片機(jī)+iic程序怎么讀寫(xiě)不了? 搞了好幾天搞不明白
求求大佬們看看哪出問(wèn)題了,1602模塊沒(méi)問(wèn)題 仿真里讀出來(lái)的是一個(gè)黑塊  

at24c02.c
  1. #include <reg52.h>
  2. #include <intrins.h>
  3. #define uchar unsigned char
  4. #define uint unsigned int
  5.         
  6. sbit SCK = P1^3;
  7. sbit SDA = P1^4;

  8. void Delayms(uint x);
  9. void Delayus(uchar x);
  10. void Delay5us();
  11. void Delay5ms();

  12. void init(){
  13.         SCK = 1;
  14.         _nop_();_nop_();_nop_();
  15.         SDA = 1;
  16.         _nop_();_nop_();_nop_();
  17. }
  18. void start(){
  19.         SCK = 1;
  20.         _nop_();_nop_();_nop_();
  21.         SDA = 1;
  22.         _nop_();_nop_();_nop_();
  23.         _nop_();_nop_();_nop_();
  24.         SDA = 0;
  25.         _nop_();_nop_();_nop_();
  26.         _nop_();_nop_();_nop_();
  27.         SCK = 0;
  28. }
  29.         
  30. void stop(){
  31.         SCK  =1;
  32.         SDA = 0;
  33.         _nop_();_nop_();_nop_();
  34.         _nop_();_nop_();_nop_();
  35.         SDA = 1;
  36.         _nop_();_nop_();_nop_();
  37.         _nop_();_nop_();_nop_();
  38.         SDA = 0;
  39.         SCK = 0;
  40. }
  41. void WaitAck(){
  42.         uchar i = 0;
  43.         SDA = 1;
  44.         SCK = 1;
  45.         Delayus(5);
  46.         while(SDA == 1 && (i < 250))
  47.                 i++;
  48.         SCK = 0;
  49.         _nop_(), _nop_(), _nop_();
  50. }


  51. //void react(){
  52. //        SCK = 0;
  53. //        SDA = 1;
  54. //        SDA = 0;
  55. //        SCK = 1;
  56. //        _nop_();_nop_();_nop_();
  57. //        _nop_();_nop_();_nop_();
  58. //        SCK = 0;
  59. //        SDA = 1;
  60. //}
  61. void noack(){
  62.          SDA=1;
  63.          _nop_();_nop_();_nop_();
  64.          SCK=1;
  65.          _nop_();_nop_();_nop_();
  66.                 _nop_();_nop_();_nop_();
  67.          SCK=0;
  68.          _nop_();_nop_();_nop_();
  69.                 SDA = 0;
  70. }

  71. uchar readByte(){
  72.         uchar i, k = 0;
  73.         for(i = 0; i < 8; i++){
  74.                 SCK = 0;
  75.                 k <<= 1;
  76.                 Delay5us();        
  77.                 if(SDA == 1){
  78.                         k |= 0x01;
  79.                 }
  80.                 SCK = 0;
  81.                 Delay5us();
  82.         }
  83.         _nop_();
  84.         Delay5ms();
  85.         return k;
  86. }

  87. void writeByte(uchar dat){
  88.         uchar i = 0;
  89.         for(i = 0; i < 8; i++){
  90.                 SCK = 0;
  91.                 Delay5us();
  92.                 SDA = dat & 0x80;
  93.                 _nop_();_nop_();_nop_();_nop_();
  94.                 SCK = 1;
  95.                 Delay5us();
  96.                 dat <<= 1;
  97.         }
  98.         SCK = 0;
  99.         _nop_();_nop_();_nop_();
  100.         Delay5ms();
  101. }

  102. void addByte(uchar wordAddress, uchar dat){
  103.         start();
  104.         writeByte(0xa0);
  105.         WaitAck();
  106.         writeByte(wordAddress);
  107.         WaitAck();
  108.         writeByte(dat);
  109.         WaitAck();
  110.         stop();
  111.         Delayms(5);
  112. }

  113. uchar readAddByta(uchar wordAddress){
  114.         uchar dat;
  115.         start();
  116.         writeByte(0xa0);
  117.         WaitAck();
  118.         writeByte(wordAddress);
  119.         WaitAck();
  120.         stop();
  121.         start();
  122.         writeByte(0xa1);
  123.         WaitAck();
  124.         dat = readByte();
  125.         noack();
  126.         stop();
  127.         return dat;
  128. }

  129. void Delayms(uint x){
  130.         int i, j;
  131.         for(i = x; i > 0; --i){
  132.                 for(j = 110; j > 0; --j);
  133.         }
  134. }
  135. void Delayus(uchar x){
  136.         while(x--);
  137. }

  138. void Delay5us()                //@12.000MHz
  139. {
  140.         _nop_();
  141. }

  142. void Delay5ms()                //@12.000MHz
  143. {
  144.         unsigned char i, j;

  145.         i = 10;
  146.         j = 183;
  147.         do
  148.         {
  149.                 while (--j);
  150.         } while (--i);
  151. }
復(fù)制代碼

main.c
  1. #include <reg52.h>
  2. #include <intrins.h>
  3. #include "at24c02.h"
  4. #include "proteus_1602.h"
  5. #define uchar unsigned char
  6. #define uint unsigned int
  7. sbit SCK = P1^3;
  8. sbit SDA = P1^4;
  9. void main(){
  10.         Delayms(2000);
  11.         while(1){
  12.                 uchar temp = 0;
  13.                 init();
  14.                 init_1602();
  15.                 addByte(0x00, 0x00);
  16.                 Delayms(10);
  17.                 temp = readAddByta(0x00);
  18.                 writeData_1602(temp + 0x38);
  19.                 Delayms(50);
  20.         }         
  21. }
復(fù)制代碼




作者: YANGTAIHUAN    時(shí)間: 2022-3-11 19:42
1602模塊沒(méi)問(wèn)題 仿真里讀出來(lái)的是一個(gè)黑塊  
作者: tatachaoren    時(shí)間: 2022-3-12 02:56
IIC的時(shí)序很重要,最好嘗試的用邏輯分析儀讀一下時(shí)序,看看是不是時(shí)序出現(xiàn)問(wèn)題,還有如果時(shí)序沒(méi)問(wèn)題的話,要看時(shí)間,比如起始信號(hào),一高一低時(shí)間會(huì)不會(huì)太短,導(dǎo)致從機(jī)識(shí)別不了IIC的起始信號(hào)等等。
作者: lkc8210    時(shí)間: 2022-3-12 08:09
要貼就貼全一點(diǎn)
為什么不把a(bǔ)t24c02.h/proteus_1602.h/proteus_1602.c也貼上來(lái)?

void WaitAck(){
        uchar i = 0;
        SDA = 0;
        SCK = 1;
        Delayus(5);
        while(SDA == 1 && (i < 250))
                i++;
        SCK = 0;
        _nop_(), _nop_(), _nop_();
}
作者: wolfinn    時(shí)間: 2022-3-13 10:53
讀寫(xiě)兩句間加個(gè)延時(shí)看看,器件兩個(gè)動(dòng)作要有間隔的。
作者: Lxy18    時(shí)間: 2022-3-13 11:56
iic通信和晶振頻率24c02的地址都有關(guān)系,錯(cuò)一點(diǎn)都可能導(dǎo)致通信失敗。
分享一下自用的驅(qū)動(dòng)程序,僅供參考。
晶振12MHz或者11.0592MHz,24c02的3個(gè)地址全接地。
at24c02.c
  1. #include "at24c02.h"
  2. #include "delay.h"

  3. //IIC啟動(dòng)
  4. void Start(void)
  5. {
  6.         SDA1=1;
  7.         Delay_Us(2);
  8.         SCL1=1;
  9.         Delay_Us(2);//建立時(shí)間是SDA保持時(shí)間>4.7us
  10.         SDA1=0;
  11.         Delay_Us(2);//保持時(shí)間是>4us
  12.         SCL1=0;                       
  13.         Delay_Us(2);
  14. }
  15. //IIC停止
  16. void Stop(void)
  17. {
  18.         SDA1=0;
  19.         Delay_Us(2);
  20.         SCL1=1;
  21.         Delay_Us(2);//建立時(shí)間大于4.7us
  22.         SDA1=1;
  23.         Delay_Us(4);               
  24. }
  25. //IIC發(fā)送字節(jié)
  26. //dat:要發(fā)送的字節(jié)
  27. void Send_Byte(unsigned char dat)
  28. {
  29.         unsigned char a=0,b=0;
  30.         for(a=0;a<8;a++)//要發(fā)送8位,從最高位開(kāi)始
  31.         {
  32.                 SDA1=dat>>7;         //起始信號(hào)之后SCL=0,所以可以直接改變SDA信號(hào)
  33.                 dat=dat<<1;
  34.                 Delay_Us(2);
  35.                 SCL1=1;
  36.                 Delay_Us(2);//建立時(shí)間>4.7us
  37.                 SCL1=0;
  38.                 Delay_Us(2);//時(shí)間大于4us
  39.         }       
  40. }
  41. //IIC檢查應(yīng)答
  42. bit Check_Ack(void)
  43. {
  44.         //unsigned char t;
  45.         SCL1=0;
  46.         SDA1=1;
  47.         Delay_Us(2);
  48.         SCL1=1;
  49.         Delay_Us(2);
  50.         CY=SDA1;
  51.         SCL1=0;
  52.         Delay_Us(2);       
  53.         return(CY);
  54. }
  55. //IIC應(yīng)答
  56. void Ack(void)
  57. {
  58.         SDA1=0;   //EEPROM通過(guò)在收到每個(gè)地址或數(shù)據(jù)之后
  59.         SCL1=1;   //置SDA低電平的方式確認(rèn)表示收到讀SDA口狀態(tài)
  60.         Delay_Us(1);
  61.         SCL1=0;
  62.         Delay_Us(1);
  63.         SDA1=1;
  64. }
  65. //IIC無(wú)應(yīng)答
  66. void NoAck(void)
  67. {
  68.         SDA1=1;
  69.         SCL1=1;
  70.         Delay_Us(1);
  71.         SCL1=0;
  72. }
  73. //IIC接收字節(jié)
  74. unsigned char Receive_Byte(void)
  75. {
  76.         unsigned char a=0,dat=0;
  77.         SDA1=1;                        //起始和發(fā)送一個(gè)字節(jié)之后SCL都是0
  78.         Delay_Us(2);
  79.         for(a=0;a<8;a++)//接收8個(gè)字節(jié)
  80.         {
  81.                 SCL1=1;
  82.                 Delay_Us(2);
  83.                 dat<<=1;
  84.                 dat|=SDA1;
  85.                 Delay_Us(2);
  86.                 SCL1=0;
  87.                 Delay_Us(2);
  88.         }
  89.         return dat;               
  90. }
  91. //At24cxx讀寫(xiě)數(shù)據(jù)
  92. //addr:要讀/寫(xiě)數(shù)據(jù)的地址
  93. //*dat:要讀/寫(xiě)的數(shù)據(jù)
  94. //length;數(shù)據(jù)的長(zhǎng)度
  95. //RW:1:寫(xiě),0:讀
  96. void At24c02_RW(unsigned char addr,unsigned char *dat,unsigned char length,bit RW)
  97. {
  98.         Start();
  99.         Send_Byte(0xa0);//發(fā)送寫(xiě)器件地址
  100.         Check_Ack();
  101.         Send_Byte((unsigned char)addr);//發(fā)送要寫(xiě)入內(nèi)存地址
  102.         Check_Ack();
  103.         if(RW)                 //寫(xiě)
  104.         {        while(length--)
  105.                 {
  106.                         Send_Byte(*dat++);
  107.                         Check_Ack();       
  108.                 }
  109.         }
  110.         else
  111.         {
  112.                 Start();
  113.                 Send_Byte(0xa1);
  114.                 Check_Ack();
  115.                 while(--length)
  116.                 {
  117.                         *dat++=Receive_Byte();
  118.                          Ack();
  119.                 }
  120.                 *dat=Receive_Byte();//讀取最后一個(gè)字節(jié)
  121.                 NoAck();
  122.         }
  123.         Stop();
  124.         if(RW)
  125.         Delay_Us(1000);
  126. }

復(fù)制代碼


at24c02.h
  1. #ifndef __AT24C02_H__
  2. #define __AT24C02_H__

  3. #include<reg52.h>

  4. sbit SCL1=P2^1;
  5. sbit SDA1=P2^0;

  6. void Start(void);
  7. void Stop(void);
  8. bit Check_Ack(void);
  9. void Ack(void);
  10. void NoAck(void);
  11. void Send_Byte(unsigned char dat);
  12. unsigned char Receive_Byte(void);
  13. void At24c02_RW(unsigned char addr,unsigned char *dat,unsigned char length,bit RW);

  14. #endif
復(fù)制代碼


delay.c
  1. #include "delay.h"

  2. /*******************************************************************************
  3. * 函 數(shù) 名         : Delay_Us()
  4. * 函數(shù)功能                   : 延時(shí)1us
  5. * 輸    入         : i
  6. * 輸    出         : 無(wú)
  7. *******************************************************************************/
  8. void Delay_Us(int i)
  9. {
  10.         while(i--);
  11. }
  12. /*******************************************************************************
  13. * 函 數(shù) 名         : Delay_Ms()
  14. * 函數(shù)功能                   : 延時(shí)1Ms
  15. * 輸    入         : m
  16. * 輸    出         : 無(wú)
  17. *******************************************************************************/
  18. void Delay_Ms(int m)
  19. {
  20.         while(m--)
  21.         {
  22.                  Delay_Us(125);
  23.         }
  24. }
復(fù)制代碼





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