使用AT24C04EEPROM的总结

             前一排开发的板中使用了M24C04的存储器,写好的程序读写正常,但是换成AT24C04就读写不了。原因:不同公司读写操作时间不同,经过测试,自己延时20ms之后,就好了。


#include <w78e516d.h>
#include "delay.c"
#include <intrins.h>
#include "main.h"
#define uchar unsigned char

//M24C02的控制脚
#define WC24C02 0x0a0//器件地址
sbit SDA=P3^7;//定义数据线
sbit SCL=P3^6;//定义时钟线
bit flag;  //24c02 应答的一个标志位

void Write_Byte(uchar ucDa) ;
uchar Read_Byte(void) ;
void v_W1302(uchar ucAddr, uchar ucDa);
uchar uc_R1302(uchar ucAddr);
void delay();  //24c02
void ACK();  //24c02应答
void NoACK();

 

 

void delay1ms(unsigned char t)
{

 unsigned char a,b,c;
 a = 5*t;
        for(;a>0;a--)

        for(b=4;b>0;b--)

        for(c=24;c>0;c--);

}


//延时300us吧
void delay()
{
        uchar i;
        for(i=100;i>0;i--)
                _nop_();
}
/*********************************************************
**名称:I2C_Start
**功能:启动I2C
**输入:无
**返回:无
*********************************************************/
void I2C_Start()
{
        SDA=1;
        delay();
        SCL=1;
        delay();
        SDA=0;
        delay();
        SCL=0;//钳位I2C总线,准备发送数据
}
/**********************************************************
**名称:I2C_Stop
**功能:停止I2C
**输入:无
**返回:无
**********************************************************/
void I2C_Stop()
{
        SDA=0;
        delay();
        SCL=1;
        delay();
        SDA=1;
        delay();
}
/**********************************************************
**名称:Ack
**功能:应答信号
**输入:无
**返回:无
**********************************************************/
void Ack()
{
        SDA=0;
        delay();
        SCL=1;
        delay();
        SCL=0;
        delay();
        SDA=1;
        delay();
}
/********************************************************
**名称:NoAck
**功能:发送非应答信号
**输入:无
**返回:无
********************************************************/
void NoAck()
{
        SDA=1;
        delay();
        SCL=1;
        delay();
        SCL=0;
        delay();
        SDA=0;
        delay();
}
/********************************************************
**名称:Test_Ack()
**功能:检测应答位
*********************************************************/
bit Test_Ack()
{
        SCL=0;
        SDA=1;//读入数据
        _nop_();_nop_();_nop_();_nop_();
        SCL=1;
        _nop_();_nop_();_nop_();_nop_();
        if(SDA==0)
                flag=1;
        else   flag=0;
     SCL=0;
        return(flag);
}

/********************************************************
**名称:SendData()       
**功能:发送一字节数据
**输入:buffer
**返回:
*******************************************************/
void SendData(uchar buffer)
{
        uchar BitCnt=8;//一字节8位
        uchar temp=0;
        do
        {
                temp=buffer;
                SCL=0;
                delay();
                if((temp&0x80)==0) //判断最高位是0还是1
                        SDA=0;
                else
                        SDA=1;
                delay();
                SCL=1;
                temp=_crol_(buffer,1);//将buffer中的数据左移一位
                buffer=temp;
                BitCnt--;
        }
        while(BitCnt);
        SCL=0;       
}

 

/**************************************************************
**名称:uchar ReceiveData()
**功能:接收一字节数据
**输入:
**返回:ucReceData
**说明:将接收的数据存放在ucReceData中
**************************************************************/
uchar ReceiveData()
{
 uchar ucReceData=0;
        uchar BitCnt=8;
        SDA=1;//读入数据
        do
        {
                SCL=0;
                delay();
                SCL=1;
                delay();
  ucReceData = ucReceData << 1;
                if(SDA==1)
                        ucReceData=ucReceData|0x01;//低位置1
                else
                        ucReceData=ucReceData&0x0fe;//低位清0
                BitCnt--;
        }
        while(BitCnt);
        SCL=0;
        return(ucReceData);
}

 

//---------------------------------------------------------------------------------------------------------------

