1.定时器简介
1.1 定时器
STM32F1有8个定时器。其中,2个基本定时器(TIM6、TIM7)、4个通用定时器(TIM2-TIM5)、2个高级定时器(TIM1、TIM8)。定时器性能:高级 > 通用 > 基本。
1.2 通用定时器
(1)主要功能:
16位向上、向下、向上/向下自动装载计数器(TIMx_CNT)
16位可编程(可以实时修改)预分频器,计数器时钟频率的分频系数为1~65536之间的任意数值
4个独立通道(TIMx_CH1~4):
输入捕获
输出比较
PWM生成(边缘或中间对齐模式)
单脉冲模式输出
使用外部信号(TIMx_ETR)控制定时器,且可实现多个定时器互连(可以用一个定时器控制另外一个定时器)的同步电路
发送如下事件发生时产生中断/DMA:
更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)
触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
输入捕获
输出比较
支持针对定位的增量(正交)编码器和霍尔传感器电路
触发输入作为外部时钟或者按周期的电流管理
(2)结构框图:
(3)主要功能模块描述:
p1:时钟部分。
内部时钟(通过APB1总线倍频(2倍频)而来,即CK_INT=72MHz)。
外部时钟1:TIx
外部时钟2:ETR
内部触发输入:ITRx
p2:控制器部分。
p3:时基单元。都是16位:
预分频器(TIMx_PSC,分频系数1~65536)-CK_CNT->
计数器(TIMx_CNT)<--
自动重装载寄存器(TIMx_ARR)
计数器模式:向上计数、向下计数、中央对齐(向上/向下计数)
p4:输入捕获。测量输入信号的脉宽、测量PWM输入信号的频率和占空比。
p5:输出比较。有效电平、无效电平、翻转、强置为有效电平、强置为无效电平、PWM1、PWM2。
2.通用定时器配置
2.1 配置步骤
添加定时器的源文件和头文件及其路径;
(1)使能定时器时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
(2)初始化定时器参数,包含自动重装值,分频系数,计数方式等
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, //定时器选择:确定哪一个定时器
TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct //结构体指针变量,对结构体成员进行配置,初始化定时器
);
typedef struct{
uint16_t TIM_Prescaler; //预分频器n-1
uint16_t TIM_CounterMode; //计数器模式
uint32_t TIM_Period; //自动重载值设置
uint16_t TIM_ClockDivision; //时钟分频因子,通常为1即不分频 uint8_t TIM_RepetitionCounter; //重复计数器,高级定时器才会用
} TIM_TimeBaseInitTypeDef;
定时时间计算:Tout= ((per)*(psc+1))/Tclk;
Tclk:系统时钟频率
psc:预分频系数
per:自动重载值
(3)设置定时器中断类型,并使能
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState)
(4)设置定时器中断优先级,使能定时器中断通道
(5)开启定时器
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState)
(6)编写定时器中断服务函数
TIM4_IRQHandler
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT); if(TIM_GetITStatus(TIM4,TIM_IT_Update)) { ...//执行TIM4更新中断内控制 }
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);
2.2 配置流程
(1)添加定时器的源文件和头文件及其路径:
(2)定时器初始化:
(3)中断服务函数:
(4)主函数:
3.硬件设计
4.软件设计
4.1 功能描述
本实验所要实现的功能是:通过 TIM4 的更新中断控制 DS1 指示灯间隔 500ms 秒状态取反,主函数控制 DS0 指示灯不断闪烁。
4.2 软件实现
(1)初始化TIM4,并使能更新中断;
/* ---------------------------------函数声明------------------------------------- *函数名称:TIM4_Iint(u16 per, u16 psc) *输入参数:u16 per:自动重装载值;u16 psc:预分频系数 *返回参数:无 *功 能:初始化定时器TIM4 *作 者:lph *日 期:2024/03/26 ------------------------------------------------------------------------------ */ void TIM4_Iint(u16 per, u16 psc) { //1.使能定时器时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE); //2.初始化定时器参数 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_TimeBaseInitStructure.TIM_Period=per; TIM_TimeBaseInitStructure.TIM_Prescaler=psc; TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; TIM_TimeBaseInit(TIM4, &TIM_TimeBaseInitStructure); //3.设置定时器中断类型,并使能 TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE); TIM_ClearITPendingBit(TIM4, TIM_IT_Update); //清除中断标志位:防止前面被使用 NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel=TIM4_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2; NVIC_InitStructure.NVIC_IRQChannelSubPriority=3; NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE; NVIC_Init(&NVIC_InitStructure); //4.开启定时器 TIM_Cmd(TIM4, ENABLE); //5.编写定时器中断服务函数 }
(2)编写TIM4中断函数;
// -----------------------------2.定时器中断服务函数----------------------------- /* ---------------------------------函数声明------------------------------------- *函数名称:TIM4_IRQHandler(void) *输入参数:无 *返回参数:无 *功 能:定时器中断服务函数 *作 者:lph *日 期:2024/03/26 ------------------------------------------------------------------------------ */ void TIM4_IRQHandler(void) { if(TIM_GetITStatus(TIM4, TIM_IT_Update) == SET) { LED1 = !LED1; } TIM_ClearITPendingBit(TIM4, TIM_IT_Update); //清除中断状态标志位 }
(3)编写主函数。
/* Includes ------------------------------------------------------------------*/ #include "stm32f10x.h" #include "system.h" #include "LED.h" #include "SysTick.h" #include "TIME.h" /* 主函数main() --------------------------------------------------------------*/ int main() { // 自定义变量 u8 i=0; // 初始化 SysTick_Iint(72); NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 中断分组 LED_Init(); TIM4_Iint(1000, 36000-1); // 分频系数为36000时,每次计数0.5ms while(1) { i++; if(i%20==0) { LED0 = !LED0; } delay_ms(10); } }