STM32系统滴答定时器SysTick实现精确ms和us延时

时间记录:2023/12/11
一、时间的计算
STM32F103C8T6单片机为例,系统时钟为72MHz,则一个时钟周期为(1/72M)秒,即1/72us
二、寄存器介绍
(1)CTRL控制及状态寄存器

位段 名称 描述
16 COUNTFLAG 当计数到0时,该位置为1,当读取该位时,自动清零
2 CLKSOURCE 值为0时选择外部时钟源,值为1时选择内核时钟
1 TICKINT 值为1时,计数到0产生SysTick中断,值为0时,计数到0无动作
0 ENABLE SysTick使能位

(2)LOAD重装载数值寄存器

位段 名称 描述
23:0 RELOAD 当计数到零时,自动加载的计数值

(3)VAL当前数值寄存器

位段 名称 描述
23:0 CURRENT 读取时返回当前倒计数的值,向其中写入值时,自动清零并且会清除CTRL寄存器的COUNTFLAG位

三、配置步骤
3.1 配置时钟源
3.2 计算延时1us和1ms的时钟周期
3.3 装入自动重装载值
3.4 向当前值寄存器写入值
3.5 使能SysTick开始计数
3.6 循环判断是否到达计数值
3.7 清除SysTick使能位停止计数
四、代码展示
头文件(.h文件)

#ifndef __DELAY_H__
#define __DELAY_H__
#include "stm32f10x.h"

static int fac_us=0;
static int fac_ms=0;

//滴答定时器初始化
void vDelayInit(void);
//计时微妙
void vDelayUs(u32 nus);
//计时毫秒
void vDelayMs(u16 nms);

#endif

源文件(.c文件)

#include "delay.h"

void vDelayInit(void)
{
    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);//配置时钟源为外部时钟9MHz,一个时钟周期时间为1/9us
    fac_us=SystemCoreClock/8/1000000;//计算1us的计数周期,9个周期,即9*1/9=1us
    fac_ms=fac_us*1000;//计算1ms的计数周期
}

void vDelayUs(u32 nus)
{
    u32 temp;
    SysTick->LOAD = fac_us*nus;     //自动重装载值寄存器,当计数到0时,将被重装载的值
    SysTick->VAL = 0x00;            //当前值寄存器,返回当前倒计数的值,写它则使之清零
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;          //使能,开始计数
    do{
        temp=SysTick->CTRL;
    }while((temp&0x01)&&!(temp&(1<<16)));   //使能位没有清零,并且COUNTFLAG=0(没有数完)
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;          //失能,停止计数
    SysTick->VAL = 0x00;
}

void vDelayMs(u16 nms)
{
    if(nms>1864){//由于是24位寄存器,最大计数为0xFFFFFF=16777215/9000=1864
        return;
    }
    
    u32 temp;
    SysTick->LOAD = (u32)fac_ms*nms;     //自动重装载值寄存器,当计数到0时,将被重装载的值
    SysTick->VAL = 0x00;            //当前值寄存器,返回当前倒计数的值,写它则使之清零
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;          //使能,开始计数
    do{
        temp=SysTick->CTRL;
    }while((temp&0x01)&&!(temp&(1<<16)));   //使能位没有清零,并且COUNTFLAG=0(没有数完)
    SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;          //失能,停止计数
    SysTick->VAL = 0x00;
}

你可能感兴趣的:(STM32,stm32,单片机,嵌入式硬件)