历史上的今天
今天是:2025年07月29日(星期二)
2019年07月29日 | stm32F40x系统滴答定时器计算方法及应用
2019-07-29 来源:eefocus
系统滴答定时器计算方法,在这记录一下,防止时间久了遗忘
下图是:时钟树的一小部分:在STM32F4xx中文参考手册.pdf文档第107页可以找到。

框架图:

控制状态寄存器: SysTick->CTRL

自动重装载寄存器:SysTick->LOAD

当前值寄存器: SysTick->VAL
校准值寄存器: SysTick->CALIB

上面框架图是来自于:Cortex M3权威指南(中文).pdf 文档第282-315页
1、换算与时钟源选择
外部时钟源: HCLK = 168MHz / 8
内核时钟: HCLK = 168MHz
这里选择了 168MHz / 8 = 21MHz
21MHz = 21000KHz = 21000 000Hz
1us = (21 000 000Hz/s) / 1000 000 = 21次
也就是1us它里面的val会减21次,因为在21MHz频率,1us中有21个脉冲波。但减到0时,会产生一个中断事件。
2、系统滴答定时器是什么?
答:系统滴答定时器(Systick)是一个24bit的定时器,因此它一次最多可以计数2的24次方个时钟脉冲。用于系统中的时钟节拍,可以不断地产生1uS的中断。
①:SysTick->VAL(最大值24位)
存放24位:二进制(1111 1111 1111 1111 1111 1111) <=> 16进制 0xFFFFFF
计数最多为:16777215次
16777215 / 168 = 0.099864375s = 99.864375ms 约等于 100ms
16777215 四舍五入 16800000
168MHz = 168000000
16800000/168000000 = 0.1s = 100ms 这个计时太短(过快)无法满足所需
如果是使用了21MHz来计算的话刚好是168的8倍,所以得出计算结果为:800ms
②:800ms计算过程
同样计算公式: oxffffff / 21000
16777215 / 21 = 798.9ms 这个时间基本满足所有计时时间
也就是最多可以记这么多毫秒: oxffffff / 21000 = 798.9ms
3、系统滴答定时器延时1S的原理
思路:利用systick定时器为递减计数器,设定初值并使能它后,它会对每1个系统时钟周期计数器减1,计数到 0时,SysTick计数器自动重装初值并继续计数,同时触发中断。那么每次计数器减到0,时间经过了:系统时钟周期*计数器初值。我们使用168M作为系统时钟,那么每次计数器减1所用的时间是1/168M,计数器的初值如果是168000,那么每次计数器减到0,时间经过(1/168M)*168000=0.001,即1ms。
答:(简单理解:用168M的时钟频率,即1s计数168M=168000000次,那1ms计数168000次,所以计数值为168000,那1us计数168次,所以计数值为168)。
4、配置流程:
①:系统滴答ms级延时设置
选择时钟源、清空当前计数器的值、设置重载值、使能计数器、等待定时时间到、关闭倒数计数器、计数器清零
②:系统滴答us级延时设置
选择时钟源、清空当前计数器的值、设置重载值、使能计数器、等待定时时间到、关闭倒数计数器、计数器清零
systick.h文件
#ifndef __SYSTICK_H__
#define __SYSTICK_H__
#include void systick_delay_us(u32 nus); void systick_delay_ms(u16 nms); void systick_delay_xms(u32 xms); #endif systick.c文件 #include "sysTick.h" /* 函数功能:系统滴答微秒延时 函数形参:nus 返回值:无 */ void systick_delay_us(u32 nus) { //21MHz = 21000000Hz/s = 21000Hz/ms = 21us if(nus>(0xffffff / 21)) //微秒,只要是大于这个值就不允许延时 { return; } SysTick->CTRL &= ~(0x1<<2);//选择21MHz的时钟源 SysTick->VAL = 0x00; //清空当前计数器的值 SysTick->LOAD = nus * 21; //要记的数 SysTick->CTRL |= 1<<0; //使能倒计数寄存器 /** SysTick->CTRL中的Set bit 16 - count flag **/ while(!(SysTick->CTRL & (0x1<<16)))//等待定时时间达到产生(位16)的标志 { ; } SysTick->CTRL &= ~(1<<0); //关闭倒数计数器 清零 可以不写 SysTick->VAL &= ~(1<<0); //计数器清零 可以不写,寄存器有自动清零功能 } /* 函数功能:系统滴答豪秒延时 函数形参:nms 返回值:无 */ void systick_delay_ms(u16 nms) { //21MHz = 21000000Hz/s = 21000Hz/ms if(nms>(0xffffff / 21000)) //毫秒,只要是大于这个值就不允许延时 { return; } SysTick->CTRL &= ~(0x1<<2); //选择21MHz的时钟源 SysTick->VAL = 0x00; //清空当前计数器的值 SysTick->LOAD = nms * 21000; //要记的数 SysTick->CTRL |= 1<<0; //使能倒计数寄存器 /** SysTick->CTRL中的Set bit 16 - count flag **/ while(!(SysTick->CTRL & (0x1<<16)))//等待定时时间达到产生(位16)的标志 { ; } SysTick->CTRL &= ~(1<<0); //关闭倒数计数器 清零 可以不写 SysTick->VAL &= ~(1<<0); //计数器清零 可以不写,寄存器有自动清零功能 } /* 函数功能:系统滴答 实现任意ms级别的延时 函数形参:nms 返回值: 无 备注: 以500ms的延时为基准延时 */ void systick_delay_xms(u32 xms) { u16 i =0;//延时的倍数循环变量 //计算整数个基准延时 for(i=0; i delay_ms(500); } //如果不是整数倍 有剩余的延时 if(xms%500!=0) //有余数 { delay_ms(xms%500); } } main.c #include "led.c" #include "systick.h" int main(void) { led_init(); while(1) { LED1_ON; systick_delay_ms(500); //延时0.5s LED1_OFF; systick_delay_ms(500); //延时0.5s } }
下一篇:STM32移植Marlin固件
史海拾趣
|
在校准后触摸屏可以正常工作。点击A点,显示上也是A点反应。但重启后点击A点,B点发生反应。针对这种触摸屏发生偏移的现象。我查看了一下四根数据线波形,与数据手册上的波形一致。在校准时我也查看了注册表,校准信息确实写入了注册表中,不知道问 ...… 查看全部问答> |
|
最近在做S3C6410的MFC,2D,3D加速,碰到一个问题 最近在做S3C6410的MFC,2D,3D加速。先是碰到了编译不能通过的问题, 再来大家说是DISPLAY的问题,所以编译通过的问题解决了,接下来的问题 又出现了,睡眠下去的时候正常,但唤醒的时候却发现LCD白屏,如果我放哪里 不管它的话,它 ...… 查看全部问答> |
|
请问pb5.0生成的模拟器可以被网络中的其它PC ping到吗? 模拟器的IP是否只能设为192.168.131.x呢? 如果我想本模拟器可以被外界ping到, 该怎么设置呢? 在此先谢谢大侠关注.… 查看全部问答> |
|
LM3S5B91进入中断之后,中端口持续低电平,这是怎么回事? LM3S5B91进入中断之后,中端口持续低电平,这是怎么回事?进入中段之后,有清除中断,但是,Io口依然保持低电平。 我做的是CH452的键盘扫描,中断方式,复位后,中端口为高电平,按下按键后,变为低电平,但是,在我松开手之后,应 ...… 查看全部问答> |
|
液压支架是煤矿综合机械化采煤工作面的支护设备,也是综采的关键设备。在国家煤矿安全生产形势的迫切需要下,目前越来越多的液压支架生产厂家开始加大电液控制系统的投入力度。 液压支架电液控制系统是具有单片机、传感器等电子装置和液压回路控制 ...… 查看全部问答> |





