因为教程上说STM32的硬件IIC复杂而且不太稳定,所以这里使用的是直接控制GPIO端口模拟IIC时序的方式进行通信
因为涉及到初始化、发送、接收等多个功能,所以就分成若干个函数来写了
这里涉及的是主设备上IIC的相关代码,因为SCL线的电平由主设备控制,因此主设备的代码会简单一点
从设备涉及到对SCL线上电平的识别,进而涉及到循环判断或者中断,以后有时间再去看看怎么写(挖坑)
一、IIC通信
1.简介
IIC总线是一种串行数据总线,只有二根信号线,一根是双向的数据线SDA,另一根是时钟线SCL,两条线可以挂多个设备。 IIC设备(绝大多数)里有个固化的地址,只有在两条线上传输的值等于IIC设备的固化地址时,其才会作出响应。通常我们为了方便把IIC设备分为主设备和从设备,基本上谁控制时钟线(即控制SCL的电平高低变换)谁就是主设备。
2.时序图
总结下来就是以下几点:
1.正常传输数据时,当SCL线处于低电平期时,SDA线上的电平允许变动
2.正常传输数据时,当SCL线处于高电平期时,SDA线上的电平不变
3.如果在SCL线的高电平期,SDA线由高电平向低电平跳变,则表示开始传输数据(START信号)
4.如果在SCL线的高电平期,SDA线由低电平向高电平跳变,则表示停止传输数据(STOP信号)
由于SCL线受主设备控制,因此主设备上的代码非常好写
发送数据时,只需按照协议规范对应更改SDA、SCL的电平
接收数据时,只有主设备将SCL线设为低电平时SDA线上的电平才会变动,而主设备将SCL线设为高电平后即可稳定地读取SDA线上的电平
二、函数部分
1.初始化
因为使用的是普通GPIO端口,因此其初始化方式和普通GPIO初始化方式相同
这里假设PB6为SCL线,PB7为SDA线
初始化代码如下:
void IIC_Init(void) { GPIO_InitTypeDef GPIO_InitStrc; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitStrc.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStrc.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStrc.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStrc); GPIO_SetBits(GPIOB, GPIO_Pin_6 | GPIO_Pin_7); }
2.产生START信号
按照时序图,当SCL为高电平时,SDA由高电平向低电平跳变,表示开始传送数据
产生START信号的代码如下:
void IIC_Start(void) { SDA_OUT(); IIC_SDA = 1; IIC_SCL = 1; delay_us(4); IIC_SDA = 0; delay_us(4); IIC_SCL = 0; }
(未完待续)
(赶着发是因为↓)
2020.02.02
来源:https://www.cnblogs.com/wh201906/p/12254330.html