×
单片机 > 单片机程序设计 > 详情

梳理STM32F429之通信传输部分---NO.2 硬件IIC

发布时间:2020-08-28 发布时间:
|

一、STM32 的 I2C 特性及架构:

只要遵守协议,就是标准的通讯,不管如何实现它,不管是 ST 生产的控制器还是 ATMEL 生产的存储器, 都能按通讯标准交互。


由于直接控制 GPIO 引脚电平产生通讯时序时,需要由 CPU 控制每个时刻的引脚状态,所以称之为“软件模拟协议”方式。


相对地,还有“硬件协议”方式, STM32 的 I2C 片上外设专门负责实现 I2C 通讯协议,只要配置好该外设,它就会自动根据协议要求产生通讯信号,收发数据并缓存起来, CPU只要检测该外设的状态和访问数据寄存器,就能完成数据收发。这种由硬件外设处理 I2C协议的方式减轻了 CPU 的工作,且使软件设计更加简单。


1、STM32 的 I2C 外设简介:


STM32 的 I2C 外设可用作通讯的主机及从机,支持 100Kbit/s 和 400Kbit/s 的速率,支持 7 位、 10 位设备地址,支持 DMA 数据传输,并具有数据校验功能。它的 I2C 外设还支持 SMBus2.0 协议, SMBus 协议与 I2C 类似,主要应用于笔记本电脑的电池管理中,本教程不展开,感兴趣的读者可参考《SMBus20》文档了解。


2、STM32 的 I2C 架构剖析:


(1)通讯引脚:


 I2C 的所有硬件架构都是根据 SCL 线和 SDA 线展开的。 STM32 芯片有多个 I2C 外设,它们的 I2C 通讯信号引出到不同的 GPIO 引脚上,使用时必须配置到这些指定的引脚,见下表。关于GPIO 引脚的复用功能,可查阅《STM32F4xx 规格书》,以它为准。


(2)时钟控制逻辑:


SCL 线的时钟信号,由 I2C 接口根据时钟控制寄存器(CCR)控制,控制的参数主要为时钟频率。配置 I2C 的 CCR 寄存器可修改通讯速率相关的参数:可选择 I2C 通讯的“标准/快速”模式,这两个模式分别 I2C 对应 100/400Kbit/s 的通讯速率。


(3)数据控制逻辑:


I2C 的 SDA 信号主要连接到数据移位寄存器上,数据移位寄存器的数据来源及目标是数据寄存器(DR)、地址寄存器(OAR)、 PEC 寄存器以及 SDA 数据线。当向外发送数据的时候,数据移位寄存器以“数据寄存器”为数据源,把数据一位一位地通过 SDA 信号线发送出去;当从外部接收数据的时候,数据移位寄存器把 SDA 信号线采样到的数据一位一位地存储到“数据寄存器”中。若使能了数据校验,接收到的数据会经过 PCE 计算器运算,运算结果存储在“PEC 寄存器”中。当 STM32 的 I2C 工作在从机模式的时候,接收到设备地址信号时,数据移位寄存器会把接收到的地址与 STM32 的自身的“ I2C 地址寄存器”的值作比较,以便响应主机的寻址。 STM32 的自身 I2C 地址可通过修改“自身地址寄存器”修改,支持同时使用两个 I2C 设备地址,两个地址分别存储在 OAR1 和 OAR2 中。


(4)整体控制逻辑:


整体控制逻辑负责协调整个 I2C 外设,控制逻辑的工作模式根据我们配置的“控制寄存器(CR1/CR2)”的参数而改变。在外设工作时,控制逻辑会根据外设的工作状态修改“状态寄存器(SR1 和 SR2)”,我们只要读取这些寄存器相关的寄存器位,就可以了解 I2C的工作状态了。除此之外,控制逻辑还根据要求,负责控制产生 I2C 中断信号、 DMA 请求及各种 I2C 的通讯信号(起始、停止、响应信号等)。


3、通讯过程:


 使用 I2C 外设通讯时,在通讯的不同阶段它会对“状态寄存器(SR1 及 SR2)”的不同数据位写入参数,我们通过读取这些寄存器标志来了解通讯状态。


① 主发送器

下图中的是“主发送器”流程,即作为 I2C 通讯的主机端时,向外发送数据时的过程。


主发送器发送流程及事件说明如下:

(1) 控制产生起始信号(S),当发生起始信号后,它产生事件“EV5”,并会对 SR1 寄存器的“ SB”位置 1,表示起始信号已经发送;

(2) 紧接着发送设备地址并等待应答信号,若有从机应答,则产生事件“ EV6”及“ EV8”,这时 SR1 寄存器的“ADDR”位及“ TXE”位被置 1, ADDR 为 1 表示地址已经发送, TXE 为 1 表示数据寄存器为空;

(3) 以上步骤正常执行并对 ADDR 位清零后,我们往 I2C 的“数据寄存器 DR”写入要发送的数据,这时 TXE 位会被重置 0,表示数据寄存器非空, I2C 外设通过SDA 信号线一位位把数据发送出去后,又会产生“ EV8”事件,即 TXE 位被置 1,重复这个过程,就可以发送多个字节数据了;

(4) 当我们发送数据完成后,控制 I2C 设备产生一个停止信号(P),这个时候会产生EV2 事件, SR1 的 TXE 位及 BTF 位都被置 1,表示通讯结束。假如我们使能了 I2C 中断,以上所有事件产生时,都会产生 I2C 中断信号,进入同一个中断服务函数,到 I2C 中断服务程序后,再通过检查寄存器位来了解是哪一个事件。

