I2C读写程序帮忙看下哪里出错

[复制链接]
4394|10
 楼主| t86964988 发表于 2009-12-24 19:07 | 显示全部楼层 |阅读模式
我写了个I2C的读写程序 在24C02的地址23中写入值0x3f 然后再读出来 通过P0口让数码管显示0 程序不知道哪里错了 有高手帮忙看下吗?硬件如下:24C02 scl 接单片机的P1.1口 sda接单片机的P1.2口 wp接单片机的P1.0口 单片机的P0口接锁存器然后接数码管的段选 P2口接数码管的片选
#include<reg52.h>
#define uchar unsigned char
sbit sda=P1^2;
sbit scl=P1^1;
sbit wp=P1^0;
uchar a;
void delay()
{ ;; }
void start()  //开始信号
{        
        sda=1;
        delay();
        scl=1;
        delay();
        sda=0;
        delay();
}

void stop()   //停止
{
        sda=0;
        delay();
        scl=1;
        delay();
        sda=1;
        delay();
}

void respons()  //应答
{
        uchar i;
        scl=1;
        delay();
        while((sda==1)&&(i<250))i++;
        delay();
        scl=0;
        delay();
}

void init()//初始化
{
        sda=1;
        delay();
        scl=1;
        delay();
}

void write_byte(uchar date)//写一个字节数据
{
        uchar i,temp;
        temp=date;
        scl=0;
        delay();
        for(i=0;i<8;i++)
        {
                temp=temp<<1;
                sda=CY;
                delay();
                scl=1;
                delay();
                scl=0;
                delay();
        }
        sda=1;
        delay();
}

uchar read_byte()//读一个字节数据
{
        uchar i,k;
        scl=0;
        delay();
        sda=1;
        delay();
        for(i=0;i<8;i++)
        {
                scl=1;
                delay();        
                k=(k<<1)|sda;
                scl=0;
                delay();        
        }
        return k;
}

void delay1(uchar x)
{
        uchar a,b;
        for(a=x;a>0;a--)
         for(b=100;b>0;b--);
}

void write_add(uchar address,uchar date)//写一串数据
{
        start();
        write_byte(0xa0);
        respons();
        write_byte(address);
        respons();
        write_byte(date);
        respons();
        stop();
}

uchar read_add(uchar address)//读一串数据
{
        uchar date;
        start();
        write_byte(0xa0);
        respons();
        write_byte(address);
        respons();
        start();
        write_byte(0xa1);
        respons();
        date=read_byte();
        stop();
        return date;
}

void main()
{
        init();
        wp=0;
        write_add(23,0x3f);
        delay1(100);
        P2=2;//选中数码管1
        P0=read_add(23);//让数码管点亮显示0
        while(1);
}
hotpower 发表于 2009-12-24 19:15 | 显示全部楼层
一般问题出在ACK上
NE5532 发表于 2009-12-24 20:32 | 显示全部楼层
nixianmin 发表于 2009-12-24 20:42 | 显示全部楼层
写数据应该是读取应答信号,可以用延时代替
读数据应该在读完后发送个应答信号,一段时间没发送从件默认接受成功

好像你只有读取应答信号的函数
znmcu 发表于 2009-12-24 22:18 | 显示全部楼层
本帖最后由 znmcu 于 2009-12-24 22:21 编辑

