IIC通讯通用代码
在实际项目中往往要用到IIC与不同的设备通讯,做一个通用型的IIC驱动代码很有必要,面得每次还得去自己测时序,实在是太麻烦了。而网上其他的IIC通讯代码要么只是适配51,要么用不了,我要弄的是适配所有平台,不需要再去检查IIC的时序。
#define SDA RB0
#define SCL RB1
#define SDA_SET SDA=1;
#define SCL_SET SCL=1;
#define SDA_RESET SDA=0;
#define SCL_RESET SCL=0;
#define SDA_IN_STATUS TRISB|=0x01; //SDA线输入状态
#define SDA_OUT_STATUS TRISB&=0xfe; //SDA线输出状态
void Single_WriteI2C(_u8 REG_Address,_u8 REG_data); //向设备写一个字节数据
_u8 Single_ReadI2C(_u8 REG_Address); //向设备读一个字节数据
void Delay5us() //自定义延迟函数
{
_u8 i;
for(i=0;i<5;i++)
}
//**************************************
//I2C起始信号
//**************************************
void I2C_Start()
{
SDA_SET; //拉高数据线
SCL_SET; //拉高时钟线
Delay5us(); //延时
SDA_RESET; //产生下降沿
Delay5us(); //延时
SCL_RESET; //拉低时钟线
}
//**************************************
//I2C停止信号
//**************************************
void I2C_Stop()
{
SDA_RESET; //拉低数据线
SCL_SET; //拉高时钟线
Delay5us(); //延时
SDA_SET; //产生上升沿
Delay5us(); //延时
Delay5us();
}
//**************************************
//I2C发送应答信号
//入口参数:ack (0:ACK 1:NAK)
//**************************************
void I2C_SendACK(_u8 ack)
{
if(ack) //写应答信号
{
SDA_SET;
}
else
{
SDA_RESET;
}
SCL_SET; //拉高时钟线
Delay5us(); //延时
SCL_RESET; //拉低时钟线
Delay5us(); //延时
}
//**************************************
//I2C接收应答信号
//**************************************
_u8 I2C_RecvACK()
{
SDA_IN_STATUS; //SDA线改成输入模式
SCL_SET; //拉高时钟线
Delay5us(); //延时
if(SDA_READ)
{
Anwer_f=1;
}
else
{
Anwer_f=0;
}
SCL_RESET; //拉低时钟线
SDA_OUT_STATUS; //SDA线改成输出模式
Delay5us(); //延时
return Anwer_f;
}
//**************************************
//向I2C总线发送一个字节数据
//**************************************
void I2C_SendByte(_u8 dat)
{
_u8 i;
for (i=0; i<8; i++)
{
if(dat&0x80)
{
SDA_SET;
}
else
{
SDA_RESET;
}
dat <<= 1; //送数据口
SCL_SET; //拉高时钟线
Delay5us(); //延时
SCL_RESET; //拉低时钟线
Delay5us(); //延时
}
I2C_RecvACK();
}
//**************************************
//从I2C总线接收一个字节数据
//**************************************
uchar I2C_RecvByte()
{
uchar i;
uchar dat_RESET;
SDA_IN_STATUS; //SDA线改成输入
for (i=0; i<8; i++) //8位计数器
{
dat <<= 1;
SCL_SET; //拉高时钟线
Delay5us(); //延时
if(SDA)
{
dat |=1;
}
SCL_RESET; //拉低时钟线
Delay5us(); //延时
}
SDA_OUT_STATUS; //SDA线改成输出
return dat;
}
//**************************************
//向I2C设备写入一个字节数据
//**************************************
void Single_WriteI2C(_u8 REG_Address,_u8 REG_data)
{
I2C_Start(); //起始信号
I2C_SendByte(SlaveAddress); //发送设备地址+写信号
I2C_SendByte(REG_Address); //内部寄存器地址,
I2C_SendByte(REG_data); //内部寄存器数据,
I2C_Stop(); //发送停止信号
}
//**************************************
//从I2C设备读取一个字节数据
//**************************************
_u8 Single_ReadI2C(_u8 REG_Address)
{
_u8 REG_data;
I2C_Start(); //起始信号
I2C_SendByte(SlaveAddress); //发送设备地址+写信号
I2C_SendByte(REG_Address); //发送存储单元地址,从0开始
I2C_Start(); //起始信号
I2C_SendByte(SlaveAddress+1); //发送设备地址+读信号
REG_data=I2C_RecvByte(); //读出寄存器数据
I2C_SendACK(1); //接收应答信号
I2C_Stop(); //停止信号
return REG_data;
}