stm32F40x系统滴答定时器计算方法及应用(寄存器版本)

系统滴答定时器计算方法,在这记录一下,防止时间久了遗忘

下图是:时钟树的一小部分:在STM32F4xx中文参考手册.pdf文档第107页可以找到。

stm32F40x系统滴答定时器计算方法及应用(寄存器版本)

框架图:

stm32F40x系统滴答定时器计算方法及应用(寄存器版本)

stm32F40x系统滴答定时器计算方法及应用(寄存器版本)

stm32F40x系统滴答定时器计算方法及应用(寄存器版本)

stm32F40x系统滴答定时器计算方法及应用(寄存器版本)

上面框架图是来自于:Cortex M3与M4权威指南.pdf 文档第313-315页


公式:
1Hz    = 1s               要计1个数用时1s
10Hz   = 0.1s           要计10个数用时1s
100Hz  = 0.01s        要计100个数用时1s
21MHz  ---> 1s        要计21M个数用时1s    21000 000个数
                               100ms           --->          2100 000个数
                                ms级             --->          21 000    

如:
1s    = 21 000 000
100ms = 21 000 00

换算
168MHz = 168000KHz = 168000000Hz

外部时钟 <=> 168M/8=21M
①:
存放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

②:
同样计算公式: oxffffff / 21000    
16777215 / 21 = 798.9ms            这个时间基本满足所有计时时间

    
也就是最多可以记这么多毫秒: oxffffff / 21000 = 798.9ms    


配置流程:
①:系统滴答ms级延时设置
    选择时钟源、清空当前计数器的值、设置重载值、使能计数器、等待定时时间到、关闭倒数计数器、计数器清零

②:系统滴答us级延时设置
    选择时钟源、清空当前计数器的值、设置重载值、使能计数器、等待定时时间到、关闭倒数计数器、计数器清零



systick.h文件

#ifndef  __SYSTICK_H__
#define  __SYSTICK_H__

#include <stm32f4xx.h>

void systick_delay_ms(u16 nms);


#endif

 

systick.c文件

#include "sysTick.h"

/*
函数功能:系统滴答豪秒延时
函数形参: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 = ms * 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);	//计数器清零   可以不写,寄存器有自动清零功能
}

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
    }
}