② 主接收器:

再来分析主接收器过程,即作为 I2C 通讯的主机端时,从外部接收数据的过程,见下图:

主接收器接收流程及事件说明如下:

(1) 同主发送流程,起始信号(S)是由主机端产生的,控制发生起始信号后,它产生事件“ EV5”,并会对 SR1 寄存器的“ SB”位置 1,表示起始信号已经发送;

(2) 紧接着发送设备地址并等待应答信号,若有从机应答,则产生事件“ EV6”这时SR1 寄存器的“ ADDR”位被置 1,表示地址已经发送。

(3) 从机端接收到地址后,开始向主机端发送数据。当主机接收到这些数据后,会产生“ EV7”事件, SR1 寄存器的 RXNE 被置 1,表示接收数据寄存器非空,我们读取该寄存器后,可对数据寄存器清空,以便接收下一次数据。此时我们可以控制 I2C 发送应答信号(ACK)或非应答信号(NACK),若应答,则重复以上步骤接收数据,若非应答,则停止传输;

(4) 发送非应答信号后,产生停止信号(P),结束传输。在发送和接收过程中,有的事件不只是标志了我们上面提到的状态位,还可能同时标志主机状态之类的状态位,而且读了之后还需要清除标志位,比较复杂。我们可使用STM32 标准库函数来直接检测这些事件的复合标志,降低编程难度。


二、I2C 初始化结构体详解:

跟其它外设一样, STM32 标准库提供了 I2C 初始化结构体及初始化函数来配置 I2C 外设。初始化结构体及函数定义在库文件“ stm32f4xx_i2c.h”及“ stm32f4xx_i2c.c”中,编程时我们可以结合这两个文件内的注释使用或参考库帮助文档。了解初始化结构体后我们就能对 I2C 外设运用自如了,见下面代码清单。


typedef struct {

uint32_t I2C_ClockSpeed; /*!< 设置 SCL 时钟频率,此值要低于 40 0000*/

uint16_t I2C_Mode; /*!< 指定工作模式,可选 I2C 模式及 SMBUS 模式 */

uint16_t I2C_DutyCycle; /*指定时钟占空比,可选 low/high = 2:1 及 16:9 模式*/

uint16_t I2C_OwnAddress1; /*!< 指定自身的 I2C 设备地址 */

uint16_t I2C_Ack; /*!< 使能或关闭响应(一般都要使能) */

uint16_t I2C_AcknowledgedAddress; /*!< 指定地址的长度,可为 7 位及 10 位 */

} I2C_InitTypeDef;

这些结构体成员说明如下,其中括号内的文字是对应参数在 STM32 标准库中定义的宏:


(1) I2C_ClockSpeed

本成员设置的是 I2C 的传输速率,在调用初始化函数时,函数会根据我们输入的数值经过运算后把时钟因子写入到 I2C 的时钟控制寄存器 CCR。而我们写入的这个参数值不得高于 400KHz。 实际上由于 CCR 寄存器不能写入小数类型的时钟因子,影响到 SCL 的实际频率可能会低于本成员设置的参数值,这时除了通讯稍慢一点以外,不会对 I2C 的标准通讯造成其它影响。


(2) I2C_Mode

本成员是选择 I2C 的使用方式,有 I2C 模式(I2C_Mode_I2C )和 SMBus 主、从模式(I2C_Mode_SMBusHost、 I2C_Mode_SMBusDevice ) 。 I2C 不需要在此处区分主从模式,直接设置 I2C_Mode_I2C 即可。


(3) I2C_DutyCycle


本成员设置的是 I2C 的 SCL 线时钟的占空比。 该配置有两个选择,分别为低电平时间比高电平时间为 2: 1 ( I2C_DutyCycle_2)和 16: 9 (I2C_DutyCycle_16_9)。其实这两个模式的比例差别并不大,一般要求都不会如此严格,这里随便选就可以了。


(4) I2C_OwnAddress1

本成员配置的是 STM32 的 I2C 设备自己的地址,每个连接到 I2C 总线上的设备都要有一个自己的地址,作为主机也不例外。 地址可设置为 7 位或 10 位(受下面I2C_AcknowledgeAddress 成员决定),只要该地址是 I2C 总线上唯一的即可。STM32 的 I2C 外设可同时使用两个地址,即同时对两个地址作出响应,这个结构成员I2C_OwnAddress1 配置的是默认的、 OAR1 寄存器存储的地址,若需要设置第二个地址寄存器 OAR2,可使用 I2C_OwnAddress2Config 函数来配置, OAR2 不支持 10 位地址。


(5) I2C_Ack_Enable


本成员是关于 I2C 应答设置,设置为使能则可以发送响应信号。 该成员值一般配置为允许应答(I2C_Ack_Enable),这是绝大多数遵循 I2C 标准的设备的通讯要求,改为禁止应答(I2C_Ack_Disable)往往会导致通讯错误。


(6) I2C_AcknowledgeAddress


本成员选择 I2C 的寻址模式是 7 位还是 10 位地址。这需要根据实际连接到 I2C 总线上设备的地址进行选择,这个成员的配置也影响到 I2C_OwnAddress1 成员,只有这里设置成10 位模式时, I2C_OwnAddress1 才支持 10 位地址。


配置完这些结构体成员值,调用库函数 I2C_Init 即可把结构体的配置写入到寄存器中。

关键字:STM32F429  通信传输  硬件IIC 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
如何为单片机选择合适的负载电容