📄 i2c.c
字号:
#include<at89x51.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
code uchar SenData[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10};
sbit SCL=P1^4;
sbit SDA=P1^5;
/***********************************************
**函数名称:DelayNms()
**函数功能:延时N毫秒
**入口参数:n
**出口参数:无
**说明 :无
***********************************************/
void DelayNms(uint n)
{
uint i,j;
for(i=0;i<n;i++)
for(j=0;j<120;j++);
}
/***********************************************
**函数名称:I2C_Start()
**函数功能:发送起始条件
**入口参数:无
**出口参数:无
**说明 :时序按照标准模式建立
***********************************************/
void I2C_Start()
{
SDA=1;
_nop_();//数据建立时间大于250ns
_nop_();
_nop_();
SCL=1;
_nop_();
_nop_();
_nop_();
SDA=0;
_nop_();
_nop_();
SCL=0; //SCL高电平时间大于4us,嵌住时钟总线
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
/***********************************************
**函数名称:I2C_Stop()
**函数功能:发送停止条件
**入口参数:无
**出口参数:无
**说明 :时序按照标准模式建立
***********************************************/
void I2C_Stop()
{
SDA=0;
_nop_();//数据建立时间大于250ns
_nop_();
_nop_();
SCL=1;
_nop_();
_nop_();
_nop_();
SDA=1;
_nop_();
_nop_();
SCL=0; //SCL高电平时间大于4us,嵌住时钟总线
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
/***********************************************
**函数名称:I2C_SendByte()
**函数功能:发送一个字节
**入口参数:待发送字节n
**出口参数:无
**说明 :时序按照标准模式建立
***********************************************/
void I2C_SendByte(uchar n)
{
char i;
for(i=7;i>=0;i--)
{
SDA=(n>>i)&0x01;
_nop_();
_nop_();
_nop_();
SCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL=0;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
}
/***********************************************
**函数名称:I2C_RecByte()
**函数功能:接收一个字节
**入口参数:无
**出口参数:已接收字节
**说明 :时序按照标准模式建立
***********************************************/
I2C_RecByte(void)
{
char i,j=0;
for(i=7;i>=0;i--)
{
j<<=1;
SDA=1;
_nop_();
_nop_();
_nop_();
SCL=1;
_nop_();
_nop_();
_nop_();
j|=SDA&0x01;
_nop_();
_nop_();
SCL=0;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
return (j);
}
/***********************************************
**函数名称:Check_Ack()
**函数功能:检测从机响应
**入口参数:无
**出口参数:从机响应则为'0',否则为'1'
**说明 :时序按照标准模式建立
***********************************************/
Check_Ack()
{
uchar i=1;
SDA=1;
_nop_();
_nop_();
_nop_();
SCL=1;
_nop_();
_nop_();
_nop_();
i=SDA;
_nop_();
_nop_();
_nop_();
SCL=0;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
return (i);
}
/***********************************************
**函数名称:Gen_Ack()
**函数功能:产生应答
**入口参数:i
**出口参数:无
**说明 :i=0产生应答,i=1产生非应答
***********************************************/
Gen_Ack(char i)
{
SDA=i;
_nop_();
_nop_();
SCL=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
SCL=0;
_nop_();
_nop_();
SDA=1;
_nop_();
_nop_();
_nop_();
}
/***********************************************
**函数名称:I2C_SendNByte()
**函数功能:发送N个字节
**入口参数:字节个数n,待发送数据队列首地址
**出口参数:无
**说明 :时序按照标准模式建立
***********************************************/
void I2C_SendNByte(uchar n,uchar *p)
{
while(n--)
{
send:I2C_SendByte(*p);
if(Check_Ack()) goto send;
p++;
}
I2C_Stop();
}
/***********************************************
**函数名称:I2C_RecNByte()
**函数功能:接收N个字节
**入口参数:字节个数n,存放数据队列首地址
**出口参数:无
**说明 :时序按照标准模式建立
***********************************************/
void I2C_RecNByte(char n,uchar *p)
{
while(n--)
{
*p=I2C_RecByte();
if(n>0)
{Gen_Ack(0x00);//产生应答
p++;
}
else
{Gen_Ack(0x01);//产生非应答
I2C_Stop();
}
}
}
void main(void)
{
uchar RecData[18]={0x00};
/***********************************************/
start:I2C_Start();
I2C_SendByte(0xae);//发送从地址选择24c01
if(Check_Ack())
{
I2C_Stop();
goto start;
}
I2C_SendByte(0x30);//发送子地址
if(Check_Ack())
{
I2C_Stop();
goto start;
}
I2C_SendNByte(17,SenData);//在页写入模式下一次最多写一页,写的数据超过16个将覆盖前面所写的
DelayNms(1000);//这个延时很有用,去掉试试看
/***********************************************/
/***********************************************/
start2:I2C_Start();
I2C_SendByte(0xac);//发送从地址选择24c02
if(Check_Ack())
{
I2C_Stop();
goto start2;
}
I2C_SendByte(0x80);//发送子地址
if(Check_Ack())
{
I2C_Stop();
goto start2;
}
I2C_SendNByte(17,SenData);//在页写入模式下一次最多写一页,写的数据超过16个将覆盖前面所写的
DelayNms(1000);//这个延时很有用,去掉试试看
/***********************************************/
/***********************************************/
start3:I2C_Start();
I2C_SendByte(0xa0);//发送从地址,选择24c04,第0页
if(Check_Ack())
{
I2C_Stop();
goto start3;
}
I2C_SendByte(0x80);//发送子地址
if(Check_Ack())
{
I2C_Stop();
goto start3;
}
I2C_SendNByte(17,SenData);//在页写入模式下一次最多写一页,写的数据超过16个将覆盖前面所写的
DelayNms(1000);//这个延时很有用,去掉试试看
start4:I2C_Start();
I2C_SendByte(0xa2);//发送从地址,选择24c04,第1页
if(Check_Ack())
{
I2C_Stop();
goto start4;
}
I2C_SendByte(0x70);//发送子地址
if(Check_Ack())
{
I2C_Stop();
goto start4;
}
I2C_SendNByte(17,SenData);//在页写入模式下一次最多写一页,写的数据超过16个将覆盖前面所写的
DelayNms(1000);//这个延时很有用,去掉试试看
/***********************************************/
/***********************************************/
start1: I2C_Start();
I2C_SendByte(0xa0);//发送从地址
if(Check_Ack())
{
I2C_Stop();
goto start1;
}
I2C_SendByte(0x08);//发送子地址
if(Check_Ack())
{
I2C_Stop();
goto start1;
}
I2C_Start();
I2C_SendByte(0xa1);//这一步不要忘记检测应答
if(Check_Ack())
{
I2C_Stop();
goto start1;
}
I2C_RecNByte(18,RecData);
/***********************************************/
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -