STM32F407 定时器输入捕获

定时器输入捕获

插播一条串口

之前学串口部分的时候,偷懒没学用printf()输出,今天要打印高电平持续时间的时候,直接重写了fputc函数。结果一直困在printf的死循环里出不来。找了半天发现居然是!!对printf重定向后,避免使用半主机模式而导致库函数程序无法运行,使用微库Micro LIB可以避免半主机模式,在keil中点击Options for Target…,勾选Use Micro LIB,点击OK即可。
在这里插入图片描述
勾选完这个选项之后,我们发现串口可以用printf()语句顺利的输出啦。

定时器捕获的原理

关于原理部分可以参考一篇博客链接: link。里面详细介绍了各个寄存器的作用。

代码实现

基本框架

首先定义四个变量,状态变化时的一个计数值、存储计数器的记录值、计数器溢出的个数和最后总的高电平的时间。

uint8_t TIM5_CH1_Edge=0;  //状态变化时,计数值
uint32_t TIM5_CH1_VAL=0;  //储存计数器的记录值
uint32_t TIM5_CH1_OVER=0; //计数器溢出的个数
uint32_t time;   //高电平持续时间

然后在主函数前面打开定时器的中断以及打开输入捕获。

HAL_TIM_Base_Start_IT(&htim5);	//打开定时器中断
HAL_TIM_IC_Start_IT(&htim5,TIM_CHANNEL_1);  //打开输入捕获

在主函数的循环中开始编写,如果状态变化两次,即一次高电平跳变和一次低电平跳变。那么就进入下一轮的捕获当中,将状态变化时的计数值置零。然后用溢出值乘以重装载值加上记录值就是高电平持续的时间。然后在重新打开输入捕获。

if(TIM5_CH1_Edge == 2)
		{
			TIM5_CH1_Edge = 0;  //重新开始捕获
			time = TIM5_CH1_VAL + TIM5_CH1_OVER*0xffff;
			printf("高电平持续时间为 %d ms\r\n", time/1000);
			HAL_TIM_IC_Start_IT(&htim5,TIM_CHANNEL_1);  //打开输入捕获
		}

然后编写定时器溢出中断回调函数。当定时器出现溢出时,计数器溢出的个数加一。

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim == &htim5)
	{
		if(TIM5_CH1_Edge == 1)
		{
			TIM5_CH1_OVER++;  //定时器溢出值增加
		}
	}
}

然后是捕获跳变的中断函数。如果捕获到上升沿跳变,则状态变化的计数器加一,并且定时器的溢出值清零。同时将捕获极性设置为下降沿,然后将计数器的值设置为0。
如果捕获的时下降沿则,马上关闭定时器,并且将状态变化的计数器再加一,即为二。同时读取捕获通道的值。在设置捕获通道的极性为上升沿捕获。

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
	if(htim == &htim5)
	{
		if(TIM5_CH1_Edge == 0) //捕获到上升沿
		{
			TIM5_CH1_Edge++;  //进入捕获下降沿状态
			TIM5_CH1_OVER = 0;  //定时器溢出值清零
			__HAL_TIM_SET_CAPTUREPOLARITY(&htim5,TIM_CHANNEL_1,TIM_ICPOLARITY_FALLING); //设置捕获极性为下降沿
			__HAL_TIM_SET_COUNTER(&htim5,0);  //设置定时器CNT计数器的值为0
		}
		else //捕获到下升沿
		{
			HAL_TIM_IC_Stop_IT(&htim5,TIM_CHANNEL_1); //关闭定时器5
			TIM5_CH1_Edge++;  //进入到主函数状态
			TIM5_CH1_VAL = HAL_TIM_ReadCapturedValue(&htim5,TIM_CHANNEL_1); //读取捕获通道的值
			__HAL_TIM_SET_CAPTUREPOLARITY(&htim5,TIM_CHANNEL_1,TIM_ICPOLARITY_RISING); //设置捕获极性为上降沿
		}
	}
}

编译之后即可以看到如下结果。
在这里插入图片描述

  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于STM32F407VET6,输入捕获是一种常见的功能,可以用来测量外部信号的频率、脉冲宽度等。下面是一些步骤来实现输入捕获: 1. 配置GPIO引脚:选择一个合适的GPIO引脚作为输入捕获的引脚,并将其配置为输入模式。 ```c GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Pin = GPIO_PIN_X; // 替换成你所选择的引脚 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF_TIMX; // 替换成你所选择的定时器通道 HAL_GPIO_Init(GPIOX, &GPIO_InitStruct); ``` 2. 配置定时器:选择一个定时器和通道用于输入捕获,并根据需求配置定时器的参数。 ```c TIM_HandleTypeDef htim; htim.Instance = TIMX; // 替换成你所选择的定时器 htim.Init.Prescaler = 0; // 预分频器 htim.Init.CounterMode = TIM_COUNTERMODE_UP; htim.Init.Period = 0xFFFF; // 计数器的最大值 htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; HAL_TIM_IC_Init(&htim); ``` 3. 配置输入捕获:为定时器通道配置输入捕获功能。 ```c TIM_IC_InitTypeDef sConfigIC; sConfigIC.ICPolarity = TIM_ICPOLARITY_RISING; // 上升沿捕获 sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI; sConfigIC.ICPrescaler = TIM_ICPSC_DIV1; sConfigIC.ICFilter = 0; HAL_TIM_IC_ConfigChannel(&htim, &sConfigIC, TIM_CHANNEL_X); // 替换成你所选择的定时器通道 ``` 4. 启动定时器:启动定时器开始计数。 ```c HAL_TIM_IC_Start(&htim, TIM_CHANNEL_X); // 替换成你所选择的定时器通道 ``` 5. 读取捕获值:在需要的时候读取输入捕获的值,可以用来计算频率、脉冲宽度等。 ```c uint32_t captureValue = HAL_TIM_ReadCapturedValue(&htim, TIM_CHANNEL_X); // 替换成你所选择的定时器通道 ``` 以上是一个简单的输入捕获的实现步骤,你可以根据具体需求进行相应的配置和操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值