写作原由:今日接手用stm32f100xx芯片开发的项目,以前用的是stm8s 和stm32f103xx芯片;因为在别人的项目代码的基础上做2次开发,但是发现那个代码main函数中没有对系统时钟的设置的相关函数,一直纳闷,但也没有深究,直至昨日 调试时出现串口收发数据出错,源代码在原项目的板子上串口发送、接收数据正常,同样程序在项目板子上收发的数据不正确, 两块板子芯片一样,串口收发管脚一样,最后发现原来板子外部晶振是8MHZ ,新板子外部晶振是12MHZ; 而在STM32固件库中,默认的外部晶振是8MHZ,由于时钟源不正确,导致波特率不正确,当然收发的数据也不正确了…..我勒个去!都怪自己平时看问题“不求甚解”。
波特率与时钟源关系公式:
IntegerDivider = ((PCLKx) / (16 * (USART_InitStruct->USART_BaudRate))
为了深入思考,我提出了一些疑问,通过解答这些问题更深入的了解时钟;
问题一:对系统时钟的设置的相关函数,在main函数中找不到,那在哪里?还是说根本没有对系统时钟进行配置?
问题二:既然用了外部晶振做系统时钟,那为什么没看到启动外部晶振的操作?
问题三:串口的时钟源是什么?串口时钟源跟系统时钟的关系?
问题四:程序中串口时钟源是怎样实现对波特率的关系的?
现附上我找到上面3个问题答案做的一张框架图:希望博友参考此图理解我后面的内容:
在进入主题之前我们先了解一些必要的基础知识—-stm32系列芯片的种类和型号:
startup_stm32f10x_cl.s 互联型的器件,STM32F105xx,STM32F107xx
startup_stm32f10x_hd.s 大容量的STM32F101xx,STM32F102xx,STM32F103xx
startup_stm32f10x_hd_vl.s 大容量的STM32F100xx
startup_stm32f10x_ld.s 小容量的STM32F101xx,STM32F102xx,STM32F103xx
startup_stm32f10x_ld_vl.s 小容量的STM32F100xx
startup_stm32f10x_md.s 中容量的STM32F101xx,STM32F102xx,STM32F103xx
startup_stm32f10x_md_vl.s 中容量的STM32F100xx (我项目中用的是此款芯片 stm32f100CB)
startup_stm32f10x_xl.s flash在512K到1024K字节的STM32F101xx,STM32F102xx,STM32F103xx
cl:互联型产品,stm32f105/107系列
vl:超值型产品,stm32f100系列
xl:超高密度产品,stm32f101/103系列
ld:低密度产品,FLASH小于64K
md:中等密度产品,FLASH=64 or 128
hd:高密度产品,FLASH大于128
(下图中的startup_stm32f10_ld.s应改为:startup_stm32f10x_md_vl.s)
stm32系列芯片系统时钟详解&&移植
问题一:对系统时钟的设置的相关函数,在main函数中找不到,那在哪里?还是说根本没有对系统时钟进行配置?
解答:高人指点,我看了一下启动文件startup_stm32f10x_md_vl.s,其中有一段汇编:
Reset handler routineReset_Handler PROC EXPORT Reset_Handler [WEAK] IMPORT __main IMPORT systemInit BLX R0 LDR R0, =__main BX R0 ENDP123456789
其中,
IMPORT __main IMPORT SystemInit //IMPORT 声明了需要引用C语言中的main函数、systeminit函数,
LDR R0, = systeminint //把systeminit 函数地址放到r0 寄存器;
BLX R0 //跳到到R0 寄存器中的地址执行;
所以,在跳到main函数执行前,已经在SystemInit 函数中把系统时钟给设置好了;
问题二:既然用了外部晶振做系统时钟,那为什么没看到启动外部晶振的操作?
我们在解答这个问题前,先到SystemInit函数里面做更深入的了解:
我们进入setsysclock()函数,看其中作了哪些操作:
我项目中用的是此款芯片 stm32f100CB,内部晶振是24MHZ, 所以应进入执行SetSysClockTo24() 函数:
解析:
void SetSysClockTo24函数中主要做了下面几件事:(不同颜色功能分别对应上面对应颜色代码部分)
1.启动外部晶振作为系统时钟源;
2.等待外部晶振起振;
3.(起振后)对系统时钟源进行分频:(默认外部是HSE–8MHZ晶振) PLL configuration: = (HSE / 2) * 6 = 24 MHz
配置HCLK、PCLK1、PCLK2 与系统时钟源的关系;
问题三:串口的时钟源是什么?串口时钟源跟系统时钟的关系?
回答这个问题前,我们先来看stm32f100芯片手册数据图(第12页):
stm32系列芯片系统时钟详解&&移植
从图里面我们可看出串口1的时钟源是PCLK1;
上面问题2的代码中我们看到PCLK1是时钟源24MHZ的1分频,即还是24MHZ;
问题四:程序中串口时钟源是怎样实现对波特率的关系的?
由问题3我们知道串口时钟源是24mhz,依据公式:IntegerDivider = ((PCLKx) / (16 * (USART_InitStruct->USART_BaudRate)))
库中自动设置IntegerDivider 存入寄存器中;
上一篇:STM32 串行通信 USART 程序例举
下一篇:stm32时钟初始化分析
推荐阅读最新更新时间:2024-03-16 16:20
设计资源 培训 开发板 精华推荐
- 4小时实战+剖析:TI工程师教你快速上手 各种无线产品开发 (限量$14售CC1352R1无线开发板,助你参与动手实验)
- 【EEWORLD第三十四届】2012年01月社区明星人物揭晓!
- 【EE团】铁电MSP-EXP430FR5739低价来袭,让你的夏日清凉到底!
- 【新年乐分享】EEWORLD优秀主题/回复第18期来啦~~
- 高性能手机设计如何实现?手机高校评估研讨会为您揭晓答案!
- MSP430 多款开发工具优惠促销,总有一款会适合你!
- 独家拆解 | 语音控制在真无线立体声TWS耳机上的创新应用
- 10秒钟调查!TI 产品封装你来左右!!!
- 是德科技电子书 《X-Apps藏宝图: 能够加速测试的信号分析仪必备测量App》下载有好礼!
- Mouser 新用户大礼包:你购物,我5折返E金币!