前言
本文章使用STM32F103C8T6标准库实现TIM1的定时功能,代码如下:
#include "stm32f10x.h" // Device header
#include "led_drv.h"
static void timInit(uint32_t periodUs)
{
/*使能定时器时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
/*定时器复位*/
TIM_DeInit(TIM1);
/*定时器配置*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruct);
TIM_TimeBaseInitStruct.TIM_Prescaler = SystemCoreClock / 1000000 - 1;//输入给计数器的时钟频率为1Mhz,周期1us
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_Period = periodUs - 1;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseInitStruct);
TIM_ClearFlag(TIM1, TIM_FLAG_Update);
/*使能定时器更新中断*/
TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);
/*NVIC配置*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//一个工程只分组一次
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = TIM1_UP_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&NVIC_InitStruct);
/*定时器使能*/
TIM_Cmd(TIM1, ENABLE);
TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
}
/**
***********************************************************
* @brief 定时器驱动初始化
* @param
* @return
***********************************************************
*/
void TimDrvInit(void)
{
timInit(1000);
}
/**
***********************************************************
* @brief 定时器1更新中断服务函数
* @param
* @return
***********************************************************
*/
void TIM1_UP_IRQHandler(void)
{
if ( TIM_GetITStatus(TIM1, TIM_IT_Update) )
{
// static uint32_t s_counter;
// static uint8_t flipFlag = 1;
// s_counter ++;
// if (s_counter >= 1000 && flipFlag)
// {
// s_counter = 0;
// flipFlag = 0;
// TurnOnLed(LED_BLUE);
// TurnOnLed(LED_YELLOW);
// TurnOnLed(LED_WHITE);
// }
// else if (s_counter >= 1000 && flipFlag == 0)
// {
// s_counter = 0;
// flipFlag = 1;
// TurnOffLed(LED_BLUE);
// TurnOffLed(LED_YELLOW);
// TurnOffLed(LED_WHITE);
// }
TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
}
}
一 基本定时框图
来自RCC的TIM1CLK的频率是72MHz,PSC预分频器是一个16位的寄存器,所以分频系数可以选择的范围是0~65535,假如设置预分频系数为0,那就是不分频(1分频),CK_CNT == TIM1CLK / 1;假如预分频系数PSC为71, 那就是72分频,CK_CNT == TIM1CLK / 72 == 1MHz。
CNT计数器是一个周期计数器,CK_CNT每来一个时钟周期就±1,假如CK_CNT == 1MHz,那么周期t = 1/f = 1us,也就是说CNT计数器每计数一次就是1us。
这时,如果自动重装载寄存器设置为999,那么每1000us即1ms产生一次更新中断,如此实现定时的功能。为什么是999重装值而不是1000呢, 假如我需要4us产生一次中断,那我设置重装寄存器的值为4, 计数器从0-1计数1次, 从1-2计数2次, 从2-3计数3次,从3-4计数4次, 从4-0计数5次,为0产生更新中断,所以需要减1。
二 代码实现
2.1 驱动初始化
只讲一些要点,不逐一进行分析。
①TIM_TimeBaseStructInit这个函数是为了对结构体初始化,因为TIM_TimeBaseInitStruct是一个局部变量,我们实现定时器1的定时功能并不会用到它的所有成员,而局部变量不赋初值其值是不确定的,所以需要进行初始化。
②SystemCoreClock / 1000000 - 1;使用这个作为预分频系数,假如系统时钟是36MHz,同样得到CK_CNT为1MHz。
③TIM_CounterMode_Up为向上计数模式,关于计数模式网上资料很多,可自行查阅。
static void timInit(uint32_t periodUs)
{
/*使能定时器时钟*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
/*定时器复位*/
TIM_DeInit(TIM1);
/*定时器配置*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_TimeBaseStructInit(&TIM_TimeBaseInitStruct);
TIM_TimeBaseInitStruct.TIM_Prescaler = SystemCoreClock / 1000000 - 1;//输入给计数器的时钟频率为1Mhz,周期1us
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_Period = periodUs - 1;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseInitStruct);
TIM_ClearFlag(TIM1, TIM_FLAG_Update);
/*使能定时器更新中断*/
TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);
/*NVIC配置*/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//一个工程只分组一次
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel = TIM1_UP_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&NVIC_InitStruct);
/*定时器使能*/
TIM_Cmd(TIM1, ENABLE);
TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
}
2.2 中断服务函数
唯一要注意的就是更换定时器后记得更换中断服务函数,进入中断后,不要忘记清除中断标志位。
/**
***********************************************************
* @brief 定时器1更新中断服务函数
* @param
* @return
***********************************************************
*/
void TIM1_UP_IRQHandler(void)
{
if ( TIM_GetITStatus(TIM1, TIM_IT_Update) )
{
/*实现功能*/
TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
}
}
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/m0_73101636/article/details/143570022
|