一、配置定时器为PWM产生
二、配置时钟树
三、定时器配置
四、配置完生成程序后,主程序里还要进行启动PWM就可以了
MX_TIM3_Init();
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2);//启动。置1 CCER的输出使能位bit4
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);//CCER的bit0
然后可以改变占空比了。
**特别注意:**占空比不能大于自动重载寄存器ARR的值,不然输出的都是高电平。这个问题整了一天。
五、程序分析
/* TIM3 init function */
static void MX_TIM3_Init(void)
{
TIM_MasterConfigTypeDef sMasterConfig;
TIM_OC_InitTypeDef sConfigOC;
//------------------实际是调用TIM_Base_SetConfig配置定时器,上一篇分析过--
htim3.Instance = TIM3;
htim3.Init.Prescaler = 71;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 99;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
//---------------------这个是默认的,不管-------------------------------
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
//----------------配置输出比较部分-- 上图5部分-------------------------------
sConfigOC.OCMode = TIM_OCMODE_PWM1;//输出模式PWM1
sConfigOC.Pulse = 80;//占空比
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;//高电平极性
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
//----------------------------------------------------------------------------------
sConfigOC.Pulse = 50;
if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
HAL_TIM_MspPostInit(&htim3);//初始化引脚IO
}
初始化PWM通道HAL_TIM_PWM_ConfigChannel------>调用
case TIM_CHANNEL_1:
{
assert_param(IS_TIM_CC1_INSTANCE(htim->Instance));
/* Configure the Channel 1 in PWM mode */
TIM_OC1_SetConfig(htim->Instance, sConfig);
/* Set the Preload enable bit for channel1 */
htim->Instance->CCMR1 |= TIM_CCMR1_OC1PE;//比较模式寄存器CCMR1的bit3位OC1PE置1,写入到CCR1的值在事件更新时,才会传到影子寄存器。清0则写入CCR1的值会马上起作用
/* Configure the Output Fast mode */
htim->Instance->CCMR1 &= ~TIM_CCMR1_OC1FE;//配置CCMR1的bit2位,输出比较快速使能
htim->Instance->CCMR1 |= sConfig->OCFastMode;
}
break;
//--------------------------------------------------------------------------------
void TIM_OC1_SetConfig(TIM_TypeDef *TIMx, TIM_OC_InitTypeDef *OC_Config)
{
uint32_t tmpccmrx = 0U;
uint32_t tmpccer = 0U;
uint32_t tmpcr2 = 0U;
/* Disable the Channel 1: Reset the CC1E Bit */
TIMx->CCER &= ~TIM_CCER_CC1E;//关通道 CCER bit0清0
/* 读出三个寄存器的值 */
tmpccer = TIMx->CCER;
tmpcr2 = TIMx->CR2;
tmpccmrx = TIMx->CCMR1;
/* Reset the Output Compare Mode Bits */
tmpccmrx &= ~TIM_CCMR1_OC1M;//复位CCMR1的bit6:4
tmpccmrx &= ~TIM_CCMR1_CC1S;//复制CCMR1的bit1:0
/* Select the Output Compare Mode */
tmpccmrx |= OC_Config->OCMode;//配置OC1M为 110 PWM1模式
/* Reset the Output Polarity level */
tmpccer &= ~TIM_CCER_CC1P;//配置输出极性 CCER的 CC1P位
tmpccer |= OC_Config->OCPolarity;
if(IS_TIM_CCXN_INSTANCE(TIMx, TIM_CHANNEL_1))//如果是定时器1的123通道,还要设置互补输出
{
assert_param(IS_TIM_OCN_POLARITY(OC_Config->OCNPolarity));
/* Reset the Output N Polarity level */
tmpccer &= ~TIM_CCER_CC1NP;
/* Set the Output N Polarity */
tmpccer |= OC_Config->OCNPolarity;
/* Reset the Output N State */
tmpccer &= ~TIM_CCER_CC1NE;
}
if(IS_TIM_BREAK_INSTANCE(TIMx))//如果是定时器1,还要设置CR2的bit8 bit9 死区控制
{
/* Check parameters */
assert_param(IS_TIM_OCNIDLE_STATE(OC_Config->OCNIdleState));
assert_param(IS_TIM_OCIDLE_STATE(OC_Config->OCIdleState));
/* Reset the Output Compare and Output Compare N IDLE State */
tmpcr2 &= ~TIM_CR2_OIS1;
tmpcr2 &= ~TIM_CR2_OIS1N;
/* Set the Output Idle state */
tmpcr2 |= OC_Config->OCIdleState;
/* Set the Output N Idle state */
tmpcr2 |= OC_Config->OCNIdleState;
}
/* 把设置好的值写入这4个寄存器 */
TIMx->CR2 = tmpcr2;
TIMx->CCMR1 = tmpccmrx;
TIMx->CCR1 = OC_Config->Pulse;//占空比
TIMx->CCER = tmpccer;
}
流程图如下:
需要改变占空比的,直接调用
__HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_1,dutycycle);
改变寄存器CCR1,改变的值是立即生效还是下一个周期生效取决于CCMR1的OC1PE位
while (1)
{
while(dutycycle<100)
{
dutycycle+=10;
__HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_1,dutycycle);
HAL_Delay(1);
}
while(dutycycle)
{
dutycycle-=10;
__HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_1,dutycycle);
HAL_Delay(1);
}
}