at24c64.c

  1. #include "at24c64.h"
  2. #include "iic.h"
  3. #include "myfun.h"
  4. /*******************************************************
  5.         +-------------------------------------+
  6.         | 振南电子 驱动程序模块 AT24C64部分   |
  7.         +-------------------------------------+
  8.   此源码版权属 振南 全权享有,如欲引用,敬请署名并告知
  9.         严禁随意用于商业目的,违者必究,后果自负
  10.          振南电子
  11.              ->产品网站 http://www.znmcu.cn/
  12.              ->产品网店 http://shop.znmcu.cn/
  13.              ->产品咨询 QQ:987582714
  14.                MSN:yzn07@126.com
  15.                      WW:yzn07
  16.            
  17. ********************************************************/
  18. /******************************************************************
  19. - 功能描述:向AT24C64的地址为addr的单元上写入一个字节dat
  20. - 隶属模块:AT24C64模块
  21. - 函数属性:外部,供用户使用
  22. - 参数说明:addr:AT24C64的单元地址
  23.              dat:要写入的字节     
  24. - 返回说明:无
  25. - 注:AT24C64的地址是字节级地址,即最小存储单元是字节,地址范围
  26.        是0~8191
  27. ******************************************************************/
  28. void AT24C64_Write_Byte(unsigned int addr,unsigned char dat)
  29. {
  30. IIC_Start(); //启动IIC传输
  31. IIC_Write_Byte(0xa0); //1010 A2 A1 A0 R/W [A2:A0]是AT24C64的芯片地址,0~7,即同一条IIC总线上可以挂接8个芯片;R/W是读/写选择位,0为写操作,1为读操作
  32. IIC_Write_Byte(addr>>8);//写入地址高字节
  33. IIC_Write_Byte(addr); //写入地址低字节
  34. IIC_Write_Byte(dat); //写入一个字节的数据
  35. IIC_Stop(); //IIC传输结束,AT24C64开始执行,即将这一个字节写入EEPROM中
  36. delay(5000); //等待AT24C64操作完成,最大5ms
  37. }
  38. /******************************************************************
  39. - 功能描述:写页操作
  40. - 隶属模块:AT24C64模块
  41. - 函数属性:外部,供用户使用
  42. - 参数说明:addr:页开始地址
  43.              pbuf:指向数据缓冲区的指针   
  44. - 返回说明:无
  45. - 注:向AT24C64芯片addr地址后面连续写入32个字节,即写页操作,
  46.        这些数据存放在pbuf中
  47. ******************************************************************/
  48. void AT24C64_Write_Page(unsigned int addr,unsigned char *pbuf) //
  49. {
  50. unsigned char i;
  51. IIC_Start(); //启动IIC传输
  52. IIC_Write_Byte(0xa0); //1010 A2 A1 A0 R/W [A2:A0]是AT24C64的芯片地址,0~7,即同一条IIC总线上可以挂接8个芯片;R/W是读/写选择位,0为写操作,1为读操作
  53. IIC_Write_Byte(addr>>8);//写入地址高字节
  54. IIC_Write_Byte(addr); //写入地址低字节
  55. for(i=0;i<32;i++)
  56. {
  57.   IIC_Write_Byte(pbuf[i]); //将pbuf中的32个字节写入AT24C64的数据缓冲区
  58. }
  59. IIC_Stop(); //IIC传输结束,AT24C64开始执行,即将这32个字节写入EEPROM中
  60. delay(5000); //等待AT24C64操作完成,最大5ms
  61. }
  62. /**********************************************************************************
  63. - 功能描述:从当前地址连续读取length个字节,放入pbuf指向的数据缓冲区
  64. - 隶属模块:AT24C64模块
  65. - 函数属性:外部,供用户使用
  66. - 参数说明:length:要读取的数据长度
  67.              pbuf:指向数据缓冲区的指针   
  68. - 返回说明:无
  69. - 注:从当前的地址上读取数据,所以此函数中没有写入地址的操作
  70. **********************************************************************************/
  71. void AT24C64_Current_Addr_Read(unsigned int length,unsigned char *pbuf)
  72. {
  73. unsigned char i;
  74. IIC_Start(); //启动传输,这里再次启动传输,因为下面要写入“读操作”的指令码,即0xa1
  75. IIC_Write_Byte(0xa1); //写入0xa1,从AT24C64中读取数据
  76. for(i=0;i<length-1;i++)
  77. {
  78.   pbuf[i]=IIC_Read_Byte(); //读取length-1个字节
  79.   IIC_Ack();      //前length-1个字节,每读完一个字节要向AT24C64提供ACK,即告诉其继续提供下面的数据,读取操作还未完毕
  80. }
  81. pbuf[i]=IIC_Read_Byte(); //读取最后一个字节,即第length个字节
  82. IIC_NAck();   //读取最后一个字节后,要向AT24C64提NACK,告诉其读取操作结束,不再向下读了
  83. IIC_Stop(); //传输结束  
  84. }
  85. /******************************************************************
  86. - 功能描述:从某个地址读取一个字节
  87. - 隶属模块:AT24C64模块
  88. - 函数属性:外部,供用户使用
  89. - 参数说明:addr:要读取字节的地址   
  90. - 返回说明:读到的字节
  91. - 注:此函数中直接调用了上面的 AT24C64_Current_Addr_Read函数
  92.        只是在它前面进行了地址的写入
  93. ******************************************************************/
  94. unsigned char AT24C64_Read_Byte(unsigned int addr)
  95. {
  96. unsigned char temp;
  97. IIC_Start(); //启动传输
  98. IIC_Write_Byte(0xa0);
  99. IIC_Write_Byte(addr>>8); //写入地址高字节
  100. IIC_Write_Byte(addr); //写入地址低字节
  101. AT24C64_Current_Addr_Read(1,&temp); //从当前地址读取一个字节,放入temp中
  102. return temp;//返回temp的值,即读到的字节  
  103. }
  104. /******************************************************************
  105. - 功能描述:读页操作
  106. - 隶属模块:AT24C64模块
  107. - 函数属性:外部,供用户使用
  108. - 参数说明:addr:要读取的页开始地址
  109.              pbuf:指向数据缓冲区的指针   
  110. - 返回说明:无
  111. - 注:从addr地址连续读取32个字节,将读出来的字节放在pbuf中
  112. ******************************************************************/
  113. void AT24C64_Read_Page(unsigned int addr,unsigned char *pbuf)
  114. {
  115. IIC_Start(); //启动传输
  116. IIC_Write_Byte(0xa0);
  117. IIC_Write_Byte(addr>>8); //写入地址高字节
  118. IIC_Write_Byte(addr); //写入地址低字节
  119. AT24C64_Current_Addr_Read(32,pbuf); //从当前地址读取32个字节,放入pbuf中
  120. }
  121. /******************************************************************
  122. - 功能描述:连续读操作
  123. - 隶属模块:AT24C64模块
  124. - 函数属性:外部,供用户使用
  125. - 参数说明:addr:要读取的开始地址
  126.              length:要读取的数据长度
  127.              pbuf:指向数据缓冲区的指针   
  128. - 返回说明:无
  129. - 注:从addr地址连续读取length个字节到pbuf中
  130. ******************************************************************/
  131. void AT24C64_Sequential_Read(unsigned int addr,unsigned int length,unsigned char *pbuf)
  132. {
  133. IIC_Start(); //启动传输
  134. IIC_Write_Byte(0xa0);
  135. IIC_Write_Byte(addr>>8); //写入地址高字节
  136. IIC_Write_Byte(addr); //写入地址低字节
  137. AT24C64_Current_Addr_Read(length,pbuf); //从当前地址读取32个字节,放入pbuf中
  138. }


