STM32 定时器间的同步 主TIM1产生PWM 从TIM4精确控制TIM1 PWM脉冲数量
文章目录
编译器平台及例程说明
编译器平台说明
1. Toolchain : MDK-ARM Community Version: 5.30.0.0(Kile V5)
2. Encoding : Chinese GB2312(Simplified)
3. Device Specific Packs : Keil.STM32F1xx_DFP.2.3.0.pack
4. C/C++ Preprocessor Symbols : STM32F10X_HD,USE_STDPERIPH_DRIVER
USE_STDPERIPH_DRIVER :允许使用标准外设驱动
STM32F10X_HD :STM32F10x大容量产品
5. Chip Type :STM32F103RET6, Flash:512KByte, ROM:48KByte, LQFP64
6. 在stm32hf10x.h文件中HSE_VALUE为外部高速振荡器,默认8MHZ。此值必须与硬件保持一致。
例程说明
1. TIM1作为主模式输出PWM,TIM1的更新事件作为从模式TIM4的时钟源。
TIM4的计数值即为TIM1产生PWM的数量。当设置TIM4的计数值时,计数器溢出产生更新事件,
在TIM4中断的更新事件中关闭TIM1和TIM4,并清除TIM4的更新事件,即可精确控制TIM1产生PWM的数量。
2. TIM1作为主模式,其通道CH2N产生1KHZ 50%占空的PWM。
3. TIM1的更新事件作为触发信号输出。
4. TIM4作为从模式,当收到TIM1的触发信号时计数器时钟开启。
5. 当TIM4产生更新事件时,在TIM4中断中关闭TIM1和TIM4,并清除TIM4的更新事件。
6. TIM1产生PWM周期/频率、占空比、脉冲数都可以重新设置。
一、PWM GPIO 配置
/**********************************************************************************************************************************************
* 函数名 : vPWM_GPIO_Config
* 描 述 : PWM GPIO配置
**********************************************************************************************************************************************/
#define TIM1_CH2N_Pin GPIO_Pin_14
static void vPWM_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); //Enable GPIOB and AFIO clock
GPIO_InitStructure.GPIO_Pin = TIM1_CH2N_Pin; //GPIO pin
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //GPIO mode
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //GPIO speed
GPIO_Init(GPIOB, &GPIO_InitStructure); //GPIO init
}
二、主模式TIM1初始化
/**********************************************************************************************************************************************
* 函数名 : vMasterTIM1_Init
* 描 述 : TIM1主PWM初始化
* 输 入 : perVal : 自动重转载值
* divClk : 时钟分频系数
* pulseVal : 占空比
* 说 明 : 1. TIM1 CH2N PWM为主模式
* 2. TIM1更新事件作为触发信号输出
**********************************************************************************************************************************************/
static void vMasterTIM1_Init(u16 perVal, u16 divClk, u16 pulseVal)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //Enable TIMx
TIM_TimeBaseStructure.TIM_Period = perVal; //TIMx period/Auto-Reload value
TIM_TimeBaseStructure.TIM_Prescaler = divClk; //TIMx Clock prescaler
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //TIMx clock division
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIMx counter mode
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //TIMx init
TIM_OCInitStructure.TIM_Pulse = pulseVal; //TIMx pulse value
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2; //TIMx mode
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable; //TIMx Output Compare state
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; //TIMx complementary Output Compare state
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low; //TIMx output polarity
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low; //TIMx complementary output polarity
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; //TIMx pin idle state
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset; //TIMx complementary pinidle state
TIM_OC2Init(TIM1, &TIM_OCInitStructure); //Init TIMx Channel
TIM_SelectMasterSlaveMode(TIM1, TIM_MasterSlaveMode_Enable); //Sets TIMx Master/Slave mode
TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_Update); //TIMx Selects trigger output mode
TIM_CtrlPWMOutputs(TIM1, ENABLE); //Disable TIMx peripheral Main Outputs
TIM_Cmd(TIM1, DISABLE); //Disable TIMx peripheral
}
三、从模式TIM4初始化
/**********************************************************************************************************************************************
* 函数名 : vSlaveTIM4_Init
* 描 述 : 从TIM4初始化
* 输 入 : perVal : 自动重转载值
* divClk : 时钟分频系数
* prePrio : 抢占优先级
* subPrio : 从优先级
* 说 明 : 1. TIM4为从模式,触发信号(TRGI)为高时计数时钟开启
* 2. TIM4输入触发源为内部触发0(ITR0/TIM1)
**********************************************************************************************************************************************/
static void vSlaveTIM4_Init(u16 perVal, u16 divClk, u8 prePrio, u8 subPrio)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //Enable TIMx clock
TIM_TimeBaseStructure.TIM_Period = perVal; //TIMx period/Auto-Reload value
TIM_TimeBaseStructure.TIM_Prescaler = divClk; //TIMx Clock prescaler
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //TIMx clock division
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIMx counter mode
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //TIMx init
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; //IRQ Channel
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = prePrio; //Preemption Priority
NVIC_InitStructure.NVIC_IRQChannelSubPriority = subPrio; //SubPriority Priority
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //Enable IRQ Channe
NVIC_Init(&NVIC_InitStructure); //Init NVIC
TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Gated); //Selects TIMx Slave Mode
TIM_SelectInputTrigger(TIM4, TIM_TS_ITR0); //Selects TIMx Input Trigger source
TIM_ClearITPendingBit(TIM4, TIM_IT_Update); //Clears TIMx interrupt pending bits
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE); //Enables TIMx update Interrupt source
TIM_Cmd(TIM4, DISABLE); //Disable TIMx peripheral
}
四、PWM周期 占空比 数量的设置
/**********************************************************************************************************************************************
* 函数名 : vPWM_Set
* 描 述 : PWM设置
* 输 入 : perVal : 周期
* pulseVal : 占空比
* pulseCount : 脉冲数
* 说 明 : 1. 改变TIM1产生PWM的周期及占空比
* 2. 设置TIM4记录TIM1更新事件次数
**********************************************************************************************************************************************/
void vPWM_Set(u16 perVal, u16 pulseVal, u16 pulseCount)
{
TIM1->ARR = perVal;//Period
TIM1->CCR2 = pulseVal;//Duty
TIM4->ARR = pulseCount;
vPWM_Control(ENABLE);
// TIM_SetAutoreload(TIM1, perVal);//TIM1->ARR = perVal
// TIM_SetCompare2(TIM1, pulseVal);//TIM1->CCR2 = pulseVal
// TIM_SetCounter(TIM1, countVal);//TIM1->CNT = countVal;
}
五、PWM控制
/**********************************************************************************************************************************************
* 函数名 : vPWM_Control
* 描 述 : PWM控制
* 输 入 : newCmd : 使能或失能
**********************************************************************************************************************************************/
static void vPWM_Control(FunctionalState newCmd)
{
TIM_ITConfig(TIM4, TIM_IT_Update, newCmd);
TIM_Cmd(TIM1, newCmd);
TIM_Cmd(TIM4, newCmd);
}
六、PWM初始化
/**********************************************************************************************************************************************
* 函数名 : vPWM_Init
* 描 述 : PWM 初始化
**********************************************************************************************************************************************/
void vPWM_Init(void)
{
vPWM_GPIO_Config();
vMasterTIM1_Init(999, 71, 499);//1KHZ 50%
vSlaveTIM4_Init(5000, 0, 3, 1);
}
七、TIM4中断服务处理
/**********************************************************************************************************************************************
* 函数名 : TIM4_IRQHandler
* 描 述 : TIM4中断服务
* 说 明 : 1. 关闭TIM1产生PWM
* 2. 关闭TIM4及更新中断
**********************************************************************************************************************************************/
void TIM4_IRQHandler(void)
{
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
{
vPWM_Control(DISABLE);
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);//Clears TIMx interrupt pending bits
}
}