使用芯片:STM32F103RCT6
思路:定时器设置为1MHZ的计数频率,定时计数器增加一就是增加1us
① 首先设置为上升沿捕获,捕获上升沿记录此刻的时间计数值;
② 然后切换为下降沿捕获,捕获下降沿记录此刻的时间计数值;
③ 最后设置为上升沿捕获,捕获上升沿记录此刻的时间计数值;
对于16bit定时器,最大可计数0xFFFF,也就是65535us,那么:高电平持续的时间 = 定时器溢出计数 * 0xFFFF + 当前计数值
对于32bit定时器,最大可计数0xFFFFFFFF,也就是4294.967295s,这个时间足够测量脉冲宽度的了,那么:高电平持续的时间 = 当前计数值
高电平持续的时间 = ② - ①
周期 = ③ - ①
定时器配置
设置定时器2的计数频率为1MHz,输入捕获使用通道一,也就是PA0引脚,将PA0引脚设置为下拉模式,目的是为了在空闲时间保持信号稳定:
中断分组设置
代码配置
tim.c中添加如下代码:
- __IO uint32_t TIM2_TIMEOUT_COUNT = 0; ///< 定时器2定时溢出计数
- uint32_t TIM2_CAPTURE_BUF[3] = {0, 0, 0}; ///< 分别存储上升沿计数、下降沿计数、下个上升沿计数
- __IO uint8_t TIM2_CAPTURE_STA = 0xFF; ///< 状态标记
- /**
- * 设置TIM2输入捕获极性
- * @param TIM_ICPolarity:
- * TIM_INPUTCHANNELPOLARITY_RISING :上升沿捕获
- * TIM_INPUTCHANNELPOLARITY_FALLING :下降沿捕获
- * TIM_INPUTCHANNELPOLARITY_BOTHEDGE:上升沿和下降沿都捕获
- */
- inline void TIM2_SetCapturePolarity(uint32_t TIM_ICPolarity)
- {
- htim2.Instance->CCER &= ~(TIM_CCER_CC1P | TIM_CCER_CC1NP);
- htim2.Instance->CCER |= (TIM_ICPolarity & (TIM_CCER_CC1P | TIM_CCER_CC1NP));
- }
- /// 定时器2时间溢出回调函数
- void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
- {
- if (htim->Instance == htim2.Instance)
- {
- TIM2_TIMEOUT_COUNT++; // 溢出次数计数
- }
- }
- ///< 输入捕获回调函数
- void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
- {
- if (htim->Instance == htim2.Instance)
- {
- switch (TIM2_CAPTURE_STA)
- {
- case 1:
- {
- printf("准备捕获下降沿...\r\n");
- TIM2_CAPTURE_BUF[0] = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1) + TIM2_TIMEOUT_COUNT * 0xFFFF;
- TIM2_SetCapturePolarity(TIM_INPUTCHANNELPOLARITY_FALLING); // 设置为下降沿触发
- TIM2_CAPTURE_STA++;
- break;
- }
- case 2:
- {
- printf("准备捕获下个上升沿...\r\n");
- TIM2_CAPTURE_BUF[1] = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1) + TIM2_TIMEOUT_COUNT * 0xFFFF;
- TIM2_SetCapturePolarity(TIM_INPUTCHANNELPOLARITY_RISING); // 设置为上升沿触发
- TIM2_CAPTURE_STA++;
- break;
- }
- case 3:
- {
- printf("捕获结束...\r\n");
- printf("# end ----------------------------------------------------\r\n");
- TIM2_CAPTURE_BUF[2] = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1) + TIM2_TIMEOUT_COUNT * 0xFFFF;
- HAL_TIM_IC_Stop_IT(htim, TIM_CHANNEL_1); // 停止捕获
- HAL_TIM_Base_Stop_IT(&htim2); // 停止定时器更新中断
- TIM2_CAPTURE_STA++;
- break;
- }
- default:
- break;
- }
- }
- }
- ///< TIM2轮训状态切换
- inline void TIM2_Poll(void)
- {
- switch (TIM2_CAPTURE_STA)
- {
- case 0:
- {
- printf("# start ----------------------------------------------------\r\n");
- printf("准备捕获上升沿...\r\n");
- TIM2_TIMEOUT_COUNT = 0;
- __HAL_TIM_SET_COUNTER(&htim2, 0); // 清除定时器2现有计数
- memset(TIM2_CAPTURE_BUF, 0, sizeof(TIM2_CAPTURE_BUF)); // 清除捕获计数
- TIM2_SetCapturePolarity(TIM_INPUTCHANNELPOLARITY_RISING); // 设置为上升沿触发
- HAL_TIM_Base_Start_IT(&htim2); // 启动定时器更新中断
- HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1); // 启动捕获中断
- TIM2_CAPTURE_STA++;
- break;
- }
- case 4:
- {
- uint32_t high = TIM2_CAPTURE_BUF[1] - TIM2_CAPTURE_BUF[0];
- uint32_t cycle = TIM2_CAPTURE_BUF[2] - TIM2_CAPTURE_BUF[0];
- float frq = 1.0 / (((float)cycle) / 1000000.0);
- TIM2_CAPTURE_STA++;
- printf("\r\n\r\n");
- printf("################################# START #########################################\r\n");
- printf("高电平持续时间:%dms\r\n", high / 1000);
- printf("周期 :%dms\r\n", cycle / 1000);
- printf("频率 :%fHz\r\n", frq);
- printf("################################## END ##########################################\r\n\r\n");
- break;
- }
- default:
- break;
- }
- }
复制代码
main.c:
- int main()
- {
- HAL_Init();
- SystemClock_Config();
- MX_GPIO_Init();
- DEBUG_UART_Init();
- MX_TIM2_Init();
- printf("================================ 系统运行! ================================ \r\n");
- while(1)
- {
- TIM2_Poll();
- DEBUG_UART_RecvHandler();
- }
- }
复制代码
说明:串口一接串口调试助手,勾选发送新行,向单片机发送任意字符以此来启动输入捕获。
|