文章目录[隐藏]
I2C开始
根据如下图显示是I2C开始的的信号处理,从左到有的来看,在SCL为1高电平时候,SDA发生了由 1高电平
到 0低电平
的转换。
void I2C_Start(void)
{
I2C_SDA=1;
I2C_SCL=1;
I2C_SDA=0;
I2C_SCL=0;
}
I2C结束
在SCL为1高电平时候,SDA发生了由 0低电平
到 1高电平
的转换。
SDA=0;
SCL=1;
SDA=1;
I2C接收的方法与波形对比
遵循上面的时序分析的思路,我们查看接收数据位的波形变化。
接收一个字节:SCL低电平期间,从机将数据位依次放到SDA线上(高位在前),然后拉高SCL,主机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可接收一个字节(主机在接收之前,需要释放SDA)
下面的代码,假如byte发送的字节为0xFE = 1111 1110;采用的思想就是按位循环的把这些数字给摘
出来,摘
的方式就是用 1 分别 与
到最后一位(也就是 按位与
)。
void I2C_SendByte(unsigned char Byte)
{
unsigned char i;
for(i=0;i<8;i++)
{
I2C_SDA=Byte&(0x80>>i);
I2C_SCL=1;
I2C_SCL=0;
}
}
代码每次按位与执行的操作。
第一次:
1111 1110 & 1000 0000 = 1000 0000
第二次:
1111 1110 & 0100 0000 = 0100 0000
第三次:
1111 1110 & 0010 0000 = 0010 0000
第四次:
1111 1110 & 0001 0000 = 0001 0000
第五次:
1111 1110 & 0000 1000 = 0000 1000
依次到最后一位
第八次:
1111 1110 & 0000 0001 = 0000 0000
下面是接收一个字节的代码逻辑
//用一个空的字节去接收,依次进行循环,如果收到SDA为1,移位到 `下标i` 的位置处。
unsigned char I2C_ReceiveByte(void)
{
unsigned char i,Byte=0x00;
I2C_SDA=1;
for(i=0;i<8;i++)
{
I2C_SCL=1;
if(I2C_SDA){Byte|=(0x80>>i);}
I2C_SCL=0;
}
return Byte;
}
接收应答的波形变化与对应的代码逻辑
注意上图的红框位置,表示的是电平信号发送变换的部分
如下是I2C接收应答,发送数据全部代码
#include <REGX52.H>
sbit I2C_SCL=P2^1;
sbit I2C_SDA=P2^0;
/**
* @brief I2C开始
* @param 无
* @retval 无
*/
void I2C_Start(void)
{
I2C_SDA=1;
I2C_SCL=1;
I2C_SDA=0;
I2C_SCL=0;
}
/**
* @brief I2C停止
* @param 无
* @retval 无
*/
void I2C_Stop(void)
{
I2C_SDA=0;
I2C_SCL=1;
I2C_SDA=1;
}
/**
* @brief I2C发送一个字节
* @param Byte 要发送的字节
* @retval 无
*/
void I2C_SendByte(unsigned char Byte)
{
unsigned char i;
for(i=0;i<8;i++)
{
I2C_SDA=Byte&(0x80>>i);
I2C_SCL=1;
I2C_SCL=0;
}
}
/**
* @brief I2C接收一个字节
* @param 无
* @retval 接收到的一个字节数据
*/
unsigned char I2C_ReceiveByte(void)
{
unsigned char i,Byte=0x00;
I2C_SDA=1;
for(i=0;i<8;i++)
{
I2C_SCL=1;
if(I2C_SDA){Byte|=(0x80>>i);}
I2C_SCL=0;
}
return Byte;
}
/**
* @brief I2C发送应答
* @param AckBit 应答位,0为应答,1为非应答
* @retval 无
*/
void I2C_SendAck(unsigned char AckBit)
{
I2C_SDA=AckBit;
I2C_SCL=1;
I2C_SCL=0;
}
/**
* @brief I2C接收应答位
* @param 无
* @retval 接收到的应答位,0为应答,1为非应答
*/
unsigned char I2C_ReceiveAck(void)
{
unsigned char AckBit;
I2C_SDA=1;
I2C_SCL=1;
AckBit=I2C_SDA;
I2C_SCL=0;
return AckBit;
}
图片资源来自 B站江科大自化协老师《51单片机入门教程-2020版 程序全程纯手打 从零开始入门》
版权声明:本文为CSDN博主「Hello_Ray」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Hello_Ray/article/details/121386029
暂无评论