
今天分享以下两点内容:( V5 V& ?- T8 I% `7 T 1.为什么我们要先开启STM32外设模块时钟;# E3 k: g9 ]- L) W$ g3 }& T 2.关于STM32的 I/O 复用功能及什么时候开启AFIO时钟;3 {+ A, w* W/ b# ]! K- Y% O$ k 1为什么我们要先开启STM32外设时钟# F, |8 M8 R3 q: c1 t, d' o% o 讲述本节内容之前先说一个案例:" L3 y B4 d, l: x, ^# C$ C 前段时间,有一个朋友为配置EXti的代码折腾了一天,最终没有结果。于是问了我这样一个问题:“你用过STM32F051C8T6的外部中断吗,就是GPIO管脚做中断,我这边就是进不了中断”。 然后他把基于标准外设库、寄存器写的代码都给我发过来了。我仔细看了又看,没发现有什么毛病啊。(但是,代码是截图分来给我发过来的)。: y' U1 l. k' F* i9 F3 H 于是,我将之前配置IO外部中断的代码,按照他(PB2)的要求,写成一个“EXTI配置”函数发给他,他直接拷贝过去,成功了。& z. F: a6 A$ P 于是,他仔细对比了代码,终于发现了问题的原因,配置的顺序不对,使能时钟不是在最开始。. m+ Y! [8 ~* @6 Z1 P& i 我想许多朋友都曾遇到过这种坑,我最初学习STM32的时候同样也遇到过,下面我就来说说为什么我们要先开启STM32外设模块时钟,再对其外设模块初始化配置?9 |) U+ J+ ?* g- g ~ 1.系统架构# E U* C% r4 u0 [1 c4 t9 ], ]* n 不同类型的STM32,它的系统架构各有不同,但原理都类似,由多条主控总线和多条被控总线组成(请参看【参考手册】存储器和总线架构章节)。 如STM32F4: ● 八条主控总线:! ~) H# _# _& F4 f3 L — Cortex-M4F 内核 I 总线、 D 总线和 S 总线 — DMA1 存储器总线 — DMA2 存储器总线$ V( G( [; \% d7 i — DMA2 外设总线 — 以太网 DMA 总线 — USB OTG HS DMA 总线 ● 七条被控总线: — 内部 Flash ICode 总线 — 内部 Flash DCode 总线5 @1 D' r: j, h# R ^5 r2 z" J — 主要内部 SRAM1 (112 KB)& |0 u/ ?1 _7 B6 n( E. [ — 辅助内部 SRAM2 (16 KB)5 V4 c) p* }8 _. H — 辅助内部 SRAM3 (64 KB)(仅适用于 STM32F42xxx 和 STM32F43xxx 器件) — AHB1 外设(包括 AHB-APB 总线桥和 APB 外设) — AHB2 外设 — FSMC ![]() 2.关于AHB和APB总线- k, V" D f; O" Z4 @7 S AHB:Advanced High-peRFormance Bus,即先进的高性能总线. APB:Advanced Peripheral Bus,即先进的外围(外设)总线.! k/ L! F/ s! d 上面说了系统总线的架构引伸出来的就是AHB和APB总线,那为什么要讲述AHB和APB总线呢?- p, i, H& g+ N+ x1 @& L' y8 l2 D- G 我们操作的外围设备一般都是位于AHB和APB总线上,而AHB可以引伸出AHB1、AHB2,甚至AHB3。同样APB也存在APB1、APB2等。) a* w& c% N/ H. b1 Y 如:USART1外设位于APB1总线上,GPIOA位于AHB1高速总线上。 请注意参考手册中“AHB/APB 总线桥”这一小节,有一条重要的内容:每次芯片复位后,所有外设时钟都被关闭( SRAM 和 Flash 接口除外)。使用外设前,必须在 RCC_AHBxENR 或 RCC_APBxENR 寄存器中使能其时钟。 3.STM32时钟控制 请参看STM32参考手册关于【复位与时钟控制RCC】章节。 ![]() 降低功耗是主要原因,还有一个原因,就是为了兼容不同速度的设备,有些高速,有些低速,如果都用高速时钟,势必造成浪费。- ?- h" a. ?9 Y% C, y RCC给外设提供时钟是一个主要目的,那么为什么要提供时钟呢? 原因在于外围设备的寄存器需要时钟才能工作。你可以把外设当做一个设备,而这个设备需要给它提供电源(时钟)才能工作。 你在STM32参考手册的“RCC”章节可能会看到这么一句话:当外设时钟没有启用时,软件不能读出外设寄存器的数值,返回的数值始终是0x0。 4.总结 看到这里相信聪明的你其中已经明白为什么我们要先开启STM32外设模块时钟,再配置其外设模块了。 简单来说:操作外设是通过外设总线来实现,只有外设总线有时钟了才能操作外设。) j: P: j: R% e' m! p( q) s' g 坑:; r r: f3 f8 b8 r/ b) S$ a& p A.先使能外设时钟,再对其进行配置% [' p% Y& ^" E1 g2 Q+ K ![]() ![]() 2关于STM32的I/O复用功能及什么时候开启AFIO时钟 前面有朋友问:“什么时候开启AFIO时钟”。写了上面章节,就顺便再讲述一下关于STM32的I/O复用功能及什么时候开启AFIO时钟。 1.什么是I/O 复用功能?3 _4 _! T6 P0 h4 Q% B 简单来说就是把普通I/O用作其它的功能。如:将PA9引脚用作USART1的Tx引脚,那么我们就把这个Tx引脚称为PA9的复用功能。0 R" z# f4 a' y d( X; y* ]1 n) V 打开数据手册,会发现类似如下的列表: ![]() 为了优化芯片引脚封装的外设数目,可以把一些复用功能重新映射到其他引脚上。设置复用重映射和调试I/O配置寄存器实现引脚的重新映射。这时,复用功能不再映射到它们的原始分配上,而是映射到“重定义功能”上(见上图)。7 x1 V2 }: E5 u: h# e 这种将引脚重定义到其它引脚上的功能在几乎所有STM32芯片中都有这个功能,但是实现的方法可能有所不同,其中STM32F1就是通过事件控制的方式将特定功能引脚连接到对应PORT和PIN上。4 `3 z# x& [: E# D) ^ 简单来说,如果需要使用重定义功能,那么就需要开启AFIO时钟。 最后,如果你觉得你的程序可能是因为时钟配置的问题,不妨上电第一步使能所有时钟试试。 推荐阅读:$ S" K# y( z) i7 g/ ` 1.STM32标准外设库SPL转换成Cube LL4 X; L# O( l+ w 2.利用STM32 ST-LINK Utility查看内核运行状态,助你判断程序是否跑飞( _8 E8 }# t& N8 J+ e# n |