这里使用STM32F407型号,其它版本可能略有区别
定时器同步可以用来BLDC的HALL、ENCODER、内部时钟相位一致
定时器同步触发:
主定时器配置:
1、TIM_SelectOutputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_TRGOSource);
TIMx:根据数据手册决定,看表76/72,这里我们选择TIM4
TIM_TRGOSource:输出触发源选项
TIM_TRGOSource_Reset
TIM_TRGOSource_Enable
TIM_TRGOSource_Update
TIM_TRGOSource_OC1
TIM_TRGOSource_OC1Ref
TIM_TRGOSource_OC2Ref
TIM_TRGOSource_OC3Ref
TIM_TRGOSource_OC4Ref
有8个选项,TIM_TRGOSource_OC1~TIM_TRGOSource_OC4Ref是OC输出,这里实验时采用PWM,可以的没问题;这里我们实验选择TIM_TRGOSource_OC1Ref
TIM_TRGOSource_Enable这一项也验证了,可以触发;
至于TIM_TRGOSource_Reset和TIM_TRGOSource_Update 这两项未能成功验证,反复试了很多方法,还是不行,现象:一上电,就触发了,根本不能控制
具体见手册,如下图
2、void TIM_SelectMasterSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_MasterSlaveMode);
TIMx:和上面保持一致
TIM_MasterSlaveMode:2个选项
TIM_MasterSlaveMode_Enable
TIM_MasterSlaveMode_Disable
这里使用TIM_MasterSlaveMode_Enable 使能主从模式
从定时器配置:
void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);
TIMx:参照表格76/72来确定,这里选择TIM5实验
TIM_InputTriggerSource:
TIM_TS_ITR0
TIM_TS_ITR1
TIM_TS_ITR2
TIM_TS_ITR3
TIM_TS_TI1F_ED
TIM_TS_TI1FP1
TIM_TS_TI2FP2
TIM_TS_ETRF
选择输入触发源,TIM_TS_ITR0~ TIM_TS_ITR3是表格76/72来确定的,和主定时器保持一致,这里我们选择TIM_TS_ITR2(即触发源是定时器4)
TIM_TS_TI1F_ED:一般用来bldc霍尔输入来触发的
TIM_TS_TI1FP1 :
TIM_TS_TI2FP2:这2个检测 编码器信号输入触发的
TIM_TS_ETRF:外部触发
这些验证没有问题
具体参数意义见手册,如下图
void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode);
TIMx:上同
TIM_SlaveMode:
TIM_SlaveMode_Reset :复位
TIM_SlaveMode_Gated :门控
TIM_SlaveMode_Trigger :触发
TIM_SlaveMode_External1 :外部
从定时器模式选择,这里反复实验验证TIM_SlaveMode_Gated、 TIM_SlaveMode_External1
没有问题
至于TIM_SlaveMode_Reset只对TI1有效,即定时器输入1通道和TIM_SlaveMode_Trigger只对TI2有效,即定时器输入2通道,都是适用于外部信号触发,比如hall,编码器,按键;见下图
详细见手册,如下图
详细见手册,如下图
下面示意2种同步代码
代码1:触发输出采用TIM_TRGOSource_Enable
触发输入采用TIM_SlaveMode_Gated
//从定时器
void Tim5_init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStre;
NVIC_InitTypeDef NVIC_InitStre;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
TIM_ITConfig(TIM5,TIM_IT_Update,DISABLE);
TIM_Cmd(TIM5, DISABLE);
//计数频率100Hz=84/(TIM_Prescaler+1)/(TIM_Period+1)
TIM_TimeBaseInitStre.TIM_Prescaler=84-1;//定时器频率84M/(840)=1us
TIM_TimeBaseInitStre.TIM_Period=50000-1;//周期计数值500 T=200Hz=5ms
TIM_TimeBaseInitStre.TIM_ClockDivision=0x00;//不分频
TIM_TimeBaseInitStre.TIM_CounterMode=TIM_CounterMode_Up ;
TIM_TimeBaseInitStre.TIM_RepetitionCounter=0;
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseInitStre);
TIM_SelectSlaveMode(TIM5,TIM_SlaveMode_Gated);
TIM_SelectInputTrigger(TIM5,TIM_TS_ITR2);//设置输入触发源
NVIC_InitStre.NVIC_IRQChannel=TIM5_IRQn;
NVIC_InitStre.NVIC_IRQChannelPreemptionPriority=0x02;
NVIC_InitStre.NVIC_IRQChannelSubPriority=0x01;
NVIC_InitStre.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStre);//初始化
TIM_ClearITPendingBit(TIM5,TIM_IT_Update);
TIM_ARRPreloadConfig(TIM5, ENABLE);//使能自动装载
TIM_ITConfig(TIM5,TIM_IT_Update,ENABLE);
TIM_ClearITPendingBit(TIM5,TIM_IT_Update);
TIM_Cmd(TIM5, ENABLE);//使能时钟,
}
//主触发器
void Tim4_init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStre;
NVIC_InitTypeDef NVIC_InitStre;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
TIM_ITConfig(TIM4,TIM_IT_Update,DISABLE);
TIM_Cmd(TIM4, DISABLE);
//计数频率100Hz=84/(TIM_Prescaler+1)/(TIM_Period+1)
TIM_TimeBaseInitStre.TIM_Prescaler=84-1;//定时器频率84M/(840)=1us
TIM_TimeBaseInitStre.TIM_Period=50000-1;//周期计数值500 T=200Hz=5ms
TIM_TimeBaseInitStre.TIM_ClockDivision=0x00;//不分频
TIM_TimeBaseInitStre.TIM_CounterMode=TIM_CounterMode_Up ;
TIM_TimeBaseInitStre.TIM_RepetitionCounter=0;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseInitStre);
TIM_SelectOutputTrigger(TIM4, TIM_TRGOSource_Enable);//设置输入触发源
TIM_SelectMasterSlaveMode(TIM4,TIM_MasterSlaveMode_Enable);//使能主从模式
NVIC_InitStre.NVIC_IRQChannel=TIM4_IRQn;
NVIC_InitStre.NVIC_IRQChannelPreemptionPriority=0x02;
NVIC_InitStre.NVIC_IRQChannelSubPriority=0x03;
NVIC_InitStre.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStre);//初始化
TIM_ClearITPendingBit(TIM4,TIM_IT_Update);
TIM_ARRPreloadConfig(TIM4, ENABLE);//使能自动装载
TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);
TIM_ClearITPendingBit(TIM4,TIM_IT_Update);
//TIM_Cmd(TIM4, ENABLE);//使能时钟,不要在这里使能
}
//我这里使用串口指令来使能定时器
Void Main_Time(vodi)
{
TIM_Cmd(TIM4 ENABLE);//在这里使能
}
//定时器5中断服务函数
void TIM5_IRQHandler(void)
{
if(TIM_GetITStatus(TIM5,TIM_IT_Update)==SET)
{
GPIO_WriteBit(GPIOA,GPIO_Pin_11,(BitAction)(1-GPIO_ReadOutputDataBit(GPIOA,GPIO_Pin_11)));//LED
TIM_ClearITPendingBit(TIM5,TIM_IT_Update);//清除中断
}
}
实验现象是,上电后,定时器5不被触发,led不闪烁
串口指令使能主定时器后,定时器5被触发,led闪烁
代码2:触发输出采用TIM_TRGOSource_OC3Ref
触发输入采用TIM_SlaveMode_Gated
//从定时器
void Tim5_init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStre;
NVIC_InitTypeDef NVIC_InitStre;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
TIM_ITConfig(TIM5,TIM_IT_Update,DISABLE);
TIM_Cmd(TIM5, DISABLE);
//计数频率100Hz=84/(TIM_Prescaler+1)/(TIM_Period+1)
TIM_TimeBaseInitStre.TIM_Prescaler=84-1;//定时器频率84M/(840)=1us
TIM_TimeBaseInitStre.TIM_Period=50000-1;//周期计数值500 T=200Hz=5ms
TIM_TimeBaseInitStre.TIM_ClockDivision=0x00;//不分频
TIM_TimeBaseInitStre.TIM_CounterMode=TIM_CounterMode_Up ;
TIM_TimeBaseInitStre.TIM_RepetitionCounter=0;
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseInitStre);
TIM_SelectSlaveMode(TIM5,TIM_SlaveMode_Gated);//从模式配置
TIM_SelectInputTrigger(TIM5,TIM_TS_ITR3);//设置输入触发源
//TIM_SelectMasterSlaveMode(TIM5,TIM_MasterSlaveMode_Enable);//使能主从模式
NVIC_InitStre.NVIC_IRQChannel=TIM5_IRQn;
NVIC_InitStre.NVIC_IRQChannelPreemptionPriority=0x02;
NVIC_InitStre.NVIC_IRQChannelSubPriority=0x01;
NVIC_InitStre.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStre);//初始化
TIM_ClearITPendingBit(TIM5,TIM_IT_Update);
TIM_ARRPreloadConfig(TIM5, ENABLE);//使能自动装载
TIM_ITConfig(TIM5,TIM_IT_Update,ENABLE);
TIM_ClearITPendingBit(TIM5,TIM_IT_Update);
TIM_Cmd(TIM5, ENABLE);//使能时钟 //中断配置
}
//主定时器
void Tim8_init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStre;
TIM_OCInitTypeDef TIM_OCInitStre;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);
PV_PEEP_IO_Init();//IO口初始化
//计数频率20kHz=168/(TIM_Prescaler+1)/(TIM_Period+1)
TIM_TimeBaseInitStre.TIM_Prescaler=0;//定时器频率168M/(0+1)
TIM_TimeBaseInitStre.TIM_Period=11200-1;//周期计数值 15k-11200 一个计数值 改成20kHz-8400
TIM_TimeBaseInitStre.TIM_ClockDivision=0x00;//不分频
TIM_TimeBaseInitStre.TIM_CounterMode=TIM_CounterMode_CenterAligned1;
TIM_TimeBaseInitStre.TIM_RepetitionCounter=0;
TIM_TimeBaseInit(TIM8, &TIM_TimeBaseInitStre);
TIM_OCInitStre.TIM_OCMode=TIM_OCMode_PWM1;
TIM_OCInitStre.TIM_Pulse=0;//占空比0%
TIM_OCInitStre.TIM_OCPolarity=TIM_OCPolarity_High ;
TIM_OCInitStre.TIM_OutputState=TIM_OutputState_Enable ;
TIM_OCInitStre.TIM_OCIdleState=TIM_OCIdleState_Reset ;
TIM_OC3Init(TIM8, &TIM_OCInitStre);//消音圈
TIM_SelectOutputTrigger(TIM8,TIM_TRGOSource_OC3Ref);//触发输出源OC3
TIM_SelectMasterSlaveMode(TIM8,TIM_MasterSlaveMode_Enable);//使能主从模式
TIM_CtrlPWMOutputs(TIM8, ENABLE);//高级定时器要加这个使能
TIM_OC3PreloadConfig(TIM8, TIM_OCPreload_Enable);
TIM_Cmd(TIM8, ENABLE);//使能时钟
}
//串口更改占空比
Void Set_CCR(void)
{
TIM8->CCR3=1000;
}
实验现象,开始占空比等于0,定时器5不被触发,led不闪烁;
使用串口发送指令,更改占空比,定时器5被触发,led闪烁