51单片机 | IIC | 软件模拟 | 基础驱动

KDRNN6个月前 (08-30)编码168

在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;
}


    相关文章

    IIC总线

    From 尚硅谷1.1 概述    I…

    发表评论

    访客

    ◎欢迎参与讨论,请在这里发表您的看法和观点。