一、环境
1.STM32F302CB的单片机,串口使用默认接口PA9/10;
2.工程从F103C8移植而来;
2.std驱动库
二、情况描述
1.最开始配置为验证正常的BOOT + 新移植的rtt APP
2.现象为串口输出乱码;
3.验证旧APP串口功能正常,对比新旧APP串口初始化无明显差异;
三、排查故障
1.去掉rtt相关初始化代码,只跑串口初始化和打印:现象无明显变化,乱码
2.去掉BOOT,将APP中断向量表便宜改为0:无变化,懵逼;
3.调试,检查GPIO寄存器,AF功能寄存器配置:无明显异常,继续懵逼;
4.调试,检查RCC寄存器,配置参数无明显异常,懵逼二式;
5.调试,检查USART1寄存器,配置参数无明显异常,波特率寄存器计算方式一眼没看懂准备上简单粗暴的办法;
6.上绝招,旧代码跑一遍,查看GPIO,USART,RCC寄存器各主要参数,其他基本都粗略记得参数,唯独波特率平时都直接给没关系细节,遂记录之;
7.新代码跑一遍,八九不离十直接看USART波特率寄存器,啪,此贴终结。。。
数分钟休息时间过去。。。
四、寻找原因
1.确认初始化参数无误,直接看串口初始化库函数:
void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct)
{
...
if (USARTx == USART1)
{
apbclock = RCC_ClocksStatus.USART1CLK_Frequency;
}
...
divider = (uint32_t)((2 * apbclock) / (USART_InitStruct->USART_BaudRate));
tmpreg = (uint32_t)((2 * apbclock) % (USART_InitStruct->USART_BaudRate));
...
}
2.忽略其他参数,变量就一个:“RCC_ClocksStatus.USART1CLK_Frequency”,追溯到源头函数中有这样一段:
void RCC_GetClocksFreq(RCC_ClocksTypeDef* RCC_Clocks)
{
/* USART1CLK clock frequency */
if((RCC->CFGR3 & RCC_CFGR3_USART1SW) == 0x0)
{
#if defined(STM32F303x8) || defined(STM32F334x8) || defined(STM32F301x8) || defined(STM32F302x8)
/* USART1 Clock is PCLK1 instead of PCLK2 (limitation described in the
STM32F302/01/34 x4/x6/x8 respective erratasheets) */
RCC_Clocks->USART1CLK_Frequency = RCC_Clocks->PCLK1_Frequency;
#else
/* USART Clock is PCLK2 */
RCC_Clocks->USART1CLK_Frequency = RCC_Clocks->PCLK2_Frequency;
#endif
}
}
WTF,问题就在这里,新建工程时还专门纠结过这个问题,std标准库中,没有F302xB这个型号的启动文件,有F302x8和F303xB的都有,唯独没有这个F302xB;本着“就近原则”,当然是选择“同系列”的F302x8,因此keil魔术棒工程设置汇总的全局宏定义为“STM32F302x8”,而实际上STM32F302C8/CB并不只是FLASH和ROM大小上的差异,这,这谁想得到啊。。。
五、总结
1.在库源码中继续以“STM32F302x8”为关键字搜索,发现部分定时器还有差异,F302/3x8等系列的部分定时器时钟最高能到144M(MCU 主时钟最高为72M),看来是因为这里将USART的时钟源从PCLK2调整到1去了。
2.上ST官网下载“Device Errata”和“Device Limitations”文档,确认与代码中描述一致;
3.检查官网F3的STD库,已经是2015年更新了,看来F3的STD库差不多已经是弃疗状态了;
4.祭出STM32CubeMx,新建F302CB工程,得到F302xC的启动文件,这里也应征了F302xB和xC一样是256kB的Flash;
5.搜索STD库中关于MCU信号的宏定义,确定STD所需的全局MCU型号宏定义:
#if !defined (STM32F303xC) && !defined (STM32F334x8) && !defined (STM32F302x8) && !defined (STM32F303xE)
/* #define STM32F303xC */ /*!< STM32F303CB, STM32F303CC, STM32F303RB, STM32F303RC, STM32F303VB, STM32F303VC
STM32F302CB, STM32F302CC, STM32F302RC, STM32F302RB, STM32F302VC, STM32F302VB,
STM32F358CC, STM32F358RC and STM32F358VC Devices */
/* #define STM32F334x8 */ /*!< STM32F334C4, STM32F334K4, STM32F334C6, STM32F334R6, STM32F334K6, STM32F334C8, STM32F334R8, STM32F334K8,
STM32F303K8, STM32F303K6, STM32F303C8, STM32F303C6, STM32F303R8, STM32F303R6 and STM32F328C8 Devices */
/* #define STM32F302x8 */ /*!< STM32F302K6, STM32F302K8, STM32F302C6, STM32F302C8, STM32F302R6, STM32F302R8,
STM32F301K8, STM32F301C8, STM32F301R8, STM32F301K6, STM32F301C6, STM32F301R6, STM32F313K8 and STM32F318C8 Devices */
/* #define STM32F303xE */ /*!< STM32F303CE, STM32F303CD, STM32F303RE, STM32F303RD, STM32F303VE, STM32F303VD, STM32F303ZE,
STM32F303ZD, STM32F302CE, STM32F302CD, STM32F302RE, STM32F302RD, STM32F302VE, STM32F302ZE,
STM32F302ZD and STM32F398VE Devices */
#endif /* STM32F303xC || STM32F334x8 || STM32F302x8 || STM32F303xE */
STM32F303xC,取值走人;
咳咳...收拾改得一团糟的代码,吃个饭回来继续码...