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

现象二

按键按下一次,每一秒TIM2CNT++,从0计数到2,即3秒后coun+1

主从定时器现象2

 五、参考来源

stm32定时器级联(一个定时器作为另一个的预分频器-CSDN博客

【STM32通过定时器主从模式-发送固定脉冲控制步进电机】 https://www.bilibili.com/video/BV15gyaYaEFh/?share_source=copy_web&vd_source=987431de99321d6d0cab581ffaaff0cd

六、总结

本次实验实现了主从定时器输出指定个数PWM波脉冲。创作不易,欢迎大家点赞,收藏,关注,交流学习。

作者:小李子学ROS

物联沃分享整理
物联沃-IOTWORD物联网 » STM32主从定时器输出指定PWM波个数(基于标准库)

发表回复