搜索
bottom↓
回复: 3

51读写24C02 (问题)

[复制链接]

出0入0汤圆

发表于 2010-4-17 11:12:27 | 显示全部楼层 |阅读模式
我使用了周立功库的一部分,读写24C02,如果只往里写数据,通过单步看,没有问题。
如果只从里面读数据,单步看,也没问题。

但是如果我写了数据,然后在接着读出来,就有问题了,主机发送器件地址,直接接不到回应。。。。
这是怎么回事??

注:我用的是protues+KEIL连调。
程序如下:
#include "reg51.h"
#include "intrins.h"
#include "I2C.h"

sbit SDA=P2^4;                    //*模拟I2C数据传送位
sbit SCL=P2^3;                    //*模拟I2C时钟控制位


#define  _Nop()  _nop_(),_nop_(),_nop_(),_nop_()      /*定义空指令*/


/*******************************************************************
                     起动总线函数               
函数原型: void  Start_I2c();  
功能:     启动I2C总线,即发送I2C起始条件.  
********************************************************************/
void Start_I2c()
{
  SDA=1;           /*发送起始条件的数据信号*/
  _Nop();
  SCL=1;
  _Nop();            /*起始条件建立时间大于4.7us,延时*/
  _Nop();
  _Nop();
  _Nop();
  _Nop();   
  SDA=0;           /*发送起始信号*/
  _Nop();            /* 起始条件锁定时间大于4μs*/
  _Nop();
  _Nop();
  _Nop();
  _Nop();      
  SCL=0;           /*钳住I2C总线,准备发送或接收数据 */
  _Nop();
  _Nop();
}

/*******************************************************************
                       结束总线函数               
函数原型: void  Stop_I2c();  
功能:     结束I2C总线,即发送I2C结束条件.  
********************************************************************/
void Stop_I2c()
{
  SDA=0;          /*发送结束条件的数据信号*/
  _Nop();           /*发送结束条件的时钟信号*/
  SCL=1;          /*结束条件建立时间大于4μs*/
  _Nop();
  _Nop();
  _Nop();
  _Nop();
  _Nop();
  SDA=1;          /*发送I2C总线结束信号*/
  _Nop();
  _Nop();
  _Nop();
  _Nop();
}

/*******************************************************************
                 字节数据发送函数               
函数原型: bit  SendByte(uchar c);
功能:     将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
          此状态位进行操作.(不应答或非应答都使ack=0)     
               发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
********************************************************************/
bit  SendByte(unsigned char c)
{
unsigned char  BitCnt;
bit ack;

for(BitCnt=0;BitCnt<8;BitCnt++)  /*要传送的数据长度为8位*/
    {
     if((c<<BitCnt)&0x80)SDA=1;   /*判断发送位*/
       else  SDA=0;               
     _Nop();
     SCL=1;               /*置时钟线为高,通知被控器开始接收数据位*/
      _Nop();
      _Nop();             /*保证时钟高电平周期大于4μs*/
      _Nop();
      _Nop();
      _Nop();         
     SCL=0;
    }
   
    _Nop();
    _Nop();
    SDA=1;                /*8位发送完后释放数据线,准备接收应答位*/
    _Nop();
    _Nop();   
    SCL=1;
    _Nop();
    _Nop();
    _Nop();
    if(SDA==1)ack=0;     
       else ack=1;        /*判断是否接收到应答信号*/
    SCL=0;
    _Nop();
    _Nop();
        return ack;
}

/*******************************************************************
                 字节数据接收函数               
函数原型: uchar  RcvByte();
功能:            用来接收从器件传来的数据,并判断总线错误(不发应答信号),
          发完后请用应答函数应答从机。  
********************************************************************/       
unsigned char  RcvByte()
{
  unsigned char retc;
  unsigned char BitCnt;
  
  retc=0;
  SDA=1;                             /*置数据线为输入方式*/
  for(BitCnt=0;BitCnt<8;BitCnt++)
      {
        _Nop();           
        SCL=0;                  /*置时钟线为低,准备接收数据位*/
        _Nop();
        _Nop();                 /*时钟低电平周期大于4.7μs*/
        _Nop();
        _Nop();
        _Nop();
        SCL=1;                  /*置时钟线为高使数据线上数据有效*/
        _Nop();
        _Nop();
        retc=retc<<1;
        if(SDA==1)retc=retc+1;  /*读数据位,接收的数据位放入retc中 */
        _Nop();
        _Nop();
      }
  SCL=0;   
  _Nop();
  _Nop();
  return(retc);
}




/********************************************************************
                     应答子函数
函数原型:  void Ack_I2c(bit a);
功能:      主控器进行应答信号(可以是应答或非应答信号,由位参数a决定)
********************************************************************/
void Ack_I2c(bit a)
{
  
  if(a==0)SDA=0;                  /*在此发出应答或非应答信号 */
        else SDA=1;
  _Nop();
  _Nop();
  _Nop();      
  SCL=1;
  _Nop();
  _Nop();                    /*时钟低电平周期大于4μs*/
  _Nop();
  _Nop();
  _Nop();  
  SCL=0;                     /*清时钟线,钳住I2C总线以便继续接收*/
  _Nop();
  _Nop();   
}

char AT24C02_WriteByte(char addr,  char ch)
{
        Start_I2c();
        if(SendByte(addr)) //发送器件地址
                SendByte(0x01);
         else
                 return 0;
        SendByte(ch);
        Stop_I2c();
        return 1;
}
char AT24C02_ReadByte(char addr)
{
    char dat;   

        Start_I2c();
        if(SendByte(addr)) //发送器件地址
                SendByte(0x01);
         else
                 return 0;
        Start_I2c();       
        SendByte(addr+1);
        dat=RcvByte();
        Ack_I2c(1);
        Stop_I2c();
        return 1;       
}

主函数:(部分)
        AT24C02_WriteByte(0xa0, 0x55);
        dat=AT24C02_ReadByte(0xa0);

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2010-5-3 20:10:44 | 显示全部楼层
写入数据后应该等待5~10ms再读

详细看数据手册!

出0入0汤圆

 楼主| 发表于 2010-5-4 21:55:48 | 显示全部楼层
哦 。谢谢。我先试下

出0入0汤圆

发表于 2010-5-7 16:08:25 | 显示全部楼层
直接在AT24C02_WriteByte()里面加延时,或者换成铁电的,嘿嘿
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-27 06:52

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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