滴答定时器概述
Systick定时器,是一个简单的定时器,对于CM3,CM4内核芯片,都有Systick定时器。常用来做延时,或者实时系统的心跳时钟。这样可以节省MCU资源,不用浪费一个定时器。比如uCOS中,分时复用,需要一个最小的时间戳,一般在STM32+UCOS系统中,都采用Systick做uCOS心跳时钟。
Systick定时器就是系统滴答定时器,一个24 位的倒计数定时器,计到0 时,将从RELOAD 寄存器中自动重装载定时初值。只要不把它在SysTick 控制及状态寄存器中的使能位清除,就永不停息,即使在睡眠模式下也能工作。
SysTick定时器被捆绑在NVIC中,用于产生SYSTICK异常(异常号:15)。
Systick中断的优先级也可以设置。
一共4个Systick寄存器
CTRL------------->SysTick 控制和状态寄存器
LOAD------------->SysTick 自动重装载除值寄存器
VAL----------------> SysTick 当前值寄存器
CALIB ------------> SysTick 校准值寄存器
对于STM32,外部时钟源是 HCLK(AHB总线时钟)的1/8,内核时钟是 HCLK时钟配置函数:SysTick_CLKSourceConfig();
滴答定时器相关函数
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
这一句把SysTick的时钟选择外部时钟, 这里需要注意的是: SysTick 的时钟源自 HCLK 的 8 分频, 假设我们外部晶振为 8M,然后倍频到 168M,那么SysTick 的时钟即为 21Mhz,也就是 SysTick 的计数器 VAL 每减 1,就代表时间过了1/21us 。
SysTick_CLKSourceConfig(); //Systick时钟源选择 misc.c文件中
SysTick_Config(uint32_t ticks); //初始化systick,时钟为HCLK,并开启中断
//core_cm3.h/core_cm4.h文件中
void SysTick_Handler(void);//Systick中断服务函数
滴答定时器实现延时
#include "stm32f4xx.h"
#include "led.h"
static __IO uint32_t TimingDelay;
void Delay(__IO uint32_t nTime)
{
TimingDelay = nTime;
while(TimingDelay != 0);
}
//每隔1ms进入中断
void SysTick_Handler(void)
{
if (TimingDelay != 0x00)
{
TimingDelay--;
}
}
int main(void)
{
Led_Init();
//配置systick时钟源及中断 SystemCoreClock = 168000 000 1ms产生中断
//初始化systick,时钟为HCLK,并开启中断
if (SysTick_Config(SystemCoreClock / 1000)) //systick时钟为HCLK,中断时间间隔1ms
{
GPIO_ResetBits(GPIOE, GPIO_Pin_14);
while (1)
{
GPIO_ToggleBits(GPIOF, GPIO_Pin_9);
Delay(1000); //延时1S
}
}
return 0;
}
//led初始化见前面几篇博客
封装函数delay.c
#include "delay.h"
u32 my_us = 21; //计21个数,用时1us
u32 my_ms = 21000; //计21000个数,用时1ms
void Delay_Init(void)
{
//systick定时器频率:168/8 = 21MHZ
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
}
//参数u32 nus值范围:0~798915
void delay_us(u32 nus)
{
u32 temp;
//设置重装值
SysTick->LOAD = my_us*nus - 1;
//设置VAL为0
SysTick->VAL = 0x00;
//开定时器
SysTick->CTRL |= (0x01<<0);
do
{
temp = SysTick->CTRL; //temp 第十六为1,则说时计数到0
}while( temp & (0x01<<0) && !(temp & (0x01<<16)) );
//判断定时器是否开启 判断计数是否到0
//关定时器
SysTick->CTRL &= ~(0x01<<0);
}
//参数u32 nms值范围:0~798
void delay_ms(u32 nms)
{
u32 temp;
//设置重装值
SysTick->LOAD = my_ms*nms - 1;
//设置VAL为0
SysTick->VAL = 0x00;
//开定时器
SysTick->CTRL |= (0x01<<0);
do
{
temp = SysTick->CTRL; //temp 第十六为1,则说时计数到0
}while( temp & (0x01<<0) && !(temp & (0x01<<16)) );
//判断定时器是否开启 判断计数是否到0
//关定时器
SysTick->CTRL &= ~(0x01<<0);
}
void delay_s(int n)
{
int i;
for(i=0; i delay_ms(500); delay_ms(500); } }
上一篇:初学stm32-库函数开发步骤及总结
下一篇:初学stm32-通用定时器的使用
推荐阅读最新更新时间:2023-09-22 01:31

![[单片机框架] [app_led] [WS2812x] 利用软<font color='red'>定时</font>器实现WS2812x闪烁和呼吸等灯光模式](http://6.eewimg.cn/news/statics/images/loading.gif)




推荐帖子
- 求基于MSP430F149测频率,通过1602显示
- 做了几天了,都没有进度,帮一下忙吧,谢谢了 求基于MSP430F149测频率,通过1602显示
-
盛开的色拉酱
微控制器 MCU
- 跪求高手单片机小程序
- 串口通信故障诊断思路:计算机作为上位机定时对作为下位机的单片机“点名”,无“应答”就说明串口通信发生故障。具体的方案:在程序运行过程中,计算机定时向单片机发一个控制代码(FEH),单片机接收到该代码后,根据通信协议向计算机回传一个身份识别代码(该身份识别代码可以由程序产生,也可以写入串行EEPROM内)。计算机在一定时间内接收到单片机发送来的识别代码并与驱动程序识别代码比较,如2个身份识别代码相符,计算机驱动程序正常运行。若计算机在一定时间内没有收到识别代码或收到的识别代码与驱动程序识
-
hongyy3
单片机
- 关于LED驱动电源的谐波测试必备
- 杭州远方PF9811,才两千多块钱; 2-50次谐波都能测出来; 按IEC61000-3-2,谐波要测到39次关于LED驱动电源的谐波测试必备
-
czf0408
LED专区
- 运放构成的信号累加电路输入的三种分析法
- 两种加法电路与对应的描述方程。 先对第一种分析,图示第一种比较简单,我们知道运放的Vin-=Vin+。所以第一个电路图上三个电阻的公共节点电势Vin-=0. (V1/R1)+(V2/R2)=(0-Vout)/RF。移项处理后就得到了公式中的第一个:Vout=-(Rf/R1)*V1-(RF/R2)*V2.请从一楼的图上看更清楚。 第二个图难以理解,当年我感觉难以理解,现在懂了,变的很简单了,我这里主要是像我从前一样迷糊的同学讲的,欢迎大家将自己有所悟的基础知识拿来与大家
-
gaoyang9992006
ADI参考电路
- 再问一个问题,我是初学者,别见笑
- 感谢楼主和其他朋友对小弟上一个问题帮助!!有哪位大虾知道自动控制增益的芯片么,我采集的信号动态范围很大,近距离不用放大信号就饱和了,远距离信号又很小淹没在噪声里,现在滤波已经解决,信号饱和却是个问题,如何实现AGC,他对系统的实时响应速度是不是会有影响,我不知道,大虾提供小弟点资料,谢谢了再问一个问题,我是初学者,别见笑
-
fengshu
DSP 与 ARM 处理器
- 华为“网络工程师”培训专用教程
- 华为“网络工程师”培训专用教程 网络工程师必备。。。。。。。。。。。华为“网络工程师”培训专用教程
-
37°男人
Linux与安卓