STM32主从定时器输出指定PWM波个数(基于标准库)
一、开发环境
硬件
STM32F103C8T6、STLINK
软件
Keil5
二、开发思路
主定时器每完成一个计数周期(CNT = ARR),产生一个更新事件,用主定时器的更新事件作为从定时器开始计数的触发条件。
注意:主定时器每完成一个计数周期,就向从定时器发出一个脉冲信号,触发从定时器开始计数,但从定时器的计数频率还是取决于从定时器的时基单元配置。
实验简介
配置TIM2为主定时器,主频72MHz,分频系数7200,自动重装载值10000。定时时间T=(分频系数7200 X 自动重装载值10000) / 主频72MHz = 1s,则TIM2的计数频率就是1Hz,即每1s发出一个PWM波脉冲,高电平与低电平时间各占500ms,占空比50%。每发出一个PWM波脉冲(每1s产生一次更新事件),用作从定时器TIM3的开始计数条件,从定时器TIM3开始计数自增一次。将从定时器TIM3的自动重装载值ARR设置为想要的PWM波输出个数,达到从定时器TIM3的自动重载值ARR时,代表已经输出了期望的PWM脉冲个数,则从定时器产生更新事件,通过更新事件进入从定时器TIM3的中断关闭主定时器输出比较通道的输出。
三、代码
主从定时器设置
#include "stm32f10x.h" // Device header
/*主定时器初始化*/
void MasterTimer_Init(void)
{
/*开启时钟*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
/*PWM复用引脚配置*/
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP; //复用推挽输出
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
/*时基单元配置*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 10000-1; //ARR = 10000
TIM_TimeBaseInitStructure.TIM_Prescaler = 7200-1; //Pres = 7200
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
/*输出比较通道配置*/
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //PWM模式1
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 5000; //占空比50%
TIM_OC1Init(TIM2,&TIM_OCInitStructure);
TIM_SelectMasterSlaveMode(TIM2,TIM_MasterSlaveMode_Enable); //TIM2配置为主模式
TIM_SelectOutputTrigger(TIM2,TIM_TRGOSource_Update); //将TIM2的更新事件作为从定时器的触发源
TIM_OC1PreloadConfig(TIM2,TIM_OCPreload_Enable); //输出比较通道使能预装载
TIM_ARRPreloadConfig(TIM2,ENABLE); //自动重装载值使能预装载
TIM_Cmd(TIM2,DISABLE); //初始化时使能,在主程序中开启
}
/*从定时器初始化*/
void SlaveTimer_Init(void)
{
/*开启时钟*/
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
/*时基单元配置*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 3-1; //从定时器ARR=3,期望PWM脉冲个数为3
TIM_TimeBaseInitStructure.TIM_Prescaler = 1-1; //从定时器计数频率不分频
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_External1); //从定时器的CNT以外部信号为时钟源,来一个外部信号,CNT计数自增一次
TIM_SelectInputTrigger(TIM3,TIM_TS_ITR1); //参考手册,与主定时器TIM2进行链接
TIM_ARRPreloadConfig(TIM3,ENABLE);
/*中断配置*/
TIM_ClearFlag(TIM3,TIM_IT_Update);
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM3,ENABLE);
}
主程序逻辑实现
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "LED.h"
#include "Key.h"
#include "Timer.h"
uint8_t count; //定义一个变量,从定时器每计数3次,该变量自增一次
int main(void)
{
/*初始化各个外设*/
LED_Init();
Key_Init();
MasterTimer_Init();
SlaveTimer_Init();
while (1)
{
/*检测到按键按下,主定时器TIM2使能,以1Hz输出PWM脉冲*/
uint8_t KeyNum = Key_GetNum();
if(1 == KeyNum)
{
TIM_Cmd(TIM2,ENABLE);
}
}
}
/*从定时器TIM3中断服务函数,主定时器每输出3个PWM波脉冲,就关闭主定时器,同时count++*/
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update) == SET)
{
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
count++;
TIM_Cmd(TIM2,DISABLE);
}
}
四、实验现象
本实验现象是输出指定个数的PWM波,为了人眼能够捕捉到现象,将主定时器TIM2的PWM输出频率设计为1s,从定时器TIM3的自动重装载值ARR=3,则按键按下一次,LED闪烁三次就熄灭,同时count每隔3s就自增一次。这样就实现了精准输出3个PWM波的需求。在实际应用中,可将PWM频率加快,用于精准控制步进电机转动。
现象一
按键按下一次,LED闪烁三次就熄灭。
主从定时器现象1
现象二
按键按下一次,每一秒TIM2的CNT++,从0计数到2,即3秒后coun+1
主从定时器现象2
五、参考来源
stm32定时器级联(一个定时器作为另一个的预分频器-CSDN博客
【STM32通过定时器主从模式-发送固定脉冲控制步进电机】 https://www.bilibili.com/video/BV15gyaYaEFh/?share_source=copy_web&vd_source=987431de99321d6d0cab581ffaaff0cd
六、总结
本次实验实现了主从定时器输出指定个数PWM波脉冲。创作不易,欢迎大家点赞,收藏,关注,交流学习。
作者:小李子学ROS