51单片机 | IIC | 软件模拟 | 基础驱动
在Dri_IIC中先定义SCL和SDA:
#define SCL P17 #define SDA P16
1.初始化/开始信号
当SCL高电平时,SDA由高电平变为低电平,视为起始信号。
所以SCL与SDA要设置初始状态为高电平:
SCL = 1; SDA = 1;
此时SDA变为低电平,发出起始信号,然后SCL置为低电平,等待数据位:
SDA = 0; SCL = 0;
起始阶段结束,完整代码:
void Dri_IIC_Start()
{
SCL = 1;
SDA = 1;
SDA = 0;
SCL = 0;
}2.发送数据
IIC协议在SCL位于高电平时读取SDA,故要先设定好SDA,再将SCL置为高电平,
SCL高电平期间稳定SDA,随后将SCL设低电平,流程逻辑:
SDA = data; SCL = 1; SCL = 0;
要发送八位数据(一字节),可使用
for (i = 0; i < 8; i++)
来进行八次扫描。
因为数据从高位起始,利用 1000 0000 右移 i 位并和byte进行与运算,对结果进行判断并填充SDA:
SDA = (byte & (0x80 >> i)) == 0 ? 0 : 1;
完整代码:
void Dri_IIC_SendByte(unsigned char byte)
{
unsigned char i;
for (i = 0; i < 8; i++){
SDA = (byte & (0x80 >> i)) == 0 ? 0 : 1;
SCL = 1;
SCL = 0;
}
}3.接收确认位
IIC所有设备引脚以开漏模式接入总线,故要在数据传输完毕后释放SDA,使从机可以操纵SDA电平:
SDA = 1;
释放SDA后,SCL置为低电平,供SDA调整,随后SCL需位于高电平读取确认位后回到低电平。
完整代码:
bit Dri_IIC_ReceiveAck()
{
bit ack;
SDA = 1;
SCL = 1;
ack = SDA;
SCL = 0;
return ack;
}4.接收数据
只需要先准备SDA,再将SCL置高电平读取即可。
完整代码:
void Dri_IIC_SendAck(bit ack)
{
SDA = ack;
SCL = 1;
SCL = 0;
}5.结束信号
在SCL高电平期间,若SDA拉高,视为结束信号,所以此时所需初始值SDA/SCL均为低电平。
因为无法确定SDA当前电位,所以在拉高SCL前先拉低SDA,避免SCL置为高电平后SDA降低而误发送起始信号。
完整代码:
void Dri_IIC_Stop()
{
SDA = 0;
SCL = 1;
SDA = 1;
}
