📄 i2c.c
字号:
/***********************************************************************/
/* 文件名 :I2C.c
/* 芯片 :Atmel AT89C51
/* 作者 :Ericson
/* 日期 :2007.11.15
/* 功能描述:本文件为I2C串行通信协议提供支持,通过AT89C51的P00和P01口模拟
实现I2C协议规范,并通过I2C通信协议实现对EEPROM AT24C32的写入
和读出操作。
/***********************************************************************/
//***********************************************************************
//包含头文件
#include "I2C.h"
//***********************************************************************
//端口定义
sbit SCL = P0^0; //I2C编程端口--SCL
sbit SDA = P0^1; //I2C编程端口--SDA
//***********************************************************************
//I2C串行通信启动函数
void I2C_Start(void)
{
SDA = 1;
_nop_();
SCL = 1;
SomeNOP();
SDA = 0; //数据线保持高电平5个指令周期后变为低电平,I2C通信开始
SomeNOP(); //SDA:5(高)+4(低)
SCL = 0; //SCL: 9(高)
_nop_();
_nop_();
}
//***********************************************************************
//I2C串行通信结束函数
void I2C_Stop(void)
{
SDA = 0;
_nop_();
_nop_();
SCL = 1;
SomeNOP();
SDA = 1;
SomeNOP();
}
//***********************************************************************
//I2C串行通信发送应答位函数
void I2C_ACK(void)
{
SDA = 0;
_nop_();
_nop_();
SCL = 1;
SomeNOP();
SCL = 0;
_nop_();
_nop_();
}
//**********************************************************************
//I2C串行通信发送非应答位函数
void I2C_NoACK(void)
{
SDA = 1;
_nop_();
_nop_();
SCL = 1;
SomeNOP();
SCL = 0;
_nop_();
_nop_();
}
//***********************************************************************
//I2C串行通信写入一个字节函数
void I2C_WriteByte(uchar ch)
{
uchar index = 8;
while(index--)
{
SCL = 0;
_nop_();
_nop_();
SDA = (bit)(ch&0x80);
SomeNOP();
SCL = 1;
SomeNOP();
ch <<= 1;
}
SCL = 0;
_nop_();
_nop_();
SDA = 1;
_nop_();
_nop_();
SCL = 1;
_nop_();
_nop_();
_nop_();
if(SDA == 1) ACK = 0;
else ACK = 1;
SCL = 0;
_nop_();
_nop_();
}
//***********************************************************************
//I2C串行通信读出一个字节函数
uchar I2C_ReadByte(void)
{
uchar index = 8;
uchar Data = 0;
SDA = 1;
while(index--)
{
Data <<= 1;
_nop_();
SCL = 0;
SomeNOP();
SCL = 1;
_nop_();
_nop_();
if(SDA == 1) Data += 1;
}
SCL = 0;
_nop_();
_nop_();
return Data;
}
//***********************************************************************
//通过I2C接口向EEPROM写入一个字节数据函数
//参数说明:sla -- 待写入数据的EEPROM的控制字节,1 0 1 0 A2 A1 A0 R/W(R/W不起作用,为0)
// addr -- 待写入数据的EEPROM的16位存储单元地址(针对AT24C32或AT24C64设计)
// ch -- 待写入EEPROM的数据
bit NVM_WriteB(uchar sla,uint addr,uchar ch)
{
uchar haddr,laddr;
laddr = (uchar)(addr&0xFF); //存储单元低字节地址
haddr = (uchar)((addr>>8)&0xFF); //存储单元高字节地址
I2C_Start();
I2C_WriteByte(sla);
if(ACK == 0) return(0);
I2C_WriteByte(haddr);
if(ACK == 0) return(0);
I2C_WriteByte(laddr);
if(ACK == 0) return(0);
I2C_WriteByte(ch);
if(ACK == 0) return(0);
I2C_Stop();
return(1);
}
//***********************************************************************
//通过I2C接口从EEPROM读出一个字节数据函数,结果放在ch指向的地址单元中
//参数说明:sla -- 待读出数据的EEPROM的控制字节,1 0 1 0 A2 A1 A0 R/W(R/W不起作用,为0)
// addr -- 待读出数据的EEPROM的16位存储单元地址(针对AT24C32或AT24C64设计)
// ch -- 用于保存从EEPROM读出的数据
bit NVM_ReadB(uchar sla,uint addr,uchar *ch)
{
uchar haddr,laddr;
laddr = (uchar)(addr&0xFF); //存储单元低字节地址
haddr = (uchar)((addr>>8)&0xFF); //存储单元高字节地址
I2C_Start();
I2C_WriteByte(sla);
if(ACK == 0) return(0);
I2C_WriteByte(haddr);
if(ACK == 0) return(0);
I2C_WriteByte(laddr);
if(ACK == 0) return(0);
I2C_Start();
I2C_WriteByte(sla+1);
if(ACK == 0) return(0);
*ch = I2C_ReadByte();
I2C_NoACK();
I2C_Stop();
return(1);
}
//***********************************************************************
//通过I2C接口向EEPROM写入一个字符串函数
//参数说明:sla -- 待写入数据的EEPROM的控制字节,1 0 1 0 A2 A1 A0 R/W(R/W不起作用,为0)
// addr -- 待写入数据的EEPROM的16位存储单元地址(针对AT24C32或AT24C64设计)
// str -- 待写入EEPROM的数据数组的首地址
// length-- 待写入EEPROM的数据数组长度
bit NVM_WriteStr(uchar sla,uint addr,uchar *str,uchar length)
{
uchar index,temp;
uchar haddr,laddr;
laddr = (uchar)(addr&0xFF); //存储单元低字节地址
haddr = (uchar)((addr>>8)&0xFF); //存储单元高字节地址
I2C_Start();
I2C_WriteByte(sla);
if(ACK == 0) return(0);
I2C_WriteByte(haddr);
if(ACK == 0) return(0);
I2C_WriteByte(laddr);
if(ACK == 0) return(0);
for(index=0;index<length;index++)
{
temp = *(str+index);
I2C_WriteByte(temp);
if(ACK == 0) return(0);
}
I2C_Stop();
return(1);
}
//***********************************************************************
//通过I2C接口从EEPROM读出一个字符串函数,结果放在ch指向的地址单元中
//参数说明:sla -- 待读出数据的EEPROM的控制字节,1 0 1 0 A2 A1 A0 R/W(R/W不起作用,为0)
// addr -- 待读出数据的EEPROM的16位存储单元地址(针对AT24C32或AT24C64设计)
// str -- 待写入EEPROM的数据数组的首地址
// length-- 待写入EEPROM的数据数组长度
bit NVM_ReadStr(uchar sla,uint addr,uchar *str,uchar length)
{
uchar index;
uchar haddr,laddr;
laddr = (uchar)(addr&0xFF); //存储单元低字节地址
haddr = (uchar)((addr>>8)&0xFF); //存储单元高字节地址
I2C_Start();
I2C_WriteByte(sla);
if(ACK == 0) return(0);
I2C_WriteByte(haddr);
if(ACK == 0) return(0);
I2C_WriteByte(laddr);
if(ACK == 0) return(0);
I2C_Start();
I2C_WriteByte(sla+1);
if(ACK == 0) return(0);
for(index=0;index<length;index++)
{
*(str+index) = I2C_ReadByte();
I2C_ACK();
}
I2C_NoACK();
I2C_Stop();
return(1);
}
//结束
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -