PWM模式下可以产生一个由ARR(自动重装载寄存器)寄存器确定频率,CCR(捕获比较寄存器)寄存器确定占空比的信号。
在设置时自动装装载的预装载位和捕获比较寄存器的预装载位。这样只有发送更新事件预装载寄存器的值传到影子寄存器,所以开始计数前通过设置EGR寄存器的UG位来产生一个更新事件初始化定时器。
我们这里讲解的就选取向上计数。都是一样的道理。
还是首先是一个时基单元的参数配置。直接看初始化函数的关键代码。
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle)
{
if(tim_baseHandle->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspInit 0 */
/* USER CODE END TIM3_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_TIM3_CLK_ENABLE();
/* Peripheral interrupt init */
HAL_NVIC_SetPriority(TIM3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM3_IRQn);
/* USER CODE BEGIN TIM3_MspInit 1 */
/* USER CODE END TIM3_MspInit 1 */
}
}
void TIM_Base_SetConfig(TIM_TypeDef *TIMx, TIM_Base_InitTypeDef *Structure)
{
uint32_t tmpcr1 = 0;
tmpcr1 = TIMx->CR1;
/* Set TIM Time Base Unit parameters ---------------------------------------*/
if (IS_TIM_COUNTER_MODE_SELECT_INSTANCE(TIMx))
{
/* Select the Counter Mode */
tmpcr1 &= ~(TIM_CR1_DIR | TIM_CR1_CMS);
tmpcr1 |= Structure->CounterMode;
}
if(IS_TIM_CLOCK_DIVISION_INSTANCE(TIMx))
{
/* Set the clock division */
tmpcr1 &= ~TIM_CR1_CKD;
tmpcr1 |= (uint32_t)Structure->ClockDivision;
}
TIMx->CR1 = tmpcr1;
/* Set the Autoreload value */
TIMx->ARR = (uint32_t)Structure->Period ;
/* Set the Prescaler value */
TIMx->PSC = (uint32_t)Structure->Prescaler;
if (IS_TIM_REPETITION_COUNTER_INSTANCE(TIMx))
{
/* Set the Repetition Counter value */
TIMx->RCR = Structure->RepetitionCounter;
}
/* Generate an update event to reload the Prescaler
and the repetition counter(only for TIM1 and TIM8) value immediatly */
TIMx->EGR = TIM_EGR_UG;
}
所以初始化函数主要是打开了time外设时钟,设置了中断。并且将配置参数写入寄存器,通过EGR的UG位触发一个更新时间去写到影子寄存器。这就更新了定时器。
我们从名字得出这个配置就是配置时钟的。我们去看一下
可以看出先是清除了四个位,功能分别是关闭从模式(若CEN==1,预分频器时钟为内部时钟),内部触发0(用于同步计数器触发输入),外部触发预分频。
我们的参数满足第一个case条件,将低三位写入了0,查手册可以得知就是关闭从模式(若CEN==1,预分频器时钟为内部时钟),所以我们可以直接用了内部时钟。
if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
{
Error_Handler();
}
看出这个作用,初始化需要的中断,DMA,GPIO和时钟,因为之前已经初始化了,所以这里不再初始化,下一步又把时基单元配置了下,觉得这里配置是基单元有点重复,可以删除一个。
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
这个是关于主模式的设置,因为我们没有用到定时器去触发定时器,所以简单看下就好,
先是清除了MMS位,然后与等于0x0000(宏定义),这样查手册看寄存器得知EGR的UG位被用于作为触发输出。
然后清除了MSM位,这就被设置了主从模式无作用。
下面就是关键部分的代码了。
因为PWM是一个输出,所以我们配置了输出通道的参数。
初始化函数是一个多分支语句,我们看一个即可。都是一样的操作。
首先是失能了通道x的输出,使用三个变量得到了CCER,CR2,CCMR2的寄存器值。
然后清除了两个控制位之后配置为PWM模式1(在向上计数时,一旦TIMx_CNT<TIMx_CCRx时通道1为有效电平,否则为无效电平)
通道3输出使能。
这是关于高级定时器的,没有用到。
这里三条代码都是写入到寄存器,还有一个就是设置了Pulse的值。设置了CCRx的值,
回到case条件配置了通道x的预装载使能和快速使能。
HAL_TIM_MspPostInit(&htim3);最后的这句代码就是GPIO的配置了。