stm32内核里面有一个很棒的定时器,可以在不占用CPU资源呢的前提下,完成定时的功能。从51单片机过来的时候,使用延时的办法就是CPU一直进行空语句的执行,即for(i=100;i>0;i--)。这样进行延时的办法,在初学阶段是比较好用的,但是深入学习到UCOSII/III这种操作系统之后,这种简单的延时,就只会占用CPU。让该运转的指令得不到及时的执行。(定时器也可以解决这个问题,但是CortexM3/M4内核里面有这个玩意,自然要用上)为了解决这种问题,SysTick定时器应运而生。
SysTick定时器的内容在《Cortex M3与M4权威指南》里面才被提到,而《STM32F4xx英文参考手册》里面却没有。作者也是看《Cortex M3与M4权威指南》学习的。只需要掌握关于 SysTick里面的3个寄存器,即可随心所欲的使用延时功能啦。
我先将这几个定时器贴出来:
- SysTick->CTRL : SysTick Control and Status Register(systick控制与状态寄存器)
- SysTick->LOAD SysTick Reload Value Register (systick 重装装载值寄存器)
- SysTick->VAL SysTick Current Value Register(systick当前值寄存器)
(51过来的同学,systick定时器和51的定时0差不多的理解 (The counter inside the SysTick is a 24-bit decrement counter)SysTick内部的计数器是一个24位递减计数器 。只需要将SysTick从一数到零需要多少时间弄明白即可。
systick定时器初始化
- static u8 time_us=0; //用来存储定时1us需要计数个数
- static u16 time_ms=0; //用来存储定时1ms需要计数个数
-
- void systick_init(void)
- {
- SysTick->CTRL &=~(1<<2); // 8分频 选择将系统时钟进行8分频 168M/8 = 21M 这个意思就是systick定时器从1->0数一下需要1/21us
- time_us=21; //168/8 延时1us需要计数21次
- time_ms=(u16)time_us*1000; // 延时1ms需要计数21*1000次
- }
复制代码 举个例子,如果我们想要延时100us 那么 以systick_init(); 进行初始化 我们只需要将计数次数计算出来 count = time_us * 100us 再将count装载进如systick->load 寄存器里面就可以,然后开启定时器 ,判断是否从count数到0,如果没有,继续检测,反之,则退出,并关闭定时器。即可以完成定时的功能。(不需要systick定时中断)
延时1us代码
延时1ms代码
- /*
- u16 t_ms 最大为65535
- 65535 * 2100 = 1376235000 >> 16777216超出24位寄存器的值
- 在不超出 24位寄存器的前提下 t_ms最大为 16777216/2100 = 798.9150476
- 也就是最大延时 798.9150476ms
- */
- void systick_delay_ms(u16 t_ms)
- {
- u8 res = 0;
- SysTick->LOAD = t_ms * time_ms; //SysTick->LOAD 24位的寄存器 最大值是16777216
- SysTick->CTRL |= 1<<0; //打开滴答定时器
- SysTick->VAL = 0;
- do { res = (u8)(SysTick->CTRL>>16); }while(!(res&1)); //判断延时是否结束的标志
- SysTick->CTRL &= ~(1<<0); //关闭滴答定时器
- }
复制代码
systick_delay_ms这个函数最大只能延时798.9150476ms,如果我们想要延时更多的时间,我们怎么办? 最通俗的办法就是systick_delay_ms(500);systick_delay_ms(500);这样即可。请看代码
- /*获取更多延时
- 思想就是:重复几次 systick_delay_ms这个函数(最大延时 798.9150476ms)
- 获取更多延时*/
- void delay_100ms(u8 t_100ms)
- {
- u8 res = 0;
- while(t_100ms--)
- {
- SysTick->LOAD = time_ms * 100; //100ms需要的节拍数
- SysTick->CTRL |= 1<<0; //打开滴答定时器
- SysTick->VAL = 0;
- do { res = (u8)(SysTick->CTRL>>16); }while(!(res&1)); //判断延时是否结束的标志
- }
- }
复制代码 void delay_100ms(u8 t_100ms) 这个函数还是有问题的,就是我们想要延时更长时间,同时也想要把这个函数延时时间降到100ms以内,这样的话,那么这个函数就做不到啦,于是继续改呗,怎么才能延时更长的时间,而减小间隔呢?
- void delay_ms(u16 t_ms)
- {
- u8 t_l = t_ms%255;
- u8 t_h = t_ms/255;
- while (t_h--)
- {
- systick_delay_ms(255);
- }
- if(t_l) systick_delay_ms(t_l);
- }
复制代码 关于systick定时器的学习,就到这里啦。我自己本身还是有很多不足的,其实关于STM32F4的时钟频率是需要配置的,才能为168M。如果没有将这些宏定义改为下面的,时钟频率不为168Mhz,就达不到你想要的延时时间了。
system_stm32f4xx.c 文件 宏定义PLL_M 改为8 即: #define PLL_M 8 uint32_t SystemCoreClock = 168000000;
stm32f4xx.c 文件 即: #define HSE_VALUE ((uint32_t)8000000)
学无止境,继续努力
代码工程奉上!
全部资料51hei下载地址:
STM32F407 systick 定时器延时.zip
(454.94 KB, 下载次数: 32)
|