STM32F1基本定时器实验-外部触发脉冲计数

本文介绍了一个使用STM32F1进行定时器实验的案例,通过外部触发脉冲计数和按键状态机实现信号检测与处理。实验中,定时器2用于接收外部触发信号并计数,定时器6则用于10ms间隔的按键检测。状态机设计用于避免抖动,确保按键状态的准确判断。在主函数中,当检测到按键按下时,会发送2ms脉冲并更新计数值。配置包括外部晶振、GPIO、TIM2和TIM6设置以及串口通信。
摘要由CSDN通过智能技术生成

STM32F1定时器实验-外部触发脉冲计数

之前我们用外部中断测量了PWM的频率,而外部触发是设置2个定时器,利用按键触发,一个定时器2用来接受外部触发信号并计数,另一个定时器6实时检测按键。
按照这样的思路,我们的按键读取用状态机思想去读取,使定时器6产生10ms的定时中断来实时检测按键并利用状态机设计思想处理按键信号,将PA1设置成输出引脚,设置定时器2的PA0引脚来接收信号,通过按键触发改变标志位来发送电平信号,再定义全局数存放PA0接收脉冲信号次数,最后串口配置。
什么?你不知道状态机思想?送你学习状态机
说实话,状态机思想可以清晰把你的代码逻辑弄清楚,这个是我自己写按键时画的草图:
在这里插入图片描述
画的只要你自己可以看懂就行

代码讲解

首先我们需要按键的状态,它的状态分为检测,按下,释放,所以定义枚举类型的结构体

/* USER CODE BEGIN PTD */
typedef enum
{
	KEY_CHECK=0,
	KEY_CONFRIM,
	KEY_RELAESE
}KEY_STATE;
/* USER CODE END PTD */

状态变量的定义以及标志位,计数值

/* USER CODE BEGIN PV */
KEY_STATE  keyState=KEY_CHECK;
int Result=0;
uint8_t keyvalue=0;

/* USER CODE END PV */

对于按键检测,是在TIM6里处理的,选用KEY1即PE3
在这里插入图片描述

在这里插入图片描述

而之间的状态转移是通过判断电平实现的,按下时为低电平,未按下为高电平,根据我们按下的一个完整过程,我们可以通过switch语句实现我们的整个过程

/* USER CODE BEGIN 4 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance==TIM6)//判断是否为TIM6中断
	{
		switch(keyState)
		{
			case KEY_CHECK://检测状态下
			{
				if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==GPIO_PIN_RESET)//检测按键为低电平
				{
					keyState=KEY_CONFRIM;//确认按下状态
				}
				break;
			}
			case KEY_CONFRIM://确认按下状态下
			{
        if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==GPIO_PIN_RESET)//再次判断	
				{
              keyvalue=1;//改变标志位用于触发脉冲信号
              keyState=KEY_RELAESE;//按下后释放
				}
         else		
				 {
					    keyState=KEY_CHECK;//排除抖动干扰或者误判,回到检测
				 }
				 break;
			 }
			case KEY_RELAESE://释放状态下
			{
				if(HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)==GPIO_PIN_SET)	//判断按键未按下
				{
					keyState=KEY_CHECK;//回到检测状态
				//	keyvalue=1;
				}
				break;
			}
			default: break;
}
		}
	}
/* USER CODE END 4 */

主函数内

  /* USER CODE BEGIN 2 */
	HAL_TIM_Base_Start(&htim2);//开启TIM2用于计数
	HAL_TIM_Base_Start_IT(&htim6);//开启TIM6用于按键检测
	printf("Timer counter founction test: \n");//串口起始提示
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		if(keyvalue==1)//如果为按下状态
		{
			keyvalue=0;
			HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET);
			HAL_Delay(1);
			HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET);
			HAL_Delay(1);//发出周期为2ms的脉冲
			Result=__HAL_TIM_GET_COUNTER(&htim2);//读取计数值
			printf("Counter:%d.\n",Result);
		}
  }
  /* USER CODE END 3 */

CUBEMX配置

1.时钟配置外部晶振,主时钟为72MHz
在这里插入图片描述
在这里插入图片描述
2.GPIO:选择PA1输出,PE3输入
在这里插入图片描述
3.TIM:
TIM2:Clock Source:外部触发
在这里插入图片描述
这时PA0为你的触发引脚
在这里插入图片描述
TIM6:激活并生成10ms中断
在这里插入图片描述
4.usart设置
在这里插入图片描述

5.Project的设置,
在这里插入图片描述
还有一个之前没注意,就是在Code Generator一栏中第一个方框里选择第二个:Copy only the necessary library files,要不一个工程就是百八十MB,占内存。

在这里插入图片描述
最后生成代码

  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要在STM32上使用定时器捕获脉冲宽度,可以遵循以下步骤: 1. 配置定时器模式为输入捕获模式。可以使用CubeMX或手动配置寄存器来完成此操作。 2. 配置GPIO引脚,使其与定时器捕获通道相对应。GPIO应该被配置为输入模式,这样它才能读取脉冲。 3. 在代码中启用定时器和GPIO时钟。 4. 在定时器中启用捕获通道,并为其设置触发条件。 5. 在捕获中断服务程序(或轮询代码)中读取捕获寄存器的值。这将给出脉冲的宽度。 6. 可以使用捕获寄存器的值来计算脉冲的频率或其他相关参数。 下面是一个简单的示例代码,演示了如何在STM32上使用定时器捕获脉冲宽度: ```c #include "stm32f4xx_hal.h" // 定义定时器句柄和捕获值变量 TIM_HandleTypeDef htim2; uint32_t capture_val; // 定义捕获中断服务程序 void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if (htim->Instance == TIM2) // 检查是否为TIM2定时器 { capture_val = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); // 读取捕获值 } } int main(void) { // 启用定时器和GPIO时钟 __HAL_RCC_TIM2_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); // 配置GPIO引脚为输入模式 GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 配置定时器为输入捕获模式 htim2.Instance = TIM2; htim2.Init.Prescaler = 0; htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 0xFFFF; htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; HAL_TIM_IC_Init(&htim2); // 配置捕获通道和触发条件 TIM_IC_InitTypeDef sConfigIC = {0}; sConfigIC.ICPolarity = TIM_ICPOLARITY_RISING; sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI; sConfigIC.ICPrescaler = TIM_ICPSC_DIV1; sConfigIC.ICFilter = 0; HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_1); // 启动定时器 HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1); while (1) { // 在这里处理捕获寄存器的值 } } ``` 在上面的示例代码中,我们配置了TIM2定时器的通道1为输入捕获模式,并将其与PA0 GPIO引脚相连接。在捕获中断服务程序中,我们读取了捕获寄存器的值,这将给出脉冲的宽度。在主循环中,我们可以根据需要处理该值。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值