查看: 6867|回复: 14

[求助] I2C程序无法读出EEPROM的数据

[复制链接]

该用户从未签到

16

主题

61

帖子

0

中级会员

Rank: 3Rank: 3

积分
404
最后登录
2022-6-10
发表于 2019-6-25 22:21:35 | 显示全部楼层 |阅读模式
同志们,这个问题折腾了4天了。请各位帮忙看看。EEPROM采用AT24C04,ARM是KEA128,死活读不出来数据,单字节读写也不行,不清楚是程序问题还是硬件问题。代码贴出来,大家帮忙看下。多谢,多谢。
有两个版本,一个是模拟I2C接口,一个是硬件I2C,接口:SDA是PA2,SCL是PA3。小弟不胜感激。
  1. #include "SKEAZ1284.h"
  2. #include "KEA_SysTick.h"
  3. #include "i2c.h"

  4. unsigned char ck;
  5. unsigned char date;

  6. void AT24CXX_WriteOneByte(unsigned  int  WriteAddr,unsigned char DataToWrite)
  7. {                                                                                                                                                                                          
  8.   I2C_Start(I2C0);  
  9.   I2C_WriteOneByte(I2C0,0XA0);
  10.   I2C_IsReceivedAck(I2C0);
  11.   I2C_WriteOneByte(I2C0,WriteAddr>>8);   //发送器件地址0XA0,写数据
  12.   I2C_IsReceivedAck(I2C0);          
  13.   I2C_WriteOneByte(I2C0,WriteAddr%256);   //发送低地址
  14.   I2C_IsReceivedAck(I2C0);                                                                                                              
  15.   I2C_WriteOneByte(I2C0,DataToWrite);     //发送字节                                                          
  16.   I2C_IsReceivedAck(I2C0);                                
  17.   I2C_Stop(I2C0);//产生一个停止条件
  18.   systick_delay_ms(10);         
  19. }
  20. //****************************************************************************
  21. //****************************************************************************
  22. //在AT24CXX指定地址读出一个数据
  23. //ReadAddr:开始读数的地址  
  24. //返回值  :读到的数据
  25. unsigned char AT24CXX_ReadOneByte(unsigned  int  ReadAddr)
  26. {                                  
  27.   unsigned char temp;                                                                                                                                                               
  28.   I2C_Start(I2C0);  
  29.   I2C_WriteOneByte(I2C0,0XA0);
  30.   I2C_IsReceivedAck(I2C0);
  31.   I2C_WriteOneByte(I2C0,ReadAddr>>8);   //发送器件地址0XA0,写数据          
  32.   I2C_IsReceivedAck(I2C0);
  33.   
  34.   I2C_WriteOneByte(I2C0,ReadAddr%256);   //发送低地址
  35.   I2C_IsReceivedAck(I2C0);            
  36.   I2C_Start(I2C0);           
  37.   I2C_WriteOneByte(I2C0,0XA1);    //进入接收模式                          
  38.   I2C_IsReceivedAck(I2C0);         
  39.   I2C_ReadOneByte(I2C0,&temp);                  
  40.   I2C_Stop(I2C0);//产生一个停止条件            
  41.   return temp;
  42. }


  43. //****************************************************************************
  44. //****************************************************************************

  45. void write_add(unsigned char address,unsigned char date)
  46. {
  47.   I2C_Start(I2C0);
  48.   I2C_WriteOneByte(I2C0,0xa0);
  49.   ck=I2C_IsReceivedAck(I2C0);
  50.   I2C_WriteOneByte(I2C0,address);
  51.   ck=I2C_IsReceivedAck(I2C0);
  52.   I2C_WriteOneByte(I2C0,date);
  53.   ck=I2C_IsReceivedAck(I2C0);
  54.   I2C_Stop(I2C0);
  55. }
  56. //****************************************************************************
  57. //****************************************************************************
  58. unsigned char read_add(unsigned char address)
  59. {
  60.   unsigned char date;
  61.   I2C_Start(I2C0);
  62.   I2C_WriteOneByte(I2C0,0xa0);
  63.   I2C_IsReceivedAck(I2C0);
  64.   I2C_WriteOneByte(I2C0,address);
  65.   I2C_IsReceivedAck(I2C0);
  66.   I2C_Start(I2C0);
  67.   I2C_WriteOneByte(I2C0,0xa1);
  68.   I2C_IsReceivedAck(I2C0);
  69.   I2C_ReadOneByte(I2C0,&date);
  70.   I2C_Stop(I2C0);
  71.   return date;
  72. }
  73. //****************************************************************************
  74. //****************************************************************************
  75. //在AT24CXX里面的指定地址开始写入长度为Len的数据
  76. //该函数用于写入16bit或者32bit的数据.
  77. //WriteAddr  :开始写入的地址  
  78. //DataToWrite:数据数组首地址
  79. //Len        :要写入数据的长度2,4
  80. void AT24CXX_WriteLenByte(unsigned  int  WriteAddr,unsigned long DataToWrite,unsigned char Len)
  81. {         
  82.   unsigned char t;
  83.   for(t=0;t<Len;t++)
  84.   {
  85.     AT24CXX_WriteOneByte(WriteAddr+t,(DataToWrite>>(8*t))&0xff);
  86.   }                                                                                                    
  87. }

  88. //在AT24CXX里面的指定地址开始读出长度为Len的数据
  89. //该函数用于读出16bit或者32bit的数据.
  90. //ReadAddr   :开始读出的地址
  91. //返回值     :数据
  92. //Len        :要读出数据的长度2,4
  93. unsigned long AT24CXX_ReadLenByte(unsigned  int  ReadAddr,unsigned char Len)
  94. {         
  95.   unsigned char t;
  96.   unsigned long temp=0;
  97.   for(t=0;t<Len;t++)
  98.   {
  99.     temp<<=8;
  100.     temp+=AT24CXX_ReadOneByte(ReadAddr+Len-t-1);                                            
  101.   }
  102.   return temp;                                                                                                    
  103. }
  104. //检查AT24CXX是否正常
  105. //这里用了24XX的最后一个地址(255)来存储标志字.
  106. //如果用其他24C系列,这个地址要修改
  107. //返回1:检测失败
  108. //返回0:检测成功
  109. unsigned char AT24CXX_Check(void)
  110. {
  111.   unsigned char temp;
  112.   temp=AT24CXX_ReadOneByte(255);//避免每次开机都写AT24CXX                          
  113.   if(temp==0X55)return 0;                  
  114.   else//排除第一次初始化的情况
  115.   {
  116.     AT24CXX_WriteOneByte(255,0X55);
  117.     temp=AT24CXX_ReadOneByte(255);          
  118.     if(temp==0X55)return 0;
  119.   }
  120.   return 1;                                                                                          
  121. }

  122. //在AT24CXX里面的指定地址开始读出指定个数的数据
  123. //ReadAddr :开始读出的地址 对24c02为0~255
  124. //pBuffer  :数据数组首地址
  125. //NumToRead:要读出数据的个数
  126. void AT24CXX_Read(unsigned  int ReadAddr,unsigned char *pBuffer,unsigned  int NumToRead)
  127. {
  128.   while(NumToRead)
  129.   {
  130.     *pBuffer++=AT24CXX_ReadOneByte(ReadAddr++);       
  131.     NumToRead--;
  132.   }
  133. }  
  134. //在AT24CXX里面的指定地址开始写入指定个数的数据
  135. //WriteAddr :开始写入的地址 对24c02为0~255
  136. //pBuffer   :数据数组首地址
  137. //NumToWrite:要写入数据的个数
  138. void AT24CXX_Write(unsigned  int WriteAddr,unsigned char *pBuffer,unsigned  int  NumToWrite)
  139. {
  140.   while(NumToWrite--)
  141.   {
  142.     AT24CXX_WriteOneByte(WriteAddr,*pBuffer);
  143.     WriteAddr++;
  144.     pBuffer++;
  145.   }
  146. }
