打印
[应用相关]

[学习笔记] STM32的I/O口结构和访问

[复制链接]
1648|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
cruelfox|  楼主 | 2018-12-28 15:07 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
参考资料: STM32各系列的参考手册(Reference Manual)

新接触到一款MCU的时候最开始试验的程序多半会是用GPIO来驱动LED变化,俗称“点个灯”。 STM32各系列的I/O口功能比较全了,除了可配置成片上外设专用功能以外,本身作为GPIO的特性就很丰富,当初从8位机过来会感到眼前一亮。下面这个图是STM32 I/O口电路连接的构造:


注意到有几个特点:
(1) 作为输出使用时,具备推挽输出的能力,两个MOS管一起提供强驱动。(另外是可以配置成开漏输出的,这张图没有明示)
(2) 不论作为输入还是输出,还是作为外设的复用功能,上拉和下拉都是可以单独开启的。
(3) 配置为复用功能只是让输出模式的I/O口高低状态由片上外设决定,而不是GPIO的输出数据寄存器决定(图上那个MUX);而是否推挽输出,是否上拉下拉仍由GPIO配置;GPIO的输入寄存器仍然反映引脚的电平状态。遗留问题:复用功能到底是输出还是输入,由谁决定?这里没有体现。
(4) 模拟输入的信号是直接从引脚连过去的,到数字输入寄存器的信号可以使能或禁止,以防止引脚悬空引起内部逻辑翻转。模拟输出信号也是直接连到引脚上。
(5) 引脚具有保护二极管,具体根据引脚容忍电压类型存在不同连接。


从结构图可以看出I/O口的能力,那么有哪些配置的组合,就得看寄存器表了。在STM32上,主要由 GPIO 外设来管理I/O口的设置。
以 STM32F0x 系列为例,包含如下寄存器:每一组GPIO (A, B, C...) 都对应一组寄存器,每组最多16个I/O口
GPIOx_MODER           每口 2-bit,决定基本功能:GPIO输入/GPIO输出/复用功能/模拟用途
GPIOx_OTYPER           每口 1-bit,决定是推挽输出还是开漏输出
GPIOx_OSPEEDR           每口 2-bit,决定输出翻转速度,最多有4档
GPIOx_PUPDR            每口 2-bit,决定是否开启上拉或者下拉
GPIOx_ODR           每口 1-bit,作GPIO输出时引脚输出驱动高低
GPIOx_IDR           每口 1-bit,读引脚电平状态
GPIOx_BSRR           每口 2-bit(实际上这个寄存器分成两半,写1来实现置位/复位输出寄存器)
GPIOx_LCKR           每口 1-bit,锁定该口的配置,以后不许更改
GPIOx_AFRL/AFRH           每口 4-bit,复用功能的编号
GPIOx_BRR           每口 1-bit,写1复位输出寄存器


上面 F0x 的 GPIO 寄存器表中,最常用到的是 MODER 寄存器,设置端口类型——GPIO输入/输出用途,还是分配给设备。然后,复用功能具体对应哪一个外设,在 AFRL, AFRH 这两个寄存器中去指定。我习惯于用 C 代码直接操作寄存器,所以觉得这样配置还蛮简洁的。必要使用开漏输出,或者上下拉时再配置相应的寄存器,否则用默认的就好了。

我买的第一款 STM32 是 F103C8T6,但它的 GPIO 寄存器表不是上面这样,没有 MODER, OTYPER, OSPEEDR, PUPDR 而是代之以:
GPIOx_CRL/CRH 两个寄存器,其中每个 I/O 口又有 2-bit 的 MODE 和 2-bit 的 CNF 位来控制

这个配起来比较费劲,因为 CNF 每个bit的意义不独立,又跟MODE扯上了关系,而MODE的意义也不仅是端口速度。而且,输入上拉居然还需要 ODR 寄存器来管理。像 F0x (其实除了F1x, 其它系列都是一样) 那样的 GPIO 寄存器表就清晰多了。

F1x 系列的复用功能设置也跟其它不同。这里没有 AFRL/AFRH 寄存器,而另外有一个 AFIO 设备来选择每个外设的功能引脚分配到哪些GPIO引脚上。例如下表是某个AFIO的寄存器

但是通过 AFIO remap 控制来配置很不直观。(估计因此后来这个方式被废弃了,代之以GPIO AFRx寄存器,这样与芯片手册中的复用功能表直接对应)
AFIO 设备还有管理外部中断引脚分配的功能,后来都移到了 SYSCFG 中。在 F0x/F2x/F3x/F4x/L1x/L4x/F7x 系列的手册中,我已经看不到 AFIO 设备了。

因此,除了老旧的仍在大量被用的 STM32F10x 系,新的 STM32 都用了一致的 GPIO 访问方式,寄存器的功能规划合理易懂。当然,如果用 CubeMX 来生成配置,可以不管这些细节的。
否则,即使在标准设备库里面,GPIO_InitTypeDef 结构类型的字段也不完全一样,不能不修改就移植 C 代码。

每次在新建一个项目,配置 STM32 GPIO的时候,主要的工作其实是配置复用功能——(如果没有用CubeMX)查手册中的 AF 号码,写到 AFRx 寄存器里。标准设备库函数的 GPIO_PinAFConfig() 提供一个快捷书写方式,定义了一些宏辅助。
沙发
huangcunxiake| | 2018-12-29 00:05 | 只看该作者
点灯看着简单,想点好了很难。

使用特权

评论回复
板凳
huangcunxiake| | 2018-12-29 00:05 | 只看该作者
比如IO口的各种复用功能都试试。

使用特权

评论回复
地板
mmuuss586| | 2018-12-30 12:02 | 只看该作者
支持,感谢分享

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

17

主题

50

帖子

1

粉丝