at24c64.h

  1. #ifndef _AT24C64_H_
  2. #define _AT24C64_H_
  3. /*******************************************************
  4.         +-------------------------------------+
  5.         | 振南电子 驱动程序模块 AT24C64部分   |
  6.         +-------------------------------------+
  7.   此源码版权属 振南 全权享有,如欲引用,敬请署名并告知
  8.         严禁随意用于商业目的,违者必究,后果自负
  9.          振南电子
  10.              ->产品网站 http://www.znmcu.cn/
  11.              ->产品网店 http://shop.znmcu.cn/
  12.              ->产品咨询 QQ:987582714
  13.                MSN:yzn07@126.com
  14.                      WW:yzn07
  15.            
  16. ********************************************************/
  17. void AT24C64_Write_Byte(unsigned int addr,unsigned char dat);
  18. void AT24C64_Write_Page(unsigned int addr,unsigned char *pbuf);
  19. void AT24C64_Current_Addr_Read(unsigned int length,unsigned char *pbuf);
  20. unsigned char AT24C64_Read_Byte(unsigned int addr);
  21. void AT24C64_Read_Page(unsigned int addr,unsigned char *pbuf);
  22. void AT24C64_Sequential_Read(unsigned int addr,unsigned int length,unsigned char *pbuf);
  23. #endif



程序中包含的文件如下:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
ningling_21 发表于 2009-12-24 23:52 | 显示全部楼层
看你的延时程序到底延时多长时间,是否满足时序要求...
znmcu 发表于 2009-12-25 01:00 | 显示全部楼层
IIC的速度有时候 不能太快的
maomao2126 发表于 2009-12-25 09:31 | 显示全部楼层
注意硬件上SLC\SDA外部要有上拉电阻
 楼主| t86964988 发表于 2009-12-28 19:36 | 显示全部楼层
解决了 原来是硬件地址弄错了
电子三极管 发表于 2009-12-29 12:09 | 显示全部楼层
你这段程序我怎么那么耳熟呢  ? 哦 是郭天祥的视频教材里面有的
xiangrui21 发表于 2010-1-5 09:38 | 显示全部楼层
楼上的,不是耳熟,是眼熟~~~当初看了好几遍的了~!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

19

主题

77

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部