在做STM32开发应用的过程中,常常会遇到这样那样的问题,其中相当部分问题是与各外设及相关GPIO的配置有关的。就这方面的问题,这里一起总结交流下。
目前的STM32芯片是基于ARM内核的可编程微处理器,我们可以简单地把内核以外的东西统称为外设,比方 TIMER、UART、SPI、USB、I2C、存储器等功能模块。以32F427芯片功能框图为例,那些红圈上的都是。
好,我们直接切入主题。围绕外设的配置,我们遇到的问题,大致可以分为两大类。
一、时钟问题,就这方面的问题又可以细分为几小点。
1.1 时钟没打开就使用。
这个不难理解,就是相关外设的时钟没有打开。比如UART5的时钟没有打开,SPI的时钟没打开等,自然操作不了或没反应。
1.2 时钟因为总线的判断错误而开错了时钟。简单点说是张冠李戴了。
这个之前经常有人发生。比如类似USART1与USART2、SP1与SP2、TIM1与
TIM2可能并不在同一总线上,配置时以为一样,结果出了问题。
1.3 时钟数率配置错误。
这点跟第2点似乎有些交叉,这里主要是指因为时钟数据配置错误导致供给外设的时钟过高导致异常。曾经就有人因给32F1系列芯片的USB配置时钟时因高于48M,使其性能极不稳定而抓狂。
1.4 复用时钟没打开,即AFIO时钟没打开。
前面三点都没问题,配置正确无误,有些功能必须打开复用时钟,结果不知或忘记打开。说AFIO时钟主要是针对STM32F1系列的芯片。这点后面还会继续补充陈述。
二、GPIO管脚物理安排及配置问题,这个也可以细分两类。
2.1 管脚复用时出现了竞争冲突,即某个或某几个管脚同时分配给了2个外设来使用。
某工程师在使用STM32F103V的芯片时,同时用到两个I2C,结果发现总是I2C2工作正常,而I2C1工作不正常。时钟、脚位本身配置都没有问题。后来,发现他启用了相关FSMC的功能,其中FSMC有个功能脚刚好与I2C1的SDA 脚冲突了。
2.2 需要重映射的脚位没进行REMAP操作。
对于STM32F1系列需要重映射的功能脚,数据手册里会在REMAP栏标注出来。
比如上图中的USART_TX/RX的功能必须执行相关REMAP指令后才能在PB6/7是体现相关功能。记住还要打开GPIOB的时钟和USART1的时钟。
2.3 接着1.4的话题多说几句。
前面1.4提到了AFIO时钟问题。AFIO时钟只是在STM32F1系列里被提及。对于32F1系列,涉及到管脚的EXTI、REMAP、事件输出时就需要开启AFIO时钟。比方上面提到的管脚REMAP,必须先开AFIO时钟。配置EXTI中断也是一样,否则不生效。
对于STM32F1以外的其它STM32系列,不再提AFIO,多了个SYSCFG【系统控制器】外设,其功能跟F1的AFIO 有些类似但有差异,主要管理内存空间的映射、与EXTI中断源有关的IO配置以及其它配置等事务,不同32系列间还各有细小差异。
如果不打开SYSCFG时钟,有关内存空间重映射、与EXTI配置的操作就会无效。
/* Enable SYSCFG clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
对于STM32F1以外的其它系列的管脚复用安排,跟F1也有所不同,它给出了专门的管脚功能复用寄存器及各个脚可能担当的复用功能之映射表, 不再单纯提管脚的REMAP及AFIO时钟。若想把某些脚做什么用,结合参考手册中GPIOx_AFR.寄存器与数据手册上的复用功能映射表查表配置即可。
下面表格是STM32F207芯片的复用功能表。其中的PA2/PA3可以根据不同复用功能需要做不同的选择。如果作为USART2的TX/RX,就选择AF7,AF7就对应到相应GPIO复用功能寄存器的配置位。这里它用GPIOA的低8位的口线,则在GPIOA_AFRL寄存器里进行配置。将0x0111分别写入AFRL2、AFRL3即可。当然,如果使用STMCU的官方库代码的话,操作也还比较直观。贴图下面的示例代码只是用来辅助说明话题而已。
?
/* Enable GPIO clock */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA , ENABLE);
/* Enable USART clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
/* Connect USART TX/RX pins to AF7 */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_7);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_7);
这里顺便提下,GPIO_PinSource2 与 GPIO_Pin_2在ST官方库代码里定义是不一样的,有时候有人把这两个也搞混而出错。他们的定义如下,一个是侧重表示管脚在端口上的位置,一个侧重表示管脚在端口上的序号。
#define GPIO_Pin_2 ((uint16_t)0x0004) /* Pin 2 selected */
#define GPIO_PinSource2 ((uint8_t)0x02)
小结下,上面提到的问题,当工程师基于ST官方固件库或自行建立工程进行开发的情形下可能会发生的比较多。可喜的是,ST官方有推出一个STM32CUBE的配置工具,该工具在处理STM32 MCU的管脚安排、时钟配置方面非常方便,可以回避很多因为管脚或时钟理解上的误会、视觉上的疏忽而导致的困扰和麻烦,建议尽量使用该工具做辅助开发。
上一篇:关于STM32串口空闲中断的问题
下一篇:stm32f103c8t6掉坑记
推荐阅读最新更新时间:2024-03-16 16:24