EXTI.c部分
#include "ext.h"
#define SYSTICK_E 9
/**
* @brief 用于SysTick初始化
* @param None
* @retval None
*/
void TICK_Init(void)
{
//1.设置SysTick的时钟频率
SysTick->CTRL&=~(1<<2); //选择当前时钟为AHB/8,在72MHz情况下,SysTick就是9MHz
}
/**
* @brief ms级别延迟,最大值在达到1864的情况下,会出现时间不精确
* @param u32 count:ms级别延迟时间数
* @retval None
*/
void sleep_ms(u32 count)
{
if(count<=0)return;
u8 n=count/1000;
u16 last=count%1000;
if(n>=1){
//循环n次1000ms
u8 i=0;
for(i=0;i<n;i++){
sleep_us(1000*1000);
}
}
if(last!=0){
//在等待最后剩余的时间
sleep_us(last*1000);
}
}
/**
* @brief us级别延迟
* @param u32 count:us级别延迟时间数
* @retval None
*/
void sleep_us(u32 count)
{
if(count<=0)return;
//1.先设置LOAD寄存器
SysTick->LOAD=SYSTICK_E*count;
//2.清零
SysTick->VAL=0;
//3.使能(开启SysTick)
SysTick->CTRL=0x01;
while(!(SysTick->CTRL&0x10000));
//关闭SysTick
SysTick->CTRL&=~(1<<0);
}
EXTI.h部分
void TICK_Init(void); //用于SysTick初始化
void sleep_ms(u32 count); //ms级别延迟
void sleep_us(u32 count); //us级别延迟
滴答定时器初始化部分
//1.设置SysTick的时钟频率
SysTick->CTRL&=~(1<<2); //选择当前时钟为AHB/8,在72MHz情况下,SysTick就是9MHz
//
//由上图可以得知滴答定时器为24位,自动装载值也是24位,并且计数器计数的方式是从当前给定的load装载值一直减少到0。
//有上一篇文章我们得知,HCLK为72MHz,那么systick就是9MHz。
//
//
//由上图我们可以得知,设置CLKSOURCE为0,则代表当前时钟频率是9MHz。
//所以左移两位,并且取反。
滴答定时器延时us部分
if(count<=0)return;
//这里就是为了防止输入该函数的参数是0,那么如果不加这个操作的话,这个函数毫无意义,最终返回。
//1.先设置LOAD寄存器
SysTick->LOAD=SYSTICK_E*count;
//在上main我们已经得知,该时钟频率为9MHz,那么就相当于为1/9us,也就是每滴答一次就是1/9us,但是我们想要延时1us,是以1us为基准单位的,那么这里就需要我们人为扩大9倍。
//2.清零
SysTick->VAL=0;
//这里就是在赋值的时候先清零,以防止之前寄存器里面有值。
//3.使能(开启SysTick)
SysTick->CTRL=0x01;
while(!(SysTick->CTRL&0x10000));
//关闭SysTick
SysTick->CTRL&=~(1<<0);
////当第0位为0时,不使能滴答定时器,反之当第0位为1时,则使能滴答定时器。并且再次清零。
////同时由上图得知,当装载值减少到0时,则该位返回1。
//那么我们就需要通过判断该位是否为1来得知延时是否完成。
//由于COUNTFLAG为第17位。
//
//最后关闭使能,取反即可。
滴答定时器延时ms部分
if(count<=0)return;
//同样的道理,不再赘述。
u8 n=count/1000;
u16 last=count%1000;
if(n>=1){
//循环n次1000ms
u8 i=0;
for(i=0;i<n;i++){
sleep_us(1000*1000);
}
}
//正常来说该装载值寄存器是24位的,那么通过计算器可知为16777216。这时是以秒为单位的那么折算成ms,则需要除以1000。然后再除以9,得到如下所示。
//
//相当于最终算出来ms函数的输入参数最大是1864,不能超过1864。那么我们如果输入的参数大于1864呢?那我们该怎么办?
//所以我们为了解决这个问题,这时需要知道此时输入的参数里面到底有多少个1000,也就是有多少个1s。
//
//如上图所示,我们通过除运算,得知有多少个1000ms,通过%运算,得知还剩多少ms。
//如果n>=1代表肯定比1000多,那么就需要先循环延时n次1000ms。
if(last!=0){
//在等待最后剩余的时间
sleep_us(last*1000);
}
//如果最终执行完n次1000ms之后还有剩余一部分时间(ms)(小于1000ms),那么就在执行last ms即可。这就完美解决问题了!!!滴答定时器如此简单!!!
如果觉得这篇文章还不错的话,记得点赞 ,支持下!!!
以后我会继续推出关于嵌入式(stm32)的协议方面的讲解,下一讲会推出DMA部分的文章!敬请期待!!!
**我先休息去了~~╭(╯^╰)╮