4.1.3 输出通道初始化
输出通道初始化,主要是配置输出的一些参数,这里主要关注TIM_OCMode(模式)与TIM_OCPolarity(极性),这两个参数是配合使用的:
PWM模式1
向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为有效电平,否则为无效电平;
向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为无效电平,否则为有效电平。
PWM模式2
向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为无效电平,否则为有效电平;
向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为有效电平,否则为无效电平。
这里的有效电平又是什么意思呢?怎么算有效电平?它就是通过极性来配置的:
输出High模式:有效电平为高电平
输出Low模式:有效电平为低电平
对比着再来看这张图:
当CNT的计数值小于CCR时,即t1这个时间段,输出有效电平(TIM_OCMode_PWM1模式),而有效电平是高电平(极性为TIM_OCPolarity_High),所以PWM的IO逻辑在t1这个时间段输出了高电平。
输出通道的配置如下:
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); /*使能TIM3在CCR1上的预装载寄存器*/TIM_ARRPreloadConfig(TIM3,ENABLE);/*ARPE使能:使能控制寄存器CR的第8位:ARPR, Auto-reload preload enable*/TIM_Cmd(TIM3, ENABLE); /*使能TIM3:使能控制寄存器CR的第0位:CEN, counter enable*/
关于配置CCMR1、CCER寄存器
CCMR1:
CCER:
TIM_OC1Init函数对应于输入通道的初始化,其实就是操作CCMR1、CCER等寄存器:
tmpccmrx = TIMx->CCMR1;/* 获取TIMx CCMR1 寄存器的值 */ tmpccmrx &= (uint16_t)~TIM_CCMR1_OC1M; /* 复位输出比较模式OC1M位 */ tmpccmrx &= (uint16_t)~TIM_CCMR1_CC1S; tmpccmrx |= TIM_OCInitStruct->TIM_OCMode;/* 设置为输出比较模式 */ tmpccer &= (uint16_t)~TIM_CCER_CC1P; /* 复位输出极性CC1P */ tmpccer |= TIM_OCInitStruct->TIM_OCPolarity; /* 设置输出极性 */ tmpccer |= TIM_OCInitStruct->TIM_OutputState; /* 设置输出状态 */ if((TIMx == TIM1) || (TIMx == TIM8)) /*gaoji定时器的特殊配置*/ { //省略。。。 } TIMx->CR2 = tmpcr2; /* 写数据到TIMx的CR2寄存器 */ TIMx->CCMR1 = tmpccmrx; /* 写数据到TIMx的CCMR1寄存器 */ TIMx->CCR1 = TIM_OCInitStruct->TIM_Pulse;/* 设置CCR1寄存器 */ TIMx->CCER = tmpccer; /* 写数据到TIMx的CCER寄存器 */}4.2 动态改变占空比
占空比是通过修改CCR寄存器的值进行修改的,如果定时器初始化时只设置了1次CCR的值,那么会输出恒定占空比的PWM波;如果在定时器运行的时候,动态修改CCR的值,则可以实现PWM占空比的动态调整。
如下程序,实现了每隔10ms对占空比进行一次修改,每次将高电平计数值增加5,当增大道500(占空比100%)时,再逐渐减小到0(占空比0%),不断循环。
if(dir) { led0pwmval+=5; //dir==1 led0pwmval递增 } else { led0pwmval-=5; //dir==0 led0pwmval递减 } if(led0pwmval>500) { dir=0; //led0pwmval到达500后,方向为递减 } if(led0pwmval==0) { dir=1; //led0pwmval递减到0后,方向改为递增 }
TIM_SetCompare1(TIM3,led0pwmval); /*CCR 修改比较值(占空比)*/}5 测试效果
将程序下载到板子,我用的一块STM32F407的板,A6引脚上接了一个LED灯,实际效果的LED逐渐变亮,再逐渐变暗,依次循环。
再通过逻辑分析仪来查看实际的输出波形,如下图,测得的pwm周期0.5ms(频率2kHz),与软件中设定的一致。
在某一时刻,脉宽55us。
在另一时刻,脉宽0.365ms,即实现了PWM脉宽的动态调整。