STM32 高级定时器 COM事件

STM32高级定时器COM事件-软件方式产生

STM32的COM事件只针对高级定时器TIM1和TIM8有效,主要是用来BLDC方波(6步梯形波)控制中更新3路PWM占空比,达到3相同时换相(即同时更新占空比),如果采用普通的更新占空比,则会造成3个通道先后延迟;这里BLDC控制采用H_PWM-L_ON(即上MOS用PWM,下MOS用高低(开关)电平,实际采用PWM占比100%),

设计思路是:换相更新3路占空比,然后在另一处产生COM事件使得前面设置的占空比生效

COM事件产生有2中方式:通过函数TIM_SelectCOM()来选择

  1. 软件TIM_GenerateEvent(TIM8,TIM_EventSource_COM);
  2. 硬件TRGI自动触发

硬件TRGI又由什么条件产生呢:看下图

红色方框是TRGI的输入源,选择器前面的都是TRGI的来源,我们追踪可以看到相关的寄存器TIMx_SMCR

关于硬件方式产生COM事件请看另一篇文章,这里不做过多说明

1.涉及到的寄存器有:

TIMx_CR2

说明一下:CCPUS位:更新方式选择,一般选择CCUS=1,软件和硬件都能更新

2.使用常见的换向方式见下表格,这里采用有感HALL换相触发

换相表:546231

5:导通相Q3、Q6

4:导通相Q3、Q2

6:导通相Q5、Q2

2:导通相Q5、Q4

3:导通相Q1、Q4

1:导通相Q1、Q6

设计步骤

  1. TIM1/TIM8定时器初始化,比普通初始化加入以下项

TIM_CCPreloadControl(TIM8,ENABLE);//使能捕获比较预装载控制

TIM8->CCER&=0x0000;//关闭6路PWM输出或者其他库函数TIM_CCxCmd()等实现关闭功能

//COM中断配置(不必须的)

       NVIC_InitStre.NVIC_IRQChannel=TIM8_TRG_COM_TIM14_IRQn;

       NVIC_InitStre.NVIC_IRQChannelPreemptionPriority=0x02;

       NVIC_InitStre.NVIC_IRQChannelSubPriority=0x01;

       NVIC_InitStre.NVIC_IRQChannelCmd=ENABLE;

       NVIC_Init(&NVIC_InitStre);//初始化

       TIM_ITConfig(TIM8,TIM_IT_COM,ENABLE);//使能TIM1/8的COM触发中断

2.6路IO口初始化,配置高级定时器

3.HALL定时器和IO初始化

4.HALL的输入捕获中断服务函数编写

5.COM事件触发的中断服务函数编写(可不要)

这里只说明设计思路和算法过程,详细的关于BLDC的算法设计请参见其他资料

HALL的输入捕获中断服务函数,完成功能:

      

根据hall读取值判断换相顺序,在对应的换相中,更新3路占空比(这时候还没有生效)

Switch(ReadHallVal)

{

Case 5:更新3路占空比;TIM8->CCER=SetVal_DISABLE_ENABLE; break;

Case 4:更新3路占空比;TIM8->CCER= SetVal_DISABLE_ENABLE; break;

Case 3:更新3路占空比;TIM8->CCER= SetVal_DISABLE_ENABLE; break;

Case 2:更新3路占空比;TIM8->CCER= SetVal_DISABLE_ENABLE; break;

Case 6:更新3路占空比;TIM8->CCER= SetVal_DISABLE_ENABLE; break;

Case 1:更新3路占空比;TIM8->CCER= SetVal_DISABLE_ENABLE; break;

}

更新占空比值可用TIMx_CCRx=Num;或函数TIM_SetCompare1()等

SetVal_DISABLE_ENABLE值是换相对应的选择通道,具体如何设定参见TIM8->CCER寄存器,就是配置相关的通道使能或失能

TIM_GenerateEvent(TIM8,TIM_EventSource_COM);//完成COM事件的产生,设定的占空比真正生效,当然生效还可以由硬件自动产生(TRGI)

这个时候就会触发TIM8的COM事件中断(如果配置中断的话),中断可要可不要,如果没有对应需要处理的任务,可以不加

//TIM8 COM事件触发实验,中断服务函数

void TIM8_TRG_COM_TIM14_IRQHandler(void)

{

//LED电平翻转,用来对照

}

演示代码:我们用软件方式产生COM事件来更新占空比

3.对互补通道PWM输出,定时器TIM8

#define CH1_ON_CH23_OFF (0x0444|(0x001<<0)) //CH1开 CH2关 CH3关

#define CH2_ON_CH13_OFF (0x0444|(0x001<<4)) //CH1关 CH2开 CH3关

#define CH3_ON_CH12_OFF (0x0444|(0x001<<8)) //CH1关 CH2关 CH3开

