蓝桥杯学习笔记八:捕获计数器

一、什么是捕获计数器(说人话)?

比如说,我们想知道一个高电平输入到某引脚持续的时间(信号频率其实也是在求信号输入的持续时间),stm32里的定时器肯定是可以实现这一功能的。

我们刚所说的定时器其实在此时不太准确,应该称之为计数器,因为定时功能的实现其实是基于计数功能的使用。定时器是一秒钟计数80M个数,在预分频80之后,也就是一秒钟计数1M次,如果在输入信号的上升沿(就是高电平时)占0.1M个数,那就是100ms的高电平维持。

二、那怎样配置定时器才能实现这样的功能呢?

以捕获上升沿为例:

1、配置定时器

看看信号输入的引脚在哪个定时器的第几个通道,对该定时器的这个通道进行设置,设置好预分频数,确定好一秒的计数值,后分频数尽量大。不设置自动重装载值,向上计数模式。

2、配置该引脚为下拉输入模式

3、定时器输入捕获设置

设置为上升沿输入捕获(当高电平结束就开启中断),上升一次就执行输入捕获中断。

最后开启中断。

4、输入捕获中断函数

中断函数里写读取计数器的数值,然后与1s内的计数值进行比较来计算高电平存在的时间。再开启中断(类似串口接受中断函数每次都需要重新开启中断)

三、以蓝桥杯TIM_FRQ例程为例:

定时器输入捕获初始化:

TIM_HandleTypeDef htim2;

static void MX_TIM2_Init(void)
{


  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_IC_InitTypeDef sConfigIC = {0};


  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 80;//预分频
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;//向上计数
  htim2.Init.Period = 0xFFFF;//后分频尽量大
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;//无自动重装载值
  if (HAL_TIM_IC_Init(&htim2) != HAL_OK)//将定时器结构体的变量代入定时器配置初始化函数进行初始化
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != 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();
  }

	HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);//开启输入捕获中断入口


}

输入捕获中断执行函数:

uint32_t  cc1_value_2 = 0;  									// TIMx_CCR1 µÄÖµ 
uint32_t  f40 = 0;

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)//ÖжϺ¯Êý
{

	cc1_value_2 = __HAL_TIM_GET_COUNTER(&htim2);//获取定时器的计数值
	__HAL_TIM_SetCounter(&htim2,0);//计数值归零
	f40 = 1000000/cc1_value_2;//计算频率
	
	HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);//重新打开输入捕获中断入口
}

主函数:

int main(void)
{

	char buf[20];

  HAL_Init();

  SystemClock_Config();

  MX_GPIO_Init();
  MX_TIM2_Init();
	LCD_Init();
	
	LCD_Clear(Blue);
	LCD_SetBackColor(Blue);
	LCD_SetTextColor(White);
	
	LCD_DisplayStringLine(Line0, (uint8_t *)"                    ");
	LCD_DisplayStringLine(Line1, (uint8_t *)"                    ");
	LCD_DisplayStringLine(Line2, (uint8_t *)"      TIM Test      ");
	LCD_DisplayStringLine(Line3, (uint8_t *)"                    ");
	LCD_DisplayStringLine(Line4, (uint8_t *)"                    ");
	
	LCD_SetBackColor(White);
	LCD_SetTextColor(Blue);

	LCD_DisplayStringLine(Line5, (uint8_t *)"                    ");
	LCD_DisplayStringLine(Line6, (uint8_t *)"      TIM2 CH1      ");
	LCD_DisplayStringLine(Line7, (uint8_t *)"                    ");
	LCD_DisplayStringLine(Line8, (uint8_t *)"                    ");
	LCD_DisplayStringLine(Line9, (uint8_t *)"                    ");

  while (1)
  {
		sprintf(buf, "  FRQ(R40):%dHz   ",f40);
		LCD_DisplayStringLine(Line8, (uint8_t *)buf);
		
		HAL_Delay(200);
  }
}

四、用Cubmx配置:

蓝桥杯学习笔记八:捕获计数器

 蓝桥杯学习笔记八:捕获计数器

完美运行! 

上一篇:【无标题】


下一篇:STM32使用DMA接收不定长数据