STM32最小系统板教程第三章第2讲|STM32时钟系统及实现准确延时
置顶公众号,不错过每一讲内容。
完整课程体系(公众号每日更新一讲):
本讲知识点:STM32时钟系统、准确毫秒级、微秒级延时
3.2.1 STM32时钟系统
时钟系统在单片机中的作用就好比人类的心脏于人一样不可或缺。STM32单片机的时钟系统相对51单片机的时钟而言比较复杂,了解过51单片机的人可能有所疑惑,问什么STM32的时钟不像51一样只用一个时钟源而是采用多个时钟源呢?原因就在于STM32的外设资源比起51来说是相当丰富,而不同的外设之间所需要的时钟也是不同的,比如看门狗以及RTC只需几十KHz的时钟即可工作。同时,时钟越快功耗也越大,抗电磁干扰能力也会减弱,因此复杂的MCU通常都是采用多时钟源来解决这些问题。
图3-2-1 STM32时钟系统
乍一眼看着,STM32时钟系统很繁杂,其实它只不过是一张“ 纸老虎 ”。在STM32中,共有五个时钟源,分别为HSE、LSE、HSI、LSI、PLL。图3-1经过笔者分类讲解,相信初学者对STM32的时钟系统会有一个清晰的认识。
① HSE是高速外部时钟,可接外部时钟源,频率范围4-16MHz,本开发板外接8MHz的晶振。
② LSE是低速外部时钟,本开发板外接了32.768KHz的晶振,作为RTC的时钟。
③ HSI是高速内部时钟,内部RC振荡器,提供8MHz的时钟。
④ LSI是低速内部时钟,内部RC振荡器,提供40KHz的时钟,独立看门狗的时钟必须来源于它,同时它也可以给RTC提供时钟。
⑤ PLL是锁相环倍频,它的来源可以是HSI/2、HSE或HSE/2,倍频范围为2-16倍,但是其输出的最大频率不超过72MHz。
A:MCO是STM32的一个时钟输出IO(PA8)引脚,可以给外部其他系统提供时钟源。输出来源可以是PLLCLK/2、HSI、HSE或者SYSCLK(系统时钟)。
B:RTC时钟源选择,可以是HSE/128、LSE或者LSI。
C:这是STM32的系统时钟,它给STM32绝大多数外设提供时钟,SYSCLK来源可以选择PLLCLK倍频输出、HSE、或者HSI,它的最大频率为72MHz。
D: 这是USB的时钟为48MHz,它来自PLL时钟源,可以选择为PLLCLK/1或者PLLCLK/1.5。
E:这部分便是其他所有外设了,从时钟树中可以看出,它们都是源自SYSCLK,然后大部分外设通过AHB预分频器获取时钟,其中部分外设的时钟会由APB1和APB2预分频器来确定。APB1(最大36MHz)上接的是低速外设包含电源接口、CAN、USB、I2C、UART2等。APB2(最大72MHz)上接的是高速外设包含UART1、SPI1、TIM1、ADC1、所有GPIO口等。
至此,STM32的时钟系统就先讲到这里,反复熟悉并经过实际应用相信大家可以掌握它。
3.2.2 SysTick定时器简介
Cortex M3内核内部包含了一个SysTick定时器,它是一个24位的倒计数定时器,当计数为0时,该定时器会从RELOAD寄存器中自动装载初值,开始新的计数。SysTick定时器包含了CTRL、LOAD、VAL、CALIB 4个寄存器,一般不会用到CALIB寄存器,这里笔者只介绍前三个寄存器。
图3-2-2 CTRL寄存器位定义
图3-2-3 LOAD寄存器位定义
图3-2-4 VAL寄存器位定义
3.2.3 利用SysTick实现准确延时
图3-2-5 启动项文件
图3-2-6 系统初始化
图3-2-7 系统时钟宏定义
图3-2-8 系统时钟设置
首先打开本节课程对应的源码,在 startup_stm32f10x_md.s 源文件中,可以找到图3-2-5中128-137行的代码,这段代码指的是系统在上电复位后执行的一段汇编代码,可以看出先执行SystemInit(系统初始化)在执行Main(主函数)。然后打开 system_stm32f10x.c 定位到图3-2-6所示212行代码处,这就是SystemInit函数原形,接着定位到262行代码处,看到SetSysClock(设置系统时钟)函数,再定位到419行处找到SetSysClock函数原形,可以看出该函数根据不同宏定义执行相应的设置系统时钟函数,由图3-2-7宏定义设置可以看出,系统上电复位后主频默认为72MHz。
图3-2-9 延时初始化
打开delay.c源文件,首先定义了两个全局变量 D_us(延时微妙系数)、D_ms(延时毫秒系数),然后看到Delay_Init()函数,函数里第一行代码含义为设置Systick(系统定时器)时钟为系统时钟8分频,之前说过系统时钟上电复位后时钟为72MHz,所以这里Systick时钟为9MHz。也就是说,Systick计数器VAL寄存器里的值每减少1则需要花费1/9 us的时间,函数里第二行代码D_us=72MHz(72000000)/8000000,即D_us=9,这行代码的含义为在72MHz的时钟下,Systick->VAL寄存器的值递减9次即为延时1us,第三行代码为计算延时毫秒系数。
图3-2-10 us延时函数
图3-2-11 ms延时函数
图3-2-10、3-2-11所示即为微秒、毫秒延时函数,我们需要延时多少us就传入多少us的参数,ms延时同理。这里需要注意的是SysTick->LOAD是一个24bit(位)的寄存器,因此它最大可以传入的参数值为224/9即为1864135,也就是最大可以延时1864 ms,当我们需要延时超过1864 ms的时候就需要多次循环调用Delay_ms(uint32_t nms)这个函数。以上就是利用SysTick定时器来实现一个比较准确的延时。
接下来,我们编写一个GPIO翻转的函数,在主函数while里循环执行,高电平的周期为1s。
图3-2-12 GPIO翻转延时测试代码
图3-2-13 示波器实际测量
由图3-2-13可以看出,利用示波器实际测量的PC13管脚翻转频率为1.00 Hz,占空比为50.00 %,周期为997.403 ms,所以这个延时函数还是比较准确的,后续的延时我们都会调用这两个延时函数。
本讲内容就到这里,趁热打铁,大家亲自动手试一试吧
视频课程(点击文末左下角“阅读原文”,可看高清视频):
https://v.qq.com/txp/iframe/player.html?vid=e0736r37ykf&width=500&height=375&auto=0
最小系统板的购买链接(复制到淘宝打开即可):
https://item.taobao.com/item.htm?&id=573256065703
elink32仿真器购买链接(复制到淘宝打开即可):
https://item.taobao.com/item.htm?&id=558334383550
课程系列回顾:
STM32最小系统板教程第三章第1讲|从“点灯”入门STM32
感谢您阅读“电子开发学习”的文章,如果您觉得图文能帮助您学习,欢迎关注我们。请点击右上角按钮,选择“查看公众号”,再点击关注即可。或者可以通过搜索公众号的方式关注: electricstudy 。您可以通过扫码下面的二维码关注我们。如果您想阅读往期文章,可点击“查看历史消息”。
历史好文推荐(点击文章标题可跳转):
小马哥四轴硬件第1讲、 Altium Designer安装与介绍
如何让Arduino IDE支持你手里的STM32 nucleo开发板