高级定时器输出PWM
主频72M,输出一个频率为1K,占空比为30%的PWM
重要参数说明
TIM_TimeBaseInitStructure.TIM_Period=100-1; 周期或叫重装值
TIM_TimeBaseInitStructure.TIM_Prescaler = 720-1; 预分频
TIM_OCInitStructure.TIM_Pulse = 30; 比较值
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; 向上计数
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; PWM模式1
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; 高电平是正极性
前三个数据和频率占空比相关
频率=Clock/((Prescaler+1)*(Period+1))=72M/(720*100)=1K
占空比=Pulse/(Period+1)=30/100=30%
后三个和输出电平极性相关
如上配置时
定时器CNT计数为0 - 99
0 - 29为高电平
30 - 99为低电平
仅改变一个参数,波形产生的变化
向下计数对波形的影响:先出现低电平 占空比不变
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Down;
99 - 30为低电平
29 - 0为高电平
PWM模式2对波形的影响: 和PWM模式1互补关系 改变占空比
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
0 - 29为低电平
30 - 99为高电平
低电平是正极性对波形的影响: 极性相反,互补关系
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
0 - 29为低电平
30 - 99为高电平
实时改变频率、占空比
直接对寄存器赋值就可以改变三个参数
Period周期(重装值):TIM1->ATRLR=100-1;
Prescaler预分频系数: TIM1->PSC=720-1;
Pulse比较值:TIM1->CH1CVR=30; CH1CVR表示通道1,不同通道数字不同,如CH2CVR表示通道2
3个参数都不能超过16位,最大65535
暂停PWM输出,强制拉高拉低
修改PWM模式就可以强制拉高拉低
使用这个库函数可以实现模式的切换
void TIM_ForcedOC1Config(TIM_TypeDef *TIMx, uint16_t TIM_ForcedAction)
其中OC1的1表示通道1,其他通道有各自的函数
强制拉高拉低模式:
TIM_ForcedAction_Active
TIM_ForcedAction_InActive
强制拉高拉低的电平仅和极性参数有关,当配置为TIM_OCPolarity_High则Active为高,InActive为低。反之则反之。
TIM_ForcedOC1Config(TIM1,TIM_ForcedAction_Active);
恢复输出PWM模式:
TIM_OCMode_PWM1
TIM_OCMode_PWM2
与之前配置的模式一致即可
TIM_ForcedOC1Config(TIM1,TIM_OCMode_PWM1);
其他通道TIM_ForcedOC2Config,TIM_ForcedOC3Config,TIM_ForcedOC4Config用法相似。
其他模式:
其中常用的4种上面已经说明,另外4种模式补充说明一下
1. TIM_OCMode_Timing 冻结 保持实时的输出电平不再变化。
2. TIM_OCMode_Active
3. TIM_OCMode_Inactive 和强制拉高拉低的2个模式最终效果一致,时间上会等到计数值CNT=比较值CH1CVR时才强制拉高拉低,之后不变。
4. TIM_OCMode_Toggle 翻转 当计数值CNT=比较值CH1CVR时,翻转输出电平。当极性配置为TIM_OCPolarity_High初始状态是低电平,与计数方向无关。
PWM互补输出
互补输出的意思是OC1和OC1N配置的极性相同时,输出高低电平正好相反。若极性相反,则输出相同。
死区时间
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; Tdts大小设置(= 1/2/4 * TCK)
TIM_BDTRInitStructure.TIM_DeadTime = 0xFF;死区时间设置
DeadTime(如0xFF)的单位是Tdts(如1*TCK),Tdts的单位是定时器时钟(如72M)。为了死区时间有足够大的范围,配置是分区间的。如上配置时,实际的死区时间为0x3F0/72M=14us
0-0x7F (0-0x7F)*Tdts 0-0x7F
0x80-0xBF 后5位(0-0x3F + 0x40 )*2* Tdts 0x80-0xFE
0xC0-0xDF 后4位(0-0x1F + 0x20 )*8* Tdts 0x100-0x1F8
0xE0-0XFF 后4位(0-0x1F + 0x20 )*16* Tdts 0x200-0x3F0
当定时器的输入时钟为72M时,两个参数设置为TIM_CKD_DIV4和0xFF,这时主频为72M的最大死区时间=0x3F0*4/72M=56us。
停止互补PWM,输出固定高低电平
单个PWM中的方法依旧管用,但是有一定局限性。此处使用设置空闲状态,可以独立设置2个停止时的输出电平。
配置参数修改:
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
配置空闲状态电平,Set为高电平,Reset为低电平,和极性、PWM模式等参数无关。
反向的参数中有个N,和正向的参数不一样,赋值时要注意
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
使能空闲状态
TIM_BDTRInitStructure.TIM_AutomaticOutput=TIM_AutomaticOutput_Disable;
关闭自动置位MOE,后面MOE作为PWM的开关
停止PWM,输出设定电平:
TIM1->BDTR&=~0x8000;
清零MOE位,进入空闲状态,输出设定电平
恢复PWM输出:
TIM1->BDTR|=0x8000;
MOE置1,OCx、OCxN正常输出PWM
刹车功能
配置BKIN输入引脚,比如TIM1的PB12配置为下拉输入,刹车输入的极性配置为高电平
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable; 使能刹车功能
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High; 刹车极性为高电平
当PB12输入高电平时,PWM停止输出,进入空闲状态,如果开启自动置位MOE位,则当PB12输入恢复为低时,会继续PWM输出,如果关闭(Disable)则不会自动恢复输出PWM。
TIM_BDTRInitStructure.TIM_AutomaticOutput=TIM_AutomaticOutput_Enable;
初始化代码
void TIM1_OC1_PWM_Init(u32 arr,u32 psc , u32 CCR1_Val )
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource8,GPIO_AF_TIM1);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA,&GPIO_InitStructure);
TIM_TimeBaseStructure.TIM_Prescaler=psc;
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period=arr;
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; //反向输出
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OCInitStructure.TIM_Pulse = CCR1_Val;// channel 1
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset; //反向输出
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM1,ENABLE);
TIM_Cmd(TIM1, ENABLE); // 使能
TIM_CtrlPWMOutputs(TIM1, ENABLE);
}