因为项目需要,最近重新拾起来STM32,正好趁着这个机会好好的梳理下遇到的知识细节。
参考链接
【 https://blog.csdn.net/qq86376032/article/details/80496853 】
【 https://cstriker1407.info/blog/stm32-timer-ti1fp1-ti2fp2/ 】
STM32的硬件定时器有个 PWM输入 模式,可以快速的检测PWM频率和占空比,不过缺点是需要占用定时器的两个通道,这里简单的笔记下如何通过STM32CubeMX来使用该功能。
假如我们要使用TIM2的channel1作为PWM输入端口,在使用PWM输入模式下,channel2作为channel1的配对端口,也会被占用。
最方便配置如下图,直接设置Combined Channels选项,如下图:
此时可以发现channel1,channel2都不可编辑,而且各类配置已经配置好了。
然后我们使能中断响应处理,如下图:
我们保存配置,IDE会自动生成代码,此时就可以看到IDE自动生成了如下定时器初始化代码:
static void MX_TIM2_Init(void) { TIM_SlaveConfigTypeDef sSlaveConfig = {0}; TIM_IC_InitTypeDef sConfigIC = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; htim2.Instance = TIM2; htim2.Init.Prescaler = 83; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 4294967295; htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; if (HAL_TIM_IC_Init(&htim2) != HAL_OK) { Error_Handler(); } sSlaveConfig.SlaveMode = TIM_SLAVEMODE_RESET; sSlaveConfig.InputTrigger = TIM_TS_TI1FP1; sSlaveConfig.TriggerPolarity = TIM_INPUTCHANNELPOLARITY_RISING; sSlaveConfig.TriggerPrescaler = TIM_ICPSC_DIV1; sSlaveConfig.TriggerFilter = 0; if (HAL_TIM_SlaveConfigSynchro(&htim2, &sSlaveConfig) != HAL_OK) { Error_Handler(); } sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING; sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI; sConfigIC.ICPrescaler = TIM_ICPSC_DIV1; sConfigIC.ICFilter = 0; if (HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_1) != HAL_OK) { Error_Handler(); } sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING; sConfigIC.ICSelection = TIM_ICSELECTION_INDIRECTTI; if (HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_2) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK) { Error_Handler(); } }
和一个默认的中断响应函数:
void TIM2_IRQHandler(void) { /* USER CODE BEGIN TIM2_IRQn 0 */ /* USER CODE END TIM2_IRQn 0 */ HAL_TIM_IRQHandler(&htim2); /* USER CODE BEGIN TIM2_IRQn 1 */ /* USER CODE END TIM2_IRQn 1 */ }
此时我们增加自己的中断业务响应函数:
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) { chan1_cap_data = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); } else if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2) { chan2_cap_data = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2); } else { 。。。 } 。。。 }
那么PWM信息就可以计算为:
/* tim_ticket_pre_second为定时器频率,计算公式为: HAL_RCC_GetPCLK1Freq() * 2 / (htim2.Init.Prescaler + 1) */ duty_circle = 100 * chan2_cap_data / chan1_cap_data; frequency = tim_ticket_pre_second / chan1_cap_data;
发表评论