SysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号:15)。在以前,大多操作系统需要一个硬件定时器来产生操作系统需要的滴答中断,作为整个系统的时基。例如,为多个任务许以不同数目的时间片,确保没有一个任务能霸占系统;或者把每个定时器周期 的某个时间范围赐予特定的任务等,还有操作系统提供的各种定时功能,都与这个滴答定时器有关。因此,需要一个定时器来产生周期性的中断,而且最好还让用户程序不能随意访问它的寄存器,以维持操作系统“心跳”的节律。
SysTick定时器除了能服务于操作系统之外,还能用于其它目的:如作为一个闹铃,用于测量时间等。本文用SysTick滴答定时器定时1s。
逻辑:
1.配置滴答定时器时钟源,初始化微秒/毫秒数值。
2.相关寄存器配置:设置当前数值初始值、重装数值、控制状态(使能、读取计数标志位)等。
程序仅使用到这三个SysTick定时器的寄存器。
单片机里面,频率就是晶振的震动次数,72MHz代表1s震动72*10^6次,此时1us震动72次。系统时钟8分频下1us的频率:f=SystemCoreClock/8/1000000=9,计数值就是以频率为基础。(用于重装载数值计算)
SysTick.c(先配置滴答定时器时钟源,对于定时器即开即关)
#include "systick.h"
static u8 fac_us=0;
static u16 fac_ms=0;
void SysTick_Init(void)
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);//AHB时钟除以8作为系统时钟源
fac_us = SystemCoreClock/8000000;
fac_ms = (u16)fac_us*1000;
}
void delay_us(u32 nus)
{
u32 temp;
SysTick->LOAD = (u32)nus*fac_us; //被重装载的值(重装数值寄存器)
SysTick->VAL = 0x00; //当前数值清0(当前数值寄存器)
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk ; //使能滴答定时器(控制及状态寄存器第0位)
do{
temp = SysTick->CTRL ;
//读取寄存器,作用是获取控制及状态寄存器的值
//SysTick已经倒数到了0,则COUNTFLAG位(控制及状态寄存器第16位)置1。
//SysTick未数到0,则COUNTFLAG位为0。
}while((temp&0x01)&&!(temp&(1<<16)));
//产生异常请求(控制及状态寄存器第0位)且SysTick未数到0(COUNTFLAG位为0)
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; //失能滴答定时器
SysTick->VAL =0x00; //当前值清0
}
void delay_ms(u16 nms) //原理与上类似
{
u32 temp;
SysTick->LOAD = (u32)nms*fac_ms;
SysTick->VAL = 0x00;
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk ;
do{
temp = SysTick->CTRL ;
}while((temp&0x01)&&!(temp&(1<<16)));
SysTick ->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
SysTick ->VAL = 0x00;
}
SysTick.h
#ifndef __SYSTICK_H
#define __SYSTICK_H
#include "stm32f10x.h"
void SysTick_Init(void);
void delay_us(u32 nus);
void delay_ms(u16 nms);
#endif
led.h(开启相关时钟,初始化端口)
#include "led.h"
void LED_Init(void){
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); //开启相关时钟
GPIO_InitTypeDef GPIO_InitIntructrue;
GPIO_InitIntructrue.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitIntructrue.GPIO_Pin = GPIO_Pin_13;
GPIO_InitIntructrue.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC,&GPIO_InitIntructrue); //初始化端口
}
void LED_ON(void){
GPIO_SetBits(GPIOC,GPIO_Pin_13);
}
void LED_OFF(void){
GPIO_ResetBits(GPIOC,GPIO_Pin_13);
}
led.h
#ifndef __LED_H
#define __LED_H
#include "stm32f10x.h"
void LED_Init(void);
void LED_ON(void);
void LED_OFF(void);
#endif
main.c
#include "stm32f10x.h"
#include "systick.h"
#include "led.h"
int main(void)
{
SysTick_Init();
LED_Init();
while(1){
delay_ms(1000);
LED_ON();
delay_ms(1000);
LED_OFF();
}
}
一个入门级的小程序,记录一下。