5. 定时器TIM
5.1 TIM结构及寄存器说明
5.2 TIM设计实例
5.2.1 1s定时程序设计
5.2.2 矩形波输出程序设计
5.2.3 矩形波测量程序设计
5.1 TIM结构及寄存器说明
- 定时器TIM2-5、基本定时器TIM6/7、实时钟RTC、独立看门狗IWDG和窗口看门狗WWDG等
- 高级控制定时器除了具有刹车输入BKIN、互补输出CHxN和重复次数计数器外与通用定时器的主要功能基本相同,两者都包含基本定时器的功能
- 实时钟提供时钟日历的功能。独立看门狗和窗口看门狗用来检测和解决软件错误引起的故障
- 高级控制定时器主要由时基单元、输入捕获和输出比较等部分组成
- 时基单元包含16位计数器CNT、预分频器PSC、自动装在寄存器ARR和重复次数计数器RCR
- 时基单元是定时器的核心,也是基本定时器的主要功能单元
- 输入捕获包含输入滤波器和边沿检测器、预分频器和捕获/比较寄存器等,可以测量输入信号的周期和脉冲宽度
- 输出比较包含捕获/比较寄存器、死区发生器DTG和输出控制,可以产生PWM等
- TIM使用的GPIO引脚
- TIM通过20个寄存器进行操作
5.2 TIM设计实例
5.2.1 1s定时程序设计
- 1s定时(定时精度0.5ms)的实现只用到基本定时器(时基单元)的核心功能,相关的寄存器及其内容为
- 实现1s定时的初始化子程序
//1s定时器初始化子程序
void Tin1_Init(void)
{
RCC->APB2ENR |= 1<<11; //开启TIM1时钟
TIM1->PSC = 4000; //预分频值(8MHz/4000=2kHz,1/2kHz=0.5ms)
TIM1->ARR = 2000; //自动装载值(2kHz/2000=1Hz)
TIM1->CR1 = 1; //计数请允许
}
- 实现1s定时的处理子程序
//1s定时处理子程序
void Tim1_Proc(void)
{
if(TIM1->SR & 1) //UIF=1(更新中断标志)
{
TIM1->SR &= ~1; //清除UIF
if((++sec & 0xf) >9)
sec += 6; //2-10进制调整
if(sec >= 0x60) //60s时间到
{
sec = 0;
if((++min & 0xf)>9)
min +=6; //2-10
if(min >= 0x60) //60m时间到
min =0;
}
}
}
5.2.2 矩形波输出程序设计
- TIM1输出矩形波初始化子程序
//1s定时处理子程序
void Tim1_Proc(void)
{
if(TIM1->SR & 1) //UIF=1(更新中断标志)
{
TIM1->SR &= ~1; //清除UIF
if((++sec & 0xf) >9)
sec += 6; //2-10进制调整
if(sec >= 0x60) //60s时间到
{
sec = 0;
if((++min & 0xf)>9)
min +=6; //2-10
if(min >= 0x60) //60m时间到
min =0;
}
}
}
- TIM1输出矩形波处理子程序
//TIM1处理子程序(调整占空比)
void Tim1_Proc(void)
{
if(TIM1->SR & 1) //UIF=1(更新中断标志)
{
TIM1->SR &= ~1; //清除UIF
TIM1->CCR1 = tim1_ccr1[ccr_num];//改变矩形波占空比
if(++ccr_num == 9)
ccr_num = 0;
}
}
- 使用仿真器调试和运行程序时可以用逻辑分析仪观测PA.08(PORTA.08)输出的波形
5.2.3 矩形波测量程序设计
- 用TIM2测量矩形波的周期和脉冲宽度(测量精度0.25ms)在用TIM1输出矩形波的基础上用定时器的输入捕获功能实现,相关的寄存器及其内容为
- TIM2测量矩形波周期和脉冲宽度初始化子程序
//TIM2初始化子程序(TIM2通道2-PA.01 测量矩形波周期和脉冲宽度)
void Tim2_Init(void)
{
RCC->APB2ENR |= 1<<2; //开启GPIOA时钟
RCC->APB1ENR |= 1; //开启TIM2时钟
TIM2->SMCR |= 0x64; //TI2FP2触发,复位模式
TIM2->CCMR1 |= 0x102; //CC1/2输入捕获TI2
TIM2->CCER |= 0x13; //CC1/2输入允许,CC1反相
TIM2->PSC = 2000; //预分频值(8MHz/2000=4kHz)
TIM2->ARR = 4000; //自动装载值
TIM2->CR1 = 1; //计数器允许
}
- TIM2测量矩形波周期和脉冲宽度处理子程序
//TIM2处理子程序(测量矩形波周期和脉冲宽度)
void Tim2_Proc(void)
{
if(TIM2->SR & 4) //CC2 IF=1(捕获/比较 2 中断标志)
tim2_ccr2 = TIM2->CCR2; //读取周期,清除CC2IF
if(TIM2->SR & 2) //CC1 IF=1(捕获/比较 1 中断标志)
tim2_ccr1 = TIM2->CCR1+1; //读取宽度,清除CC1IF
}