复制代码
还有一个
  1. #include "SKEAZ1284.h"
  2. #include "KEA_SysTick.h"


  3. #define SDA_IN()   GPIOA->PDDR = GPIOA->PDDR&0xfffffffb;
  4. #define SDA_OUT()  GPIOA->PDDR |= 1<<2;


  5. #define IIC_SDA_1       GPIOA->PSOR |= 1<<2;
  6. #define IIC_SDA_0       GPIOA->PCOR |= 1<<2; //48 a2

  7. #define IIC_SCL_1       GPIOA->PSOR |= 1<<3;//47 a3
  8. #define IIC_SCL_0       GPIOA->PCOR |= 1<<3;

  9. #define READ_SDA        GPIOA->PDIR&0x04

  10. unsigned char ck;
  11. unsigned char date;

  12. void IIC_delay(void)    //????(???)
  13. {
  14.    uint8_t i=10;     
  15.    while(i)
  16.    {
  17.      i--;
  18.    }
  19. }

  20. //产生IIC起始信号
  21. void IIC_Start(void)
  22. {
  23.   SDA_OUT();     //sda线输出
  24.   IIC_SDA_1;                    
  25.   IIC_SCL_1;
  26.   IIC_delay();
  27.   IIC_SDA_0;//START:when CLK is high,DATA change form high to low
  28.   IIC_delay();
  29.   IIC_SCL_0;//钳住I2C总线,准备发送或接收数据
  30.   
  31. }          
  32. //产生IIC停止信号
  33. void IIC_Stop(void)
  34. {
  35.   SDA_OUT();//sda线输出
  36.   IIC_SCL_0;
  37.   IIC_SDA_0;//STOP:when CLK is high DATA change form low to high
  38.   IIC_delay();
  39.   IIC_SCL_1;  

  40.   IIC_SDA_1;//发送I2C总线结束信号
  41.   IIC_delay();
  42.   
  43. }
  44. //等待应答信号到来
  45. //返回值:1,接收应答失败
  46. //        0,接收应答成功
  47. unsigned char IIC_Wait_Ack(void)
  48. {
  49.   unsigned  int  ucErrTime=0;
  50.   
  51.   SDA_IN();      //SDA设置为输入
  52.   
  53.   IIC_SDA_1;IIC_delay();          
  54.   IIC_SCL_1;IIC_delay();
  55.   while((READ_SDA))
  56.   {
  57.     ucErrTime++;
  58.     if(ucErrTime>250)
  59.     {
  60.       IIC_Stop();
  61.       return 1;
  62.     }
  63.   }
  64.   IIC_SCL_0;//时钟输出0           
  65.   return 0;  
  66. }
  67. //产生ACK应答
  68. void IIC_Ack(void)
  69. {
  70.   IIC_SCL_0;
  71.   SDA_OUT();
  72.   IIC_SDA_0;
  73.   IIC_delay();
  74.   IIC_SCL_1;
  75.   IIC_delay();
  76.   IIC_SCL_0;
  77. }
  78. //不产生ACK应答                    
  79. void IIC_NAck(void)
  80. {
  81.   IIC_SCL_0;
  82.   SDA_OUT();
  83.   IIC_SDA_1;
  84.   IIC_delay();
  85.   IIC_SCL_1;
  86.   IIC_delay();
  87.   IIC_SCL_0;
  88. }                                                                              
  89. //IIC发送一个字节
  90. //返回从机有无应答
  91. //1,有应答
  92. //0,无应答                          
  93. void IIC_Send_Byte(unsigned char txd)
  94. {                        
  95.   unsigned char t;   
  96.   SDA_OUT();             
  97.   
  98.   for(t=0;t<8;t++)
  99.   {   

  100.             if(txd&0x80)
  101.               IIC_SDA_1
  102.             else
  103.               IIC_SDA_0

  104.       txd=txd<<1;
  105.       IIC_delay();
  106.    
  107.     IIC_SCL_1;
  108.     IIC_delay();
  109.     IIC_SCL_0;       
  110.     IIC_delay();
  111.   }         
  112. }
  113. //****************************************************************************
  114. //****************************************************************************


  115. //读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
  116. unsigned char IIC_Read_Byte(unsigned char ack)
  117. {
  118.   unsigned char i,receive=0;
  119.   SDA_IN();//SDA设置为输入
  120.   for(i=0;i<8;i++ )
  121.   {
  122.     IIC_SCL_0;
  123.     IIC_delay();
  124.     IIC_SCL_1;
  125.     receive<<=1;
  126.     if((READ_SDA))
  127.     receive++;   
  128.     IIC_delay();
  129.    
  130.   }                                         
  131.   if (!ack)
  132.     IIC_NAck();//发送nACK
  133.   else
  134.     IIC_Ack(); //发送ACK   
  135.   return receive;
  136. }
  137. void IIC_Init(void)
  138. {                                             
  139.   IIC_Stop();
  140.   
  141. }
  142. //****************************************************************************
  143. //****************************************************************************
  144. //在AT24CXX指定地址写入一个数据
  145. //WriteAddr  :写入数据的目的地址   
  146. //DataToWrite:要写入的数据
  147. void AT24CXX_WriteOneByte(unsigned  int  WriteAddr,unsigned char DataToWrite)
  148. {                                                                                                                                                                                          
  149.   IIC_Start();  
  150.   
  151.   IIC_Send_Byte(0XA0);   //发送器件地址0XA0,写数据
  152.   IIC_Wait_Ack();
  153.   IIC_Send_Byte(WriteAddr>>8);//发送高地址
  154.   IIC_Wait_Ack();          
  155.   IIC_Send_Byte(WriteAddr%256);   //发送低地址
  156.   IIC_Wait_Ack();                                                                                                              
  157.   IIC_Send_Byte(DataToWrite);     //发送字节                                                          
  158.   IIC_Wait_Ack();                                
  159.   IIC_Stop();//产生一个停止条件
  160.   systick_delay_ms(10);         
  161. }
  162. //****************************************************************************
  163. //****************************************************************************
  164. //在AT24CXX指定地址读出一个数据
  165. //ReadAddr:开始读数的地址  
  166. //返回值  :读到的数据
  167. unsigned char AT24CXX_ReadOneByte(unsigned  int  ReadAddr)
  168. {                                  
  169.   unsigned char temp=0;                                                                                                                                                               
  170.   IIC_Start();  
  171.   IIC_Send_Byte(0XA0);   //发送器件地址0XA0,写数据          
  172.   IIC_Wait_Ack();
  173.   IIC_Send_Byte(ReadAddr>>8);
  174.   IIC_Wait_Ack();
  175.   IIC_Send_Byte(ReadAddr%256);   //发送低地址
  176.   IIC_Wait_Ack();            
  177.   IIC_Start();                     
  178.   IIC_Send_Byte(0XA1);           //进入接收模式                          
  179.   IIC_Wait_Ack();         
  180.   temp=IIC_Read_Byte(0);                  
  181.   IIC_Stop();//产生一个停止条件            
  182.   return temp;
  183. }



  184. //在AT24CXX里面的指定地址开始读出指定个数的数据
  185. //ReadAddr :开始读出的地址 对24c02为0~255
  186. //pBuffer  :数据数组首地址
  187. //NumToRead:要读出数据的个数
  188. void AT24CXX_Read(unsigned  int ReadAddr,unsigned char *pBuffer,unsigned  int NumToRead)
  189. {
  190.   while(NumToRead)
  191.   {
  192.     *pBuffer++=AT24CXX_ReadOneByte(ReadAddr++);       
  193.     NumToRead--;
  194.   }
  195. }  
  196. //在AT24CXX里面的指定地址开始写入指定个数的数据
  197. //WriteAddr :开始写入的地址 对24c02为0~255
  198. //pBuffer   :数据数组首地址
  199. //NumToWrite:要写入数据的个数
  200. void AT24CXX_Write(unsigned  int WriteAddr,unsigned char *pBuffer,unsigned  int  NumToWrite)
  201. {
  202.   while(NumToWrite--)
  203.   {
  204.     AT24CXX_WriteOneByte(WriteAddr,*pBuffer);
  205.     WriteAddr++;
  206.     pBuffer++;
  207.   }
  208. }