/********************************************************************
*
* 名称: Write_Byte(uchar ucDa)
* 说明:
* 功能: 往DS1302写入1Byte数据
* 调用:
* 输入: ucDa 写入的数据
* 返回值: 无
***********************************************************************/
void Write_Byte(uchar ucDa)
{
uchar i;
ACC= ucDa;
for(i=8; i>0; i--)
{
 IO = ACC0; //*相当于汇编中的 RRC
 _nop_();
 SCK = 1;
 _nop_();
 SCK = 0;
 ACC = ACC>> 1;
}
}
/********************************************************************
*
* 名称: uchar Read_Byte(void)
* 说明:
* 功能: 从DS1302读取1Byte数据
* 调用:
* 输入:
* 返回值: ACC
***********************************************************************/
uchar Read_Byte(void)
{
uchar i;
for(i=8; i>0; i--)
{
 ACC = ACC>>1; //*相当于汇编中的 RRC
 IO = 1;
 ACC7 = IO;
 _nop_();
 SCK = 1;
 _nop_();
 SCK = 0;
 _nop_();

return(ACC);
}
/********************************************************************
*
* 名称: v_W1302
* 说明: 先写地址,后写命令/数据
* 功能: 往DS1302写入数据
* 调用: v_RTInputByte()
* 输入: ucAddr: DS1302地址, ucDa: 要写的数据
* 返回值: 无
***********************************************************************/
void v_W1302(uchar ucAddr, uchar ucDa)
{

SCK = 0;
CS_DS1302 = 0;
_nop_();
_nop_();
CS_DS1302 = 1;
Write_Byte(ucAddr); /* 地址,命令 */
Write_Byte(ucDa); /* 写1Byte数据*/
SCK = 1;
CS_DS1302 =0;
G2 = HIGH;
}
/********************************************************************
*
* 名称: uc_R1302
* 说明: 先写地址,后读命令/数据
* 功能: 读取DS1302某地址的数据
* 调用: v_RTInputByte() , uc_RTOutputByte()
* 输入: ucAddr: DS1302地址
* 返回值: ucDa :读取的数据
***********************************************************************/
uchar uc_R1302(uchar ucAddr)
{
uchar ucDa;
CS_DS1302 = 0;
SCK = 0;
_nop_();
_nop_();
CS_DS1302 = 1;
Write_Byte(ucAddr); /* 地址,命令 */
ucDa = Read_Byte(); /* 读1Byte数据 */
SCK = 1;
CS_DS1302 =0;;
return(ucDa);
}

 

/*************************************************************
**名称:bit WriteNByte()
**功能:向24C02中写入多字节数据
**输入:
**返回:
**说明:sla-器件地址 suba-数据地址,*s-写入的数据,n-写入的字节数
                (n<=8)
**************************************************************/
bit WriteNByte(uchar Address,uchar *s,uchar n)
{
        uchar i;
        I2C_Start();//启动I2C
        SendData(WC24C02);//发送器件地址
        Test_Ack();
        if(flag==0)        return(0);
        SendData( Address);
        Test_Ack();
        if(flag==0)        return(0);
        for(i=0;i<n;i++)//写入8字节数据
        {
                SendData(*(s+i));
                Test_Ack();
                if(flag==0)        return(0);
        }
        I2C_Stop();
       delay1ms(20);
        return(1);
}
/*************************************************************
**名称:bit ReadNByte()
**功能:从24C02中读出N字节数据(n<=8)
**输入:
**返回:
**说明:
**************************************************************/
bit ReadNByte(uchar Address,uchar *p,uchar n)
{
        uchar i;
        I2C_Start();//启动I2C
        SendData( WC24C02);//发送器件地址
        Test_Ack();
        if(flag==0)        return(0);
        SendData(Address);//发送器件内部地址
        Test_Ack();
        if(flag==0)        return(0);
        I2C_Start();
        SendData( WC24C02+1);
        Test_Ack();
        if(flag==0)        return(0);
        for(i=0;i<n-1;i++)//读取字节数据
        {
                *(p+i)=ReceiveData();//读取数据
                ACK();
        }
        *(p+i)=ReceiveData();
        NoACK();
        I2C_Stop();
        delay1ms(20);
         return(1);
}

 

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值