由于现在学习的是以寄存器库为基础来实现功能,所以以后的知识点和代码都是以寄存器库来配置的,还有目前现在用的板子是STM32F407VET6,该笔记只是自己的见解和理解,大佬勿喷。
5.1 系统滴答定时器介绍
5.1.1 定时器
定时器 = 计数器
定时器的本质:有规律的计数
有规律:固定时钟频率 ---> 数一个数的速度 0 -> 1 1us
计数 :定时器中会有可控计数器(数数) 设置数去数 1000 --> 0
定时器定时原理:
通过时钟源可知1s计数次数
通过要定时的秒数 * 每秒计数的次数 来决定定时器中的计数器所需要计数的次数
计算出周期 时间(T)
5.1.2 定时器分类
内核级定时器(系统滴答定时器)
延时 定时中断 (给系统提供时钟节拍) 给实时操作系统提供时基(任务调度) FreeRTOS UCOSII 5ms
基本定时器
延时 定时中断 时间片(实现两盏LED灯同时以一个不同速度闪烁,轮询标志位的改变) (M4两个 TIM6 TIM7) 开启DAC转换
通用定时器
延时 定时中断 输出比较(PWM) 输入捕获(捕获高/低电平时间) 红外信号解码(解NEC)、按键时长、超声波测距 逻辑分析仪(IIC SPI) 示波器
高级定时器
延时 定时中断 输出比较 输入捕获 电机死区 刹车
其他定时器
看门狗 --- 产生复位
RTC --- 1s定时期 ---- 实时时钟(RTC显示时间)
5.1.3 系统滴答定时器
系统滴答定时器是CM4核心内部集成的一个简单定时器硬件模块,SysTick(系统滴答定时器)属于NVIC一部分
作用:
①为系统提供时钟节拍 (时基)X
②作为简单的定时器使用 延时 和 定时中断
延时:
CPU一定要等到时间到才会往下执行 while();作阻塞
定时中断: 实时性
时间没有到的时候,CPU执行主程序,时间到了就进入中断服务函数执行紧急事件
5.2 系统滴答定时器框图
M3&M4权威指南手册 第九章 9.5 P349
The SysTick timer is a simple decrement 24-bit timer
系统滴答定时器是一个24bit递减定时器
24bit --->设置数数大小 0 - 16777215
①数数速度
②数多少数
STM32时钟树:
中文参考手册 RCC章节
STM32时钟源:
LSI:低速内部时钟 看门狗、RTC
LSE:低速外部时钟 RTC
HSI:高速内部时钟 系统、PLL锁相环
HSE:高速外部时钟 25Mhz -->168Mhz
PPL(HSE):25Mhz /M分频 * N倍频 / P分频
25Mhz / 25 * 336 / 2 = 168Mhz
参考时钟频率:
参考时钟:168Mhz / 8 = 21Mhz
5.3 系统滴答定时器寄存器
SysTick->CTRL:
位16 :读取标志位,如果读取到1,代表定时器周期完成;如果读取到0,代表定时器周期未结束
①读取CTRL的第16位
位2:选择时钟源 0:参考时钟(168 / 8 = 21Mhz) 1:处理器时钟(168Mhz)
位1: 中断使能位 1:使能中断 0:无中断
位0:定时器使能位 1:使能 0:禁止
重装载寄存器大小为24bit,设置的数值不得超过24bit大小
可设置数值:0 - 16777215
特性:需要计数值递减0时,重装载值才会被加载
读取:获得当前计数的值
写入:让计数值清零(重装载值会被加载)
5.4 系统滴答定时延时效果
5.4.1 系统滴答定时器延时过程
延时时间,定时器周期T如何计算? 定时器频率---> 时钟源(用户决定) 重装载值(设置)
例子1:
时钟源选择参考时钟,频率:21Mhz,定时器周期设置为1ms,重装载值需要写入多少?
T(周期)= ARR(重装载值) / Fck(时钟源频率)
1000us = ARR / 21
ARR = 1000 * 21 = 21000
Void systick_delay_ms(u16 nms)
{
SysTick->LOAD = nms * 21000 - 1 ; // 1001
}
例子2:
时钟源选择处理器时钟,频率:168Mhz,定时器周期设置为2ms,重装载值需要写入多少?
T(周期)= ARR(重装载值) / Fck(时钟源频率)
2000 = ARR / 168
ARR = 336000
5.4.2 毫秒延时函数
systick.c systick.h
void SysTick_Delay_ms(u16 nms)
{
//注意:系统滴答不需要打开时钟
//1、选择时钟源
//2、配置重装载值
//3、向当前值寄存器写入一个值,将重装载值加载到计数器
//4、使能系统滴答定时器 --- 递减计数
//5、等待系统滴答标志位置1 -- 包括读标志位(清标志位)
//6、关闭系统滴答定时器
}
5.4.3 代码设计
systick.c
#include "systick.h"
/*
函数功能:系统滴答毫秒延时
返回值:void
形参:u16 nms
函数说明:
*/
void SysTick_Delay_ms(u16 nms)//注意:798ms
{
//1、选择时钟源 --- 参考时钟21Mhz
SysTick->CTRL &=~ (1 << 2);
//2、设置重装载值 T = ARR / Fck
SysTick->LOAD = nms * 21000 - 1;
//3、往写入当前值寄存器写入一个值
SysTick->VAL = 0;
//4、使能系统滴答定时器
SysTick->CTRL |= 1 << 0;
//5、等待标志位置一
while(!(SysTick->CTRL & 1 << 16));
//6、禁止系统滴答定时器
SysTick->CTRL &=~ (1 << 0);
}
/*
函数功能:系统滴答微秒延时
返回值:void
形参:u16 nus
函数说明:
*/
void SysTick_Delay_us(u16 nus)//注意:798ms
{
//1、选择时钟源 --- 参考时钟21Mhz
SysTick->CTRL &=~ (1 << 2);
//2、设置重装载值 T = ARR / Fck
SysTick->LOAD = nus * 21 - 1 ;
//3、往写入当前值寄存器写入一个值
SysTick->VAL = 0;
//4、使能系统滴答定时器
SysTick->CTRL |= 1 << 0;
//5、等待标志位置一
while(!(SysTick->CTRL & 1 << 16));
//6、禁止系统滴答定时器
SysTick->CTRL &=~ (1 << 0);
}
systick.h
#ifndef _SYSTICK_H
#define _SYSTICK_H
#include "stm32f4xx.h"
void SysTick_Delay_ms(u16 nms);
void SysTick_Delay_us(u16 nus);
#endif
5.5 系统滴答定时器定时中断
5.5.1 定时中断
在所定的时间没到之前,CPU正常做主程序中的事情
时间到CPU进入中断服务函数执行紧急事件 1->0
主程序里面跑1个程序(LED1 500ms闪烁一次)
中断服务函数跑1个程序(LED2 1S闪烁一次)
5.5.2 系统滴答定时器中断程序设计
周期为1ms系统滴答定时器,1ms进入一次中断服务函数实现串口打印字符串printf(“进入系统滴答定时器中断\r\n”);
//1、选择时钟源
//2、使能系统滴答定时器中断
//3、配置重装载值
//4、向当前值寄存器写入一个值,将重装载值加载到计数器
//5、使能系统滴答定时器 --- 递减计数
系统滴答定时器中断服务函数:
CTRL + F : SysTick
5.5.3 代码设计
systick.c
#include "systick.h"
/*
函数功能:系统滴答定时器1ms中断初始化
返回值:void
形参:u16 nms
函数说明:
*/
void SysTick_Interrupt(u16 nms)
{
//1、选择时钟源 21Mhz
SysTick->CTRL &=~ (1 << 2);
//2、使能滴答定时器中断
SysTick->CTRL |= 1 << 1;
//3、设置重装载值 T = ARR / Fck
SysTick->LOAD = nms * 21000 - 1;
//4、往写入当前值寄存器写入一个值
SysTick->VAL = 0;
//5、使能系统滴答定时器
SysTick->CTRL |= 1 << 0;
}
/*
函数功能:系统滴答定时器中断服务函数
返回值:void
形参:void
函数说明:时间到
每1ms都会进入中断服务函数
*/
void SysTick_Handler(void)
{
//清除标志位
SysTick->CTRL &=~ (1 << 16);
printf("进入SysTick中断\r\n");
LED2_TAG;
}
/*
函数功能:系统滴答毫秒延时
返回值:void
形参:u16 nms
函数说明:
*/
void SysTick_Delay_ms(u16 nms)//注意:798ms
{
//1、选择时钟源 --- 参考时钟21Mhz
SysTick->CTRL &=~ (1 << 2);
//2、设置重装载值 T = ARR / Fck
SysTick->LOAD = nms * 21000 - 1;
//3、往写入当前值寄存器写入一个值
SysTick->VAL = 0;
//4、使能系统滴答定时器
SysTick->CTRL |= 1 << 0;
//5、等待标志位置一
while(!(SysTick->CTRL & 1 << 16));
//6、禁止系统滴答定时器
SysTick->CTRL &=~ (1 << 0);
}
/*
函数功能:系统滴答微秒延时
返回值:void
形参:u16 nus
函数说明:
*/
void SysTick_Delay_us(u16 nus)//注意:798ms
{
//1、选择时钟源 --- 参考时钟21Mhz
SysTick->CTRL &=~ (1 << 2);
//2、设置重装载值 T = ARR / Fck
SysTick->LOAD = nus * 21 - 1 ;
//3、往写入当前值寄存器写入一个值
SysTick->VAL = 0;
//4、使能系统滴答定时器
SysTick->CTRL |= 1 << 0;
//5、等待标志位置一
while(!(SysTick->CTRL & 1 << 16));
//6、禁止系统滴答定时器
SysTick->CTRL &=~ (1 << 0);
}
systick.h
#ifndef _SYSTICK_H
#define _SYSTICK_H
#include "stm32f4xx.h"
#include "stdio.h"
#include "led.h"
void SysTick_Interrupt(u16 nms);
void SysTick_Delay_ms(u16 nms);
void SysTick_Delay_us(u16 nus);
#endif
以上就是我对定时器及系统滴答定时器的一点拙见,由于我现在用的板子是STM32F407VET6,所以后面的代码和图片都是基于这块板子的。后面会继续更新相关我的STM32的学习之路。