基本定时器流程图:
其中PSC预分频器与自动重载寄存器ARR都有影子寄存器,预分频器寄存器和自动重载寄存器起着缓存的作用。
当有事件产生的时候,自动重载寄存器将值传入影子寄存器中。
基本定时器的溢出条件为CNT==ARR(影子),当基本定时器溢出时,会产生事件,中断和DMA请求。
16 位可编程预分频器,用于对计数器时钟频率进行分频(即运行时修改),分频系数 介于 1 和 65536 之间。
基本的一些配置步骤
结构体成员
timer.c
#include "timer.h"
#include "led.h"
TIM_HandleTypeDef TIM_Handle;//句柄
void timer_init(uint32_t psc,uint32_t arr) // 定时器初始化函数
{
TIM_Handle.Instance = TIM6 ;
TIM_Handle.Init.Prescaler = psc;
TIM_Handle.Init.Period = arr ;
HAL_TIM_Base_Init(&TIM_Handle);
HAL_TIM_Base_Start_IT(&TIM_Handle);
}
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim) //MSP函数
{
if ( htim ->Instance == TIM6 ) //在多串口的情况下,比如tim和usart等
{
__HAL_RCC_TIM6_CLK_ENABLE();
HAL_NVIC_SetPriority(TIM6_DAC_IRQn,0,0);
HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn);
}
}
void TIM6_DAC_IRQHandler(void)// TIM6_DAC_IRQHandler //中断服务函数
{
HAL_TIM_IRQHandler(&TIM_Handle);
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) //callback函数
{
if ( htim ->Instance == TIM6 ) //在多串口的情况下,比如tim和usart等
{
HAL_GPIO_TogglePin( GPIOB , GPIO_PIN_0);
}
}
main.c
int main(void)
{
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(360,25,2,8); //设置时钟,180Mhz
delay_init(180); //初始化延时函数
uart_init(115200); //初始化USART
LED_Init(); //初始化LED
KEY_Init(); //初始化按键
timer_init(9000-1,5000-1); //定时器6初始化,定时器时钟为90M,分频系数为9000-1,
//所以定时器6的频率为90M/9000=10K,自动重装载为5000-1,那么定时器周期就是500ms
while(1)
{
delay_ms(600);//因为设置的周期为500ms,所以600ms的延迟是溢出的,也是5s一反转
}
}
记录一下自己犯错误的地方
1.句柄申明在.h文件申明时一定要加分号!!!本人因为这个查了半小时的错
extern TIM_HandleTypeDef TIM_Handle;
2.中断服务函数一定要在.s文件中找,因为TIM6的通道有和DAC复用,一开始写的中断服务函数为TIM6_IRQHandler(void),死活程序跑不对,后面改成TIM6_DAC_IRQHandler(void)就对了。
3.要养成写一段代码保存一段的好习惯,不然等全部写完找错太麻烦了。