当前位置:   article > 正文

STM32第十一节(中级篇):SysTick——功能框图讲解和系统配置以及实验函数的编写

STM32第十一节(中级篇):SysTick——功能框图讲解和系统配置以及实验函数的编写

目录

前言

STM32第十一节(中级篇):SysTick(第一节)——功能框图讲解和系统配置

SysTick功能框图讲解

CTRL控制及状态寄存器

重装载数值寄存器

当前数值寄存器

SysTick定时时间计算

SysTick库函数分析

SysTick中断优先级

编写程序

微秒级,毫秒级延时函数

初始化SysTick

main函数

小结


前言

        从这节课开始我们学习有关SysTick系统定时器,主要讲解功能框图以及定时实验讲解。


STM32第十一节(中级篇):SysTick(第一节)——功能框图讲解和系统配置


SysTick功能框图讲解

        SysTick:系统定时器,24位,只能递减,存在于内核,嵌套在NVIC中,所有的Cortex-M内核的单片机都具有这个定时器。

        counter在时钟的驱动下,从reload初值开始往下递减计数到0,产生中断和置位COUNTFLAG标志。然后又从reload值开始重新递减计数,如此循环。那么这样的话,我们在计数结束后使能中断,那么就会执行中断服务程序,置位COUNTFLAG。

        最常用的三个寄存器如上表所示,接下来介绍一下他们分别的功能。

CTRL控制及状态寄存器

        CTRL控制及状态寄存器只有四位有效,第16位为COUNTFLAG,就是说在计数完成后,该位会置为1,那么我们就需要使用软件进行清零,就需要我们读取这个位,就会清零。第2位为CLKSOURCE位,若配置为1,即为AHB时钟,72MHz;若改为0,则为9MHz。 第1位为TICKINT位,我们可以通过该位是否置1去判断我们的程序是否进入中断。 第0位也不多说就是使能位。

重装载数值寄存器

        该寄存器决定了reload的值,帮我写作文一个这样的话再不就是到倒数计数置0时将被重装载的值。(24位有效)

当前数值寄存器

        该寄存器可以读取时返回当前倒计数的值。

SysTick定时时间计算

        t=reload*(1/clk)

        CIk=72M 时, t=(72)*(1/ 72 M) = 1US

        Clk=72M时 , t=(72000)*(1/72 M) = 1MS

        时间单位换算:

        1s= 1000ms=1000 000us=1000000 000ns

SysTick库函数分析

  1. /**
  2. * @brief Initialize and start the SysTick counter and its interrupt.
  3. *
  4. * @param ticks number of ticks between two interrupts
  5. * @return 1 = failed, 0 = successful
  6. *
  7. * Initialise the system tick timer and its interrupt and start the
  8. * system tick timer / counter in free running mode to generate
  9. * periodical interrupts.
  10. */
  11. static __INLINE uint32_t SysTick_Config(uint32_t ticks)
  12. {
  13. if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */
  14. SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; /* set reload register */
  15. NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Cortex-M0 System Interrupts */
  16. SysTick->VAL = 0; /* Load the SysTick Counter Value */
  17. SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
  18. SysTick_CTRL_TICKINT_Msk |
  19. SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
  20. return (0); /* Function successful */
  21. }
  22. #endif

        我们在core.cm3.c文件中大概1700行的代码中找到上述代码,我们可以看到,我们传入的值为 int 类型的 ticks 参数,首先判断ticks 的值是否大于2^24,若大于该值,程序返回1,若小于该值,程序开始中断前的配置。接下来初始化reload 寄存器的值,将该值写入到LOAD中,然后就是配置中断优先级。

SysTick中断优先级

        我们这里用到了NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1);函数来配置中断优先级,配置为15,默认为最低的优先级。

        STM32里面无论是内核还是外设都是使用4个二进制位来表示中断优先级。

        中断优先级的分组对内核和外设同样适用。当比较的时候,只需要把内核外设的中断优先级的四个位按照外设的中断优先级来分组来解析即可,即人为的分出抢占优先级和子优先级。

编写程序

微秒级,毫秒级延时函数

        我们现在先编写两个函数,使得实现微妙和毫秒级延时。我们先宏定义SystemCoreClock为72000000,然后进入一个for循环,计次减一,直到减到0,每次循环都判断SysTick->CTRL是否为1。那么我们就&一下1左移16位的值。若整体非1,即跳出循环。然后就是关闭SysTick定时器
