前一排开发的板中使用了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);
}