#include<reg52.h>
#include<intrins.h>
#define I2CDelay() {_nop_();_nop_();_nop_();_nop_();}
sbit SDA=P3^6;
sbit SCL=P3^7;
//产生总线起始信号号
void I2CStart()
{
SCL=1;
SDA=1;
I2CDelay(); //确保SDA产生下降沿信号时SCL为高电平
SDA=0; //拉低SDA产生一个下降沿
I2CDelay(); //延时确保产生下降沿后稳定
SCL=0; //此时拉低SCL后SDA可变,即可以准备发送的信号
}
//产生总线停止信号
void I2CStop()
{
SCL=0; //拉低SDA,SCL
SDA=0;
I2CDelay();
SCL=1; // 拉低SCL
I2CDelay(); //确保SDA产生上升沿时,SCL为低电平。
SDA=1; //产生一个上升沿
I2CDelay(); //
}
//I2C总线写操作,dat为待写入的字节
bit IC2Write(unsigned char dat)
{
bit ACK; //用与暂存丛机应答的值
unsigned char mask; //用于探测写入字节内某一位掩码的变量
for(mask=0x80;mask!=0;mask>>=1) //主机要发送的数据,先发送高位再发送低位 此处有疑问
{
if(mask&dat==0) //dat不是一位么,I2C总线是一位一位的发送的,这里按位与后不是一个char型与一位与么。懵逼请教大能。萌新。后面读操作也类似。
{
SDA=0;
}
else
{
SDA=1;
}
I2CDelay(); //延时使其保持一段时间
SCL=1; //拉高SCL
I2CDelay(); //再拉高SCL期间,SDA不可变。因为此时丛机会读取SDA,若SDA改变,则读取可能错误
SCL=0; //再拉低SCL完成一个位周期
}
SDA=1; //8位数据发送完毕后,主机必须释放SDA线,以便从机进行应答
I2CDelay(); //丛机通过拉低或拉高SDA进行应答
SCL=1; //拉高SCL从机即能应答
ACK=SDA; //读取此时SDA的值即为从机的应答值
I2CDelay();
SCL=0; //再拉低SCL完成应答位
return ~ACK; //将应答值返回调用其的函数0表示成功,1表示发送失败。此处~为正常逻辑
}
//I2C总线的读操作,并发送非应答信号,返回值为读到的字节
unsigned char I2CReadyNAck()
{
unsigned char mask;
unsigned char dat; //所读数据缓冲区
SDA=1; //读之前自己引脚为高电平 与按键类似,避免占用总线
for(mask=0x80;mask!=0;mask>>=1)
{
I2CDelay();
SCL=1;
if(SDA==0)
{
dat&=~mask; //将dat对应的位清零
}
else
{
dat|=mask;
}
I2CDelay();
SCL=0; //再拉低SCL以使丛机发送下一位
}
SDA=1; //当丛机将8位数据发送完毕后,拉高SDA,发送非应答信号
I2CDelay();
SCL=1;
I2CDelay();
SCL=0; //再次拉低SCL完成非应答位,并保持住总线
return dat; //将读到的数据返回
}
//I2C总线读操作,并发送应答信号,返回值位为读到的字节
unsigned char I2CReadyAck()
{
unsigned char mask;
unsigned char dat; //所读字节缓冲区
SDA=1; //确保主机释放SDA
for(mask=0x08;mask!=0;mask>>=1)
{
I2CDelay();
SCL=1;
if(SDA==0)
{
dat&=~mask;
}
else(dat|=mask);
I2CDelay();
SCL=0; //在拉低SCL,以使丛机发送出下一位
}
SDA=0; //8为数据发送完毕后,拉低SDA,发送应答信号
I2CDelay();
SCL=1; //拉高SCL
I2CDelay();
SCL=0; //再拉低SCL完成应答位,并保持住总线 此处保持住总线是扫描意思?
return dat;
}
请教老司机解答,实在蒙蔽,有些注释是我自己理解注释的有错误老司机见谅
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
一周热门 更多>