复制代码


我知道答案 目前已有14人回答
回复

使用道具 举报

  • TA的每日心情
    开心
    2019-12-23 15:26
  • 签到天数: 6 天

    连续签到: 1 天

    [LV.2]偶尔看看I

    5

    主题

    20

    帖子

    0

    注册会员

    Rank: 2

    积分
    68
    最后登录
    2019-12-23
    发表于 2019-12-8 21:08:57 | 显示全部楼层
    怎么样了?解决没有?
    该会员没有填写今日想说内容.
    回复 支持 0 反对 1

    使用道具 举报

  • TA的每日心情
    奋斗
    前天 20:19
  • 签到天数: 1849 天

    连续签到: 4 天

    [LV.Master]伴坛终老

    203

    主题

    3万

    帖子

    64

    超级版主

    Rank: 8Rank: 8

    积分
    112633
    最后登录
    2025-7-22
    发表于 2019-6-26 10:14:17 | 显示全部楼层
    有没有逻辑分析仪,可以试着抓一下数据,看看是哪个地方的时序出问题了
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    14

    主题

    61

    帖子

    0

    高级会员

    Rank: 4

    积分
    569
    最后登录
    2022-2-11
    发表于 2019-6-27 14:16:40 | 显示全部楼层
    还么搞出来呀?
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    2021-7-8 09:06
  • 签到天数: 27 天

    连续签到: 1 天

    [LV.4]偶尔看看III

    18

    主题

    445

    帖子

    26

    金牌会员

    Rank: 6Rank: 6

    积分
    2302
    最后登录
    2025-5-15
    发表于 2019-6-27 14:44:23 | 显示全部楼层
    联机调试,看看卡死在哪了
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    16

    主题

    61

    帖子

    0

    中级会员

    Rank: 3Rank: 3

    积分
    404
    最后登录
    2022-6-10
     楼主| 发表于 2019-6-30 18:23:26 | 显示全部楼层
    stm1024 发表于 2019-6-26 10:14
    有没有逻辑分析仪,可以试着抓一下数据,看看是哪个地方的时序出问题了

    前段时间出差,准备这周用示波器看看波形。
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    16

    主题

    61

    帖子

    0

    中级会员

    Rank: 3Rank: 3

    积分
    404
    最后登录
    2022-6-10
     楼主| 发表于 2019-6-30 18:23:55 | 显示全部楼层
    anxb 发表于 2019-6-27 14:16
    还么搞出来呀?

    没有昂……程序都对过了,不知道是什么原因。前段时间出差,准备这周用示波器看看波形。
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    16

    主题

    61

    帖子

    0

    中级会员

    Rank: 3Rank: 3

    积分
    404
    最后登录
    2022-6-10
     楼主| 发表于 2019-6-30 18:24:29 | 显示全部楼层
    zmh169 发表于 2019-6-27 14:44
    联机调试,看看卡死在哪了

    是的,准备用示波器看看波形,等调试好了,得出个帖子总结下。
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    前天 20:19
  • 签到天数: 1849 天

    连续签到: 4 天

    [LV.Master]伴坛终老

    203

    主题

    3万

    帖子

    64

    超级版主

    Rank: 8Rank: 8

    积分
    112633
    最后登录
    2025-7-22
    发表于 2019-7-1 07:56:04 | 显示全部楼层
    yaomeng0725 发表于 2019-6-30 18:24
    是的,准备用示波器看看波形,等调试好了,得出个帖子总结下。

    有逻辑分析仪的话,直接用还方便一些,它可以带协议分析
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    24

    主题

    82

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    1239
    最后登录
    2022-1-7
    发表于 2019-7-18 20:10:07 | 显示全部楼层
    你好 请问调试出来了么 遇到一样的问题
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    16

    主题

    61

    帖子

    0

    中级会员

    Rank: 3Rank: 3

    积分
    404
    最后登录
    2022-6-10
     楼主| 发表于 2019-7-21 22:15:55 | 显示全部楼层
    byxzwz 发表于 2019-7-18 20:10
    你好 请问调试出来了么 遇到一样的问题

    我E2是从淘宝买的……不能用。换个大点的电子商城。
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2025-7-24 15:50 , Processed in 0.107070 second(s), 30 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表