2.STM32嵌入式学习(I2C通信)

I2C通信工作原理

I2C通信与USART通信硬件结构对比:
USART结构:
usart传输主要是通过两根线,一根RX用于接收,一根TX用于发送(注意两个设备RX和TX要交叉相连),是一种全双工,异步的通信方式。我们使用usart串口进行通信的化主要是设定好两个设备的参数,常用的参数是:波特率为115200,数据位长度为8位,无校验位,1位的停止位。在USART章节已经详细的讲解过,这里就不在详细解释
在这里插入图片描述
I2C通信模拟图:
I2C通信,他是同步半双工通信。他由一根SCL控制时钟,SDA用来发送数据。他可以挂载多设备,通过主机实现对外部多个从设备的通信,而usart只能是两个设备之间的通信,所以这也是I2C通信优势所在。
在这里插入图片描述
下面我就详细说下I2C是如何进行通信的:
主机拥有对SCL的绝对控制权,以及在空闲时将SDA的控制权交给从机的权利。
1.主机发送/读取从机数据:
主机控制SCL产生时钟信号,在SCL低电平时,主机释放对SDA的控制权,从机可以在这个时候将自己的数据放到SDA线上发送,获得SDA线的暂时控制权。在SCL高电平时,主机重新获得SDA的控制权,这个时候不允许SDA的电平发生跳变,因为主机要读取SDA线上的数据。因为一个字节是8位的,所以上述过程重复8次我们就可以读取一个完整的字节。
2.从机发送/读取主机发送数据:
其实和主机读取从机数据是差不多的。主机控制SCL产生时钟信号,在SCL低电平时,主机将数据放到SDA线。控制SDA的高低电平。在SCL高电平时,从机读取SDA线上的数据。因为一个字节是8位的,所以上述过程重复8次我们就可以读取一个完整的字节。

软件模拟I2C通信协议

I2C协议可以使用硬件来实现,也可以利用软件来自己模拟,使用硬件的来实现的话就要查看数据手册,确定好使用对应的GPIO口,利用STM32官方提供的库函数来实现。使用软件来模拟I2C通信协议,选择任意I/O口就可以,但是需要自己从底层来书写协议。那么我们本章我们通过软件来实现I2C通信。
想要实现I2C通信,我们就需要知道I2C的通信时序,也就对应我们需要书写的6个底层函数。

I2C通信时序

I2C时序可以大致分为6个时序:起始时序,终止时序,发送应答,接收应答,发送一个字节,接收一个字节。
1.起始条件:SCL高电平期间,SDA从高电平变为低电平(下降沿)
在这里插入图片描述
2.终止条件
SCL高电平期间,SDA由低电平变为高电平(上升沿)

在这里插入图片描述
3.发送一个字节
发送一个字节:SCL低电平期间,主机将数据位依次放到SDA线上(高位先行),然后释放SCL,从机将在SCL高电平期间读取数据位所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次即可发送一个字节
在这里插入图片描述
4.接收一个字节
接收一个字节:SCL低电平期间,从机将数据位依次放到SDA线上(高位先行),然后释放SCL,主机将在SCL高电平期间读取数据位所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次即可接收一个字节 (主机在接收之前,需要释放SDA)(虚线表示从机控制SDA)
在这里插入图片描述
5.发送应答
发送应答:主机在接收完一个字节之后在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答在下一个时钟接收一位数
在这里插入图片描述

6.接收应答
接收应答:主机在发送完一个字节之后据,判断从机是否应答,数据0表示应答,数据1表示非应答(主机在接收之前,需要释放SDA)(虚线表示从机控制SDA)
在这里插入图片描述

软件模拟I2C配置流程

1.初始化GPIO端口
2.书写六个基本时序函数

具体代码

//初始化GPIO端口,配置位开漏输出模式
void MyI2C_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	GPIO_SetBits(GPIOB, GPIO_Pin_10 | GPIO_Pin_11);
//封装三个函数
void MyI2C_W_SCL(uint8_t BitValue)
{
	GPIO_WriteBit(GPIOB, GPIO_Pin_10, (BitAction)BitValue);
	Delay_us(10);
}

void MyI2C_W_SDA(uint8_t BitValue)
{
	GPIO_WriteBit(GPIOB, GPIO_Pin_11, (BitAction)BitValue);
	Delay_us(10);
}

uint8_t MyI2C_R_SDA(void)
{
	uint8_t BitValue;
	BitValue = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11);
	Delay_us(10);
	return BitValue;
}
//六个时序
void MyI2C_Start(void)
{
	MyI2C_W_SDA(1);
	MyI2C_W_SCL(1);
	MyI2C_W_SDA(0);
	MyI2C_W_SCL(0);
}

void MyI2C_Stop(void)
{
	MyI2C_W_SDA(0);
	MyI2C_W_SCL(1);
	MyI2C_W_SDA(1);
}

void MyI2C_SendByte(uint8_t Byte)
{
	uint8_t i;
	for (i = 0; i < 8; i ++)
	{
		MyI2C_W_SDA(Byte & (0x80 >> i));
		MyI2C_W_SCL(1);
		MyI2C_W_SCL(0);
	}
}

uint8_t MyI2C_ReceiveByte(void)
{
	uint8_t i, Byte = 0x00;
	MyI2C_W_SDA(1);
	for (i = 0; i < 8; i ++)
	{
		MyI2C_W_SCL(1);
		if (MyI2C_R_SDA() == 1){Byte |= (0x80 >> i);}
		MyI2C_W_SCL(0);
	}
	return Byte;
}

void MyI2C_SendAck(uint8_t AckBit)
{
	MyI2C_W_SDA(AckBit);
	MyI2C_W_SCL(1);
	MyI2C_W_SCL(0);
}

uint8_t MyI2C_ReceiveAck(void)
{
	uint8_t AckBit;
	MyI2C_W_SDA(1);
	MyI2C_W_SCL(1);
	AckBit = MyI2C_R_SDA();
	MyI2C_W_SCL(0);
	return AckBit;
}

结语

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值