前言
本例使用芯片为 STM32f407zg
使用标准库编程
输出指定脉冲个数的PWM方法主要有两种:计数器中断方式和定时器同步方式。
项目输出可控双脉冲pwm波形,可根据需要控制输出脉冲个数,查阅网上资料大部分为HAL库配置,自己实际第一次编程有些一头雾水,后查阅官方帮助手册和参考手册,配置出项目,故在此纪录。
1、计数器中断方式
原理:
程序定义两个定时器,定时器1负责计数,开启定时器1比较中断和溢出更新中断,在达到给定的比较值时产生中断,进入中断开启定时器2输出PWM波(设置占空比),在达到溢出值时产生更新中断,停止定时器2的PWM输出(占空比0),从而达到稳定输出脉冲个数。结果如图
主要程序:
定时器1:
TIM_TimeBaseInitTypeDef TIM_TimeStructure;
TIM_OCInitTypeDef TIM_OCStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //选择优先级分组2。
NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_TIM10_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//引脚复用
GPIO_PinAFConfig(GPIOF, GPIO_PinSource6, GPIO_AF_TIM10);
GPIO_Init(GPIOF,&GPIO_InitStructure);
//时基单元
RCC_APB2PeriphClockCmd(Major_TIM_CLK,ENABLE);
TIM_TimeStructure.TIM_Period = TIM_Time-1;
TIM_TimeStructure.TIM_Prescaler = Major_TIM_Prescaler;
TIM_TimeStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM10,&TIM_TimeStructure);
//占空比设置
TIM_OCStructure.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCStructure.TIM_OutputState = TIM_OutputState_Enable;//比较输出使能
TIM_OCStructure.TIM_Pulse = TIM_duty*TIM_Time;
TIM_OCStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OC1Init(TIM10, &TIM_OCStructure);
TIM_OC1PreloadConfig(TIM10, TIM_OCPreload_Enable);//使能预装载值处理器
TIM_ARRPreloadConfig(TIM10, ENABLE);//使能ARPE位
TIM_ClearFlag(TIM10, TIM_FLAG_Update);//清除中断标志位
TIM_ITConfig(TIM10,TIM_FLAG_Update,ENABLE); //开启中断
TIM_ITConfig(TIM10,TIM_FLAG_CC1,ENABLE);
TIM_Cmd(TIM10,ENABLE);
以定时器10为计数器,在比较值和更新值分别进入中断,比较值中断负责开启定时器2PWM,更新值中断负责关闭。
定时器2:
TIM_TimeBaseInitTypeDef TIM_TimeStructure;
TIM_OCInitTypeDef TIM_OCStructure;
GPIO_InitTypeDef GPIO_InitStructure; //定义IO口模式,并初始化IO口
RCC_APB2PeriphClockCmd(Main_TIM_CLK,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_TIM9);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_Init(GPIOA,&GPIO_InitStructure);
TIM_TimeStructure.TIM_Period = Main_Time-1;
TIM_TimeStructure.TIM_Prescaler = Main_TIM_Prescaler;
TIM_TimeStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM9,&TIM_TimeStructure);
TIM_OCStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCStructure.TIM_Pulse = Main_Time*0.5;
//TIM_OCStructure.TIM_Pulse = 100;
TIM_OC1Init(TIM9,&TIM_OCStructure);
TIM_OC1PreloadConfig(TIM9, TIM_OCPreload_Enable);//使能预装载值处理器
TIM_ARRPreloadConfig(TIM9, ENABLE);//使能ARPE位
TIM_Cmd(TIM9,ENABLE);
中断服务函数:
void TIM1_UP_TIM10_IRQHandler(void)
{
if(TIM_GetITStatus(TIM10,TIM_FLAG_Update)!=RESET)
{
TIM_ClearITPendingBit(TIM10, TIM_FLAG_Update); //清除中断标志位
TIM_SetCompare1(TIM9,50);
}
if (TIM_GetITStatus(TIM10, TIM_FLAG_CC1)!=RESET)
{
TIM_ClearITPendingBit(TIM10, TIM_FLAG_CC1);
TIM_SetCompare1(TIM9,0);
}
}
2、定时器同步方式
原理:
stm32定时器从内部就连接到一起,可以查询芯片参考手册获取主从定时器分配信息。如图查询结果:
本例中设置TIM9为从定时器,TIM10为主定时器,采用门控方式输出
因此设置TIM9为ITR2模式,TIM_SlaveMode_Gated门控
通过定时器 10 的输出比较来使能定时器 9。 仅当定时器 10的 OC1REF 为高电平时,定时器 9 才根据分频后的内部时钟进行计数。
如图所示:
其中第一中为复位,第二中为门控,这两种较为常用
主要程序:
主定时器:
static void TIM10_TimeConfig(u16 TIM_Time,double TIM_duty)
{
TIM_TimeBaseInitTypeDef TIM_TimeStructure;
TIM_OCInitTypeDef TIM_OCStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//引脚复用
GPIO_PinAFConfig(GPIOF, GPIO_PinSource6, GPIO_AF_TIM10);
GPIO_Init(GPIOF,&GPIO_InitStructure);
//时基单元
RCC_APB2PeriphClockCmd(Major_TIM_CLK,ENABLE);
TIM_TimeStructure.TIM_Period = TIM_Time-1;
TIM_TimeStructure.TIM_Prescaler = Major_TIM_Prescaler;
TIM_TimeStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM10,&TIM_TimeStructure);
//占空比设置
TIM_OCStructure.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCStructure.TIM_OutputState = TIM_OutputState_Enable;//比较输出使能
TIM_OCStructure.TIM_Pulse = TIM_duty*TIM_Time;
TIM_OCStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OC1Init(TIM10, &TIM_OCStructure);
TIM_OC1PreloadConfig(TIM10, TIM_OCPreload_Enable);//使能预装载值处理器
TIM_ARRPreloadConfig(TIM10, ENABLE);//使能ARPE位
TIM_ITConfig(TIM10,TIM_FLAG_CC1,ENABLE);
//定时器主模式设置
TIM_SelectMasterSlaveMode(TIM10, TIM_MasterSlaveMode_Enable);//开启 Master/Slave 模式
TIM_SelectOutputTrigger(TIM10,TIM_TRGOSource_Update);
TIM_Cmd(TIM10,ENABLE);
}
从定时器:文章来源:https://www.toymoban.com/news/detail-586768.html
static void TIM9_TimeConfig(u16 Main_Time)
{
//时基单元
TIM_TimeBaseInitTypeDef TIM_TimeStructure;
TIM_OCInitTypeDef TIM_OCStructure;
GPIO_InitTypeDef GPIO_InitStructure; //定义IO口模式,并初始化IO口
RCC_APB2PeriphClockCmd(Main_TIM_CLK,ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_TIM9);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
TIM_TimeStructure.TIM_Period = Main_Time-1;
TIM_TimeStructure.TIM_Prescaler = Main_TIM_Prescaler;
TIM_TimeStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM9,&TIM_TimeStructure);
TIM_OCStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCStructure.TIM_Pulse = Main_Time*0.5;
//TIM_OCStructure.TIM_Pulse = 100;
TIM_OC1Init(TIM9,&TIM_OCStructure);
//定时器从模式设置
TIM_SelectSlaveMode(TIM9, TIM_SlaveMode_Gated);//允许Slave 模式
TIM_SelectInputTrigger(TIM9, TIM_TS_ITR2);
TIM_OC1PreloadConfig(TIM9, TIM_OCPreload_Enable);//使能预装载值处理器
TIM_ARRPreloadConfig(TIM9, ENABLE);//使能ARPE位
TIM_Cmd(TIM9,ENABLE);
}
结果图:文章来源地址https://www.toymoban.com/news/detail-586768.html
到了这里,关于stm32定时器方式精确输出指定脉冲个数的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!