SysTick->CTRL &=~ SysTick_CTRL_ENABLE_Msk;函数。另一个与上面相同编程。

  1. // couter 减1的时间 等于 1/systick_clk
  2. // 当counter 从 reload 的值减小到0的时候,为一个循环,如果开启了中断则执行中断服务程序,
  3. // 同时 CTRL 的 countflag 位会置1
  4. // 这一个循环的时间为 reload * (1/systick_clk)
  5. void SysTick_Delay_Us( __IO uint32_t us)
  6. {
  7. uint32_t i;
  8. SysTick_Config(SystemCoreClock/1000000);
  9. for(i=0;i<us;i++)
  10. {
  11. // 当计数器的值减小到0的时候,CRTL寄存器的位16会置1
  12. while( !((SysTick->CTRL)&(1<<16)) );
  13. }
  14. // 关闭SysTick定时器
  15. SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk;
  16. }
  17. void SysTick_Delay_Ms( __IO uint32_t ms)
  18. {
  19. uint32_t i;
  20. SysTick_Config(SystemCoreClock/1000);
  21. for(i=0;i<ms;i++)
  22. {
  23. // 当计数器的值减小到0的时候,CRTL寄存器的位16会置1
  24. // 当置1时,读取该位会清0
  25. while( !((SysTick->CTRL)&(1<<16)) );
  26. }
  27. // 关闭SysTick定时器
  28. SysTick->CTRL &=~ SysTick_CTRL_ENABLE_Msk;
  29. }

初始化SysTick

  1. /**
  2. * @brief 启动系统滴答定时器 SysTick
  3. * @param 无
  4. * @retval 无
  5. */
  6. void SysTick_Init(void)
  7. {
  8. /* SystemFrequency / 1000 1ms中断一次
  9. * SystemFrequency / 100000 10us中断一次
  10. * SystemFrequency / 1000000 1us中断一次
  11. */
  12. // if (SysTick_Config(SystemFrequency / 100000)) // ST3.0.0库版本
  13. if (SysTick_Config(SystemCoreClock / 100000)) // ST3.5.0库版本
  14. {
  15. /* Capture error */
  16. while (1);
  17. }
  18. }

main函数

  1. #include "stm32f10x.h"
  2. #include "bsp_SysTick.h"
  3. #include "bsp_led.h"
  4. /*
  5. * t : 定时时间
  6. * Ticks : 多少个时钟周期产生一次中断
  7. * f : 时钟频率 72000000
  8. * t = Ticks * 1/f = (72000000/100000) * (1/72000000) = 10us
  9. */
  10. /**
  11. * @brief 主函数
  12. * @param 无
  13. * @retval 无
  14. */
  15. int main(void)
  16. {
  17. /* LED 端口初始化 */
  18. LED_GPIO_Config();
  19. /* 配置SysTick 为10us中断一次 */
  20. SysTick_Init();
  21. // for(;;)
  22. // {
  23. // LED1( ON );
  24. // Delay_us(100000); // 100000 * 10us = 1000ms
  25. // //Delay_ms(100);
  26. // LED1( OFF );
  27. //
  28. // LED2( ON );
  29. // Delay_us(100000); // 100000 * 10us = 1000ms
  30. // //Delay_ms(100);
  31. // LED2( OFF );
  32. //
  33. // LED3( ON );
  34. // Delay_us(100000); // 100000 * 10us = 1000ms
  35. // //Delay_ms(100);
  36. // LED3( OFF );
  37. // }
  38. for(;;)
  39. {
  40. LED1( ON );
  41. SysTick_Delay_Ms( 1000 );
  42. LED1( OFF );
  43. LED2( ON );
  44. SysTick_Delay_Ms( 1000 );
  45. LED2( OFF );
  46. LED3( ON );
  47. SysTick_Delay_Ms( 1000 );
  48. LED3( OFF );
  49. }
  50. }

小结

        我们这节就到这里啦,代码部分实现了LED三个灯的流水亮灭。我们下节开始就要学习关于串口的内容了。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/462418
推荐阅读
相关标签
  

闽ICP备14008679号