目录
定时器
STM32F1中,除了互联型的产品,共有8个定时器。
控制器上的所有定时器都是彼此独立,不共享任何资源。
基本定时器只能定时,没有外部IO。
通用定时器可以定时,输出比较(如PWM),输入捕获(如脉冲),每个定时器有四个外部IO。
高级定时器可以定时,输出比较(如PWM),输入捕获(如脉冲),三相电机互补输出,每个定时器有八个外部IO。
基本定时器
基本定时器TIM6和TIM7由一个可编程预分频器驱动的16位自动重新加载计数器组成。应用:定时、驱动DAC。事实上,定时器内部连接到DAC,并能够通过其触发器输出驱动它。
计数器是完全独立的,不共享任何资源。核心是时基。
功能框图
基本定时器包括:
16位自动重装载计数器。
16位可编程预分频器,1~65536。
同步电路触发DAC
在更新事件上产生中断/DMA:计数器溢出
时钟源
定时器时钟TIMxCLK(即内部时钟CK_INT),经APB1预分配器分频提供。根据时钟树,得知如果APB1预分配系数等于1,则频率不变,否则频率系数*2。
时钟树的APB1为低速时钟,经AHB 2分频所得,即PCLK1=36M。所以定时器时钟TIMxCLK=36M*2=72M。
PSC预分频器
定时器时钟经过 PSC 预分频器之后,即 CK_CNT,用来驱动计数器计数。 PSC 是一个 16 位的预分频器,可以对定时器时钟 TIMxCLK 进行 1~65536 之间的任何一个数进行分频。具体计算方式为: CK_CNT=TIMxCLK/(PSC+1)。
CNT计数器
计数器 CNT 是一个 16 位的计数器,只能往上计数,最大计数值为 65535。
ARR自动重装载寄存器
自动重装载寄存器 ARR 是一个 16 位的寄存器,这里面装着计数器能计数的最大数值。当计数达到自动重装载寄存器的时候产生更新事件,并清零从头开始计数。如果使能了中断的话,定时器就产生溢出中断。
定时时间的计算
定时器的定时时间等于计数器的中断周期乘以中断次数。定时器在 CK_CNT 的驱动下,计一个数的时间则是 CK_CLK 的倒数,等于1/(TIMxCLK/(PSC+1)),产生一次中断的时间则等于:(1/CK_CNT)*(ARR+1)。
如:psc=71,add=999。
CK_CNT=TIMxCLK/(PSC+1)=72M/72=1MHz,计数器在 CK_CNT 的驱动下,计一个数的时间则是 CK_CLK 的倒数,等于:1/1MHz=1us。
即1us一个节拍。向上计数达1000个节拍时结束,即1ms。
初始化结构体
typedef struct
{
uint16_t TIM_Prescaler; // 预分频器,基本定时器配置需要
uint16_t TIM_CounterMode; // 计数模式
uint16_t TIM_Period; // 定时周期,基本定时器配置需要
uint16_t TIM_ClockDivision; // 时钟分频
uint8_t TIM_RepetitionCounter; // 重复计数器
} TIM_TimeBaseInitTypeDef;
基本定时器实验
常规配置
USART:115200-8-N-1,支持重定向输出printf函数,勾选使用C库。
TIM6配置
1/(1+71)/72M * (999+1)= 1ms进一次中断。
TIM_HandleTypeDef htim6;
void MX_TIM6_Init(void)
{
TIM_MasterConfigTypeDef sMasterConfig = {0};
htim6.Instance = TIM6;
htim6.Init.Prescaler = 71;
htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
htim6.Init.Period = 999;
htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim6) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
}
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *tim_baseHandle)
{
if (tim_baseHandle->Instance == TIM6)
{
__HAL_RCC_TIM6_CLK_ENABLE();
/* TIM6 interrupt Init */
HAL_NVIC_SetPriority(TIM6_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM6_IRQn);
}
}
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef *tim_baseHandle)
{
if (tim_baseHandle->Instance == TIM6)
{
__HAL_RCC_TIM6_CLK_DISABLE();
/* TIM6 interrupt Deinit */
HAL_NVIC_DisableIRQ(TIM6_IRQn);
}
}
测试环节
volatile uint32_t time_ms;
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
time_ms++;
}
void test(void)
{
初始化
/* 在中断模式下启动定时器 */
HAL_TIM_Base_Start_IT(&htim6);
while(1)
{
if (time_ms == 1000) // 1s
{
time_ms = 0;
printf("couvrir\r\n");
}
}
}
实验现象
定时器初始化结构体
时基初始化结构体 TIM_TimeBaseInitTypeDef 基本、通用、高级
输出比较初始化结构体 TIM_OCInitTypeDef 通用、高级
输入捕获初始化结构体 TIM_ICInitTypeDef 通用、高级
断路和死区初始化结构体 TIM_BDTRInitTypeDef 高级