1.概念:
系统嘀嗒定时器首先是存在于内核里---》配置时不需要开时钟
SysTick(系统滴答计时器)原理:SysTick本质就是一个定时器。从计数值递减到零时,表示定时的时间到了。
SysTick 定时器是一个简单的递减 24 位定时器,两个时钟来源:处理器时钟频率(168MHZ)或参考时钟频率(168/8 =21MHZ) 。 【基本上选后者】
定时范围:以21MHZ为例,2^24=16777216。 毫秒级计数上限:16777216/21*000=798ms
注:无标准库函数调用==》用寄存器写定时
毫秒延迟与微秒延迟代码如下:
SysTick设计毫秒延时和微秒延时
毫秒延时:
步骤 --------------------
1 选择时钟源—21MHZ
2 填入计数值—LOAD
3 清零计数器—VAL
4使能定时器—CTRL
5判断计数是否结束--CTRL
6关闭定时器—CTRL
/*******************************************************************
* Function : 系统滴答计时器--毫秒延迟
* Parameter : u32 xms--多少毫秒
* Return : void
* Comment :
属于内核--不需要时钟使能
F4的库函数手册里面找不到有关的库函数---》用寄存器操作
1HZ-->1s振动一次 1MHZ--》1秒振动1,000,000次---》微秒定时的时钟频率=1ms/(1ms内振动的次数)》1MHz=>1s振动1,000,000次=》1ms振动1,00次
1s=1HZ;1s=1,000ms;1s=1,000,000us
1MHz = 1,000,000Hz ;21MHZ=21,000,000HZ
选择21M参考时钟AHB经过8分频得到 2^21=1677215,最大计数时间ms = 16777215 / 21 = 798.9ms ==》系统滴答计时器外部时钟计时不得超过798ms!!!
时钟周期与时钟频率互为倒数---时钟周期(s/ms/us),时间频率(HZ,MHZ)=时钟源
1s--1hz
1us--1mhz
时钟周期=记一个数需要多少时间
时钟频率=1s振动多少次
定时时间=单个计数周期*重装载值=====》重转载值【SysTick->LOAD】=xms【定时时间】/单个时钟周期。由于是毫秒级,时钟周期换成毫秒级
=》重转载值【SysTick->LOAD】=xms【定时时间】*时钟源【对应时间单位的时钟源】-1
********************************************************************/
void SysTick_Ms(u32 xms)
{
/*第一步:先选择时钟源(一般选择STCLK -- 21MHZ)-- 因为位2是选择时钟的,0=21HMZ=外部时钟,1=168HMZ=内部时钟,选0故位2写0,用&=~*/
SysTick->CTRL &= ~(1 << 2);
/*第二步: 往重装载寄存器写值ms*21000-1(记多少次)*/
/*计数个数=时间/时间频率=时间*时钟源=ms*21MHZ=ms*21X10^3=ms*21000-1(-1=0=也算个数)*/
SysTick->LOAD =xms*21000 - 1;
/*第三步: 计数器清零,并开始计数*/
SysTick->VAL = 0;
SysTick->CTRL |= (1<<0);
/*第四步:等待计数完成,停止计数,清除计数完成标记*/
while(!(SysTick->CTRL & (1<<16)));//等待条件为假
SysTick->CTRL &=~(1<<0); //SysTick->CTRL的第16位具有读取后自动清零效果
}
/*******************************************************************
* Function : 系统滴答计时器-微秒延迟
* Parameter : u32 us--多少微秒
* Return : void
* Comment :
********************************************************************/
void SysTick_Us(u32 us)
{
/*第一步 【选择时钟】*/
//因为位2是选择时钟的,0=21HMZ=外部时钟,1=168HMZ=内部时钟,选0故位2写0 ,用&=~
SysTick->CTRL &=~(1<<2);
/*第二步 【填入计数值】*/
SysTick->LOAD=us*21-1;
/*第三步 【清零计数器】*/
SysTick->VAL=0;
/*第四步 【使能计时器】*/
//因为位0是计时器使能,1使能,0关闭,位0写1,用|=
SysTick->CTRL|=1<<0;
/*第五步 【判断计数是否结束】*/
//因为位16,倒计时结束时,该位会变成1,所以用while判断真假,若SysTick->CTRL1的16位为1,则&后,
//SysTick->CTRL1除16位外全为0,如果他不是1位0的话SysTick->CTRL&(1<<16)的结果为0(假)
while(!(SysTick->CTRL&(1<<16)));
/*第六步 【关闭定时器】*/
SysTick->CTRL&=~(1<<0);
}