#define uchar unsigned char
#define DELAY5US _nop_(); _nop_(); _nop_(); _nop_(); //延时5us
#define WriteDeviceAddress 0xa0 //写I2C外围器件的寻址地址
#define ReadDeviceAddress 0xa1 //读I2C外围器件的寻址地址
//注:写I2C外围器件的寻址地址为器件的地址,读为器件地址加1
uchar E0; //非应答信号标志位
uchar NACK=0; //错误标志位
//**************************修改硬件时要修改的部分********************************
sbit SDA = P1^0; //模拟数据线
sbit SCL = P1^1; //模拟时钟线
void Start(void) //启动I2C总线子函数
{
SDA=1;
SCL=1;
DELAY5US
SDA=0;
DELAY5US
SCL=0;
}
void Stop(void) //停止I2C总线数据传送子函数
{
SDA=0;
SCL=1;
DELAY5US
SDA=1;
DELAY5US
SCL=0;
}
void Ack(void) //发送应答位子程序
{
SDA=0;
SCL=1;
DELAY5US
SCL=0;
SDA=1;
}
void NoAck(void) //发送非应答位子程序
{
SDA=1;
SCL=1;
DELAY5US
SCL=0;
SDA=0;
}
void TestAck(void) //应答位检查子程序,若检测不到非应答信号,置位E0
{
SDA=1;
SCL=1;
E0=0;
_nop_(); //短延时
if(SDA==1) //如果SDA为1,表明非应答,置位非应答标志E0
E0=1;
SCL=0;
}
void Write8Bit(uchar n) //写一个字节数据子程序,n为待发送的数据
{
uchar i;
for(i=8;i>0;i--)
{
SDA=(bit)(n&0x80);
SCL=1;
DELAY5US
SCL=0;
SDA=0;
n=n<<1;
}
}
void WriteI2C(uchar *Wdata,uchar RomAddress,uchar number) // 写n个字节数据子程序
{ //*Wdata为待发送数据的首地址,RomAddress为待I2C外围器件的数据写入首地址,number为写字节的个数
Start(); //启动
Write8Bit(WriteDeviceAddress); //写入器件的寻址地址
TestAck(); //应答检查
if(E0==1)
{
NACK=1; //若非应答表明器件错误或已坏,置错误标志位NACK
return;
}
Write8Bit(RomAddress); //写入I2C器件的数据存储首地址
TestAck(); //应答检查
if(E0==1)
{
NACK=1; //若非应答表明器件错误或已坏,置错误标志位NACK
return;
}
for(;number!=0;number--) //循环,逐个字节发送
{
Write8Bit(*Wdata); //写一个字节
TestAck(); //应答检查
if(E0==1)
{
NACK=1; //若非应答表明器件错误或已坏,置错误标志位NACK
return;
}
Wdata++; //指针增加,指向下一个数据
}
Stop(); //全部发送完则停止
}
uchar Read8Bit(void) //读一个字节数据子程序
{
uchar temp,rbyte=0;
for(temp=8;temp>0;temp--)
{
SDA=1;
SCL=1;
_nop_(); //短延时
rbyte=rbyte<<1;
rbyte=rbyte|((uchar)(SDA));
SCL=0;
}
return(rbyte);
}
void ReadI2C(uchar *RamAddress,uchar RomAddress,uchar bytes) // 读n个字节数据子程序
{ //RamAddress为接收数据缓冲区的首地址,RomAddress为待I2C外围器件的数据读取首地址,bytes为写字节的个数
Start(); //启动
Write8Bit(WriteDeviceAddress); //写入器件的寻址地址
TestAck(); //应答检查
if(E0==1)
{
NACK=1; //若非应答表明器件错误或已坏,置错误标志位NACK
return;
}
Write8Bit(RomAddress); //写入I2C器件内部数据的读取首地址
TestAck(); //应答检查
if(E0==1)
{
NACK=1; //若非应答表明器件错误或已坏,置错误标志位NACK
return;
}
Start(); //重新启动
Write8Bit(ReadDeviceAddress); //写入器件的寻址地址
TestAck(); //应答检查
if(E0==1)
{
NACK=1; //若非应答表明器件错误或已坏,置错误标志位NACK
return;
}
while(bytes!=1) //循环读入字节数据
{
*RamAddress=Read8Bit(); //读入一个字节
Ack(); //应答
RamAddress++; //地址指针递增
bytes--; //待读入数据个数递
}
*RamAddress=Read8Bit(); //读入最后一个字节数据
NoAck(); //非应答
Stop(); //停止
}
上一篇:I2S总线原理及其实例
下一篇:可移植程序的探讨
推荐阅读最新更新时间:2024-03-16 15:11
- 热门资源推荐
- 热门放大器推荐