//IO口初始化

       GPIO_InitTypeDef GPIO_InitStre;

      

       RCC_AHB1PeriphClockLPModeCmd(RCC_AHB1Periph_GPIOA|RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOC, ENABLE);

      

       GPIO_InitStre.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8;

       GPIO_InitStre.GPIO_Mode=GPIO_Mode_AF;

       GPIO_InitStre.GPIO_OType=GPIO_OType_PP;

       GPIO_InitStre.GPIO_PuPd=GPIO_PuPd_DOWN;

       GPIO_InitStre.GPIO_Speed=GPIO_Speed_2MHz;

       GPIO_Init(GPIOC, &GPIO_InitStre);

      

       GPIO_InitStre.GPIO_Pin=GPIO_Pin_14|GPIO_Pin_15;

       GPIO_InitStre.GPIO_Mode=GPIO_Mode_AF;

       GPIO_InitStre.GPIO_OType=GPIO_OType_PP;

       GPIO_InitStre.GPIO_PuPd=GPIO_PuPd_NOPULL;

       GPIO_InitStre.GPIO_Speed=GPIO_Speed_2MHz;

       GPIO_Init(GPIOB, &GPIO_InitStre);

      

       GPIO_InitStre.GPIO_Pin=GPIO_Pin_7;

       GPIO_InitStre.GPIO_Mode=GPIO_Mode_AF;

       GPIO_InitStre.GPIO_OType=GPIO_OType_PP;

       GPIO_InitStre.GPIO_PuPd=GPIO_PuPd_NOPULL;

       GPIO_InitStre.GPIO_Speed=GPIO_Speed_2MHz;

       GPIO_Init(GPIOA, &GPIO_InitStre);

      

         /* Connect TIM3 pins to AF2 */ 

       GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_TIM8);

       GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_TIM8);

       GPIO_PinAFConfig(GPIOC, GPIO_PinSource8, GPIO_AF_TIM8);

      

       GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_TIM8);

       GPIO_PinAFConfig(GPIOB, GPIO_PinSource14, GPIO_AF_TIM8);

       GPIO_PinAFConfig(GPIOB, GPIO_PinSource15, GPIO_AF_TIM8);

       TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStre;

       TIM_OCInitTypeDef TIM_OCInitStre;

       TIM_BDTRInitTypeDef     TIM_BDTRInitStructure;

       //定时器初始化

       RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);

       PV_PEEP_IO_Init();//IO口初始化

      

       //计数频率20kHz=168/(TIM_Prescaler+1)/(TIM_Period+1)

       TIM_TimeBaseInitStre.TIM_Prescaler=100-1;//定时器频率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=0x00;

       TIM_TimeBaseInit(TIM8, &TIM_TimeBaseInitStre);

      

       TIM_OCInitStre.TIM_OCMode=TIM_OCMode_PWM1;

       TIM_OCInitStre.TIM_OCPolarity=TIM_OCPolarity_High ;

       TIM_OCInitStre.TIM_OCIdleState=TIM_OCIdleState_Reset ;

       TIM_OCInitStre.TIM_OutputState=TIM_OutputState_Enable;

      

       TIM_OCInitStre.TIM_OCNPolarity=TIM_OCPolarity_High;

       TIM_OCInitStre.TIM_OCNIdleState=TIM_OCIdleState_Reset;

       TIM_OCInitStre.TIM_OutputNState=TIM_OutputState_Enable ;

             

       TIM_OCInitStre.TIM_Pulse=0;//占空比0%

       TIM_OC1Init(TIM8, &TIM_OCInitStre);//消音圈

      

       TIM_OCInitStre.TIM_Pulse=0;//占空比0%

       TIM_OC2Init(TIM8, &TIM_OCInitStre);//消音圈

      

       TIM_OCInitStre.TIM_Pulse=0;//占空比0%

       TIM_OC3Init(TIM8, &TIM_OCInitStre);//消音圈

      

       TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;

  TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;

  TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;

  TIM_BDTRInitStructure.TIM_DeadTime = 132;//

       TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Disable;

  TIM_BDTRConfig(TIM8, &TIM_BDTRInitStructure);

      

       TIM_OC1PreloadConfig(TIM8, TIM_OCPreload_Enable);

       TIM_OC2PreloadConfig(TIM8, TIM_OCPreload_Enable);

       TIM_OC3PreloadConfig(TIM8, TIM_OCPreload_Enable);

       TIM_CtrlPWMOutputs(TIM8, ENABLE);//高级定时器要加这个使能

       TIM_Cmd(TIM8, ENABLE);//使能时钟

       TIM_GenerateEvent(TIM8, TIM_EventSource_Update);

       TIM8->CCER = 0x0444;//失能3对通道输出PWM

这里使用串口中断接收数据,来模拟6步换相

void USART1_IRQHandler( void )//串口1中断

{

       u8 CHannel = 0;

      

       //接收

       if( USART_GetITStatus( USART1, USART_IT_RXNE ) != RESET )

       {            

                CHannel = USART_ReceiveData( USART1 );

       }

switch(CHannel)

{

Case1:TIM8->CCR1=5000;TIM8->CCR2=0;TIM8->CCR3=0;TIM8->CCER=CH2_ON_CH13_OFF; TIM_GenerateEvent(TIM8, TIM_EventSource_Update);break;//TIM8->CCER=0x0445

case2:TIM8->CCR1=0;TIM8->CCR2=5000;TIM8->CCR3=0;TIM8->CCER=CH2_ON_CH13_OFF; TIM_GenerateEvent(TIM8, TIM_EventSource_Update);break;

case3:TIM8->CCR1=0;TIM8->CCR2=0;TIM8->CCR3=5000;TIM8->CCER=CH3_ON_CH12_OFF; TIM_GenerateEvent(TIM8, TIM_EventSource_Update);break;

default:;break;

}

TIM_GenerateEvent(TIM8,TIM_EventSource_COM);//产生COM事件

}

为什么要加TIM_GenerateEvent(TIM8, TIM_EventSource_Update);是为了让计数器清0,即TIM8->CNT=0

实验现象:

PWM输出通道开始占空比=0,外部串口产生事件触发对应通道占空比更新,计数;占空比=设定值,示波器波形如下

图1是硬件自动更新占空比比较值,可以看到通道切换间由很明显的延迟

图1

图2是软件产生的COM事件来更新占空比比较值,通道切换几乎没有延迟

 

图2

  • 10
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值