定时器按键 面向对象封装 HAL库

首先选择一个定时器 中断周期为10ms

1.Key.h中的内容

cnt_delay 为消抖次数 6*10ms  60ms的消抖时间 可以按照实际需求更改 
后面长按按键可以根据需求 仿照写在time_read_key函数中

通过BIT5 在Key_GetNum函数中解析出数值

只写了长按和短按

连按之类的可以仿照继续写

把有关freertos的头文件和test任务删除就可以直接使用了

#ifndef _KEY_H
#define _KEY_H

#include "main.h"
#include "FreeRTOS.h"
#include "queue.h"

#define cnt_short_delay 6		//消抖数值 短按
#define cnt_long_delay 	50		//消抖数值 长按

typedef enum 				//按键状态
{
	BIT0=0,					//初始状态
	BIT1,					//计数状态		
	BIT2,					//短按状态确认
	BIT3,					//长按状态确认
}Key_Bit_t;

typedef struct {
    GPIO_TypeDef *GPIOx;    	//端口号
    uint16_t GPIO_PIN;      	//引脚号
    
    int8_t cnt;			    	//计数值
    Key_Bit_t bit;	        	//状态值
	int key_value;				//返回值
	int8_t key_short_value;	    //短按值
	int8_t key_long_value;	    //长按值
} KeyState_t;

extern KeyState_t Key_board;
extern  int value_KEY;
extern QueueHandle_t g_xQueueKey;

void time_read_key(KeyState_t *key_state);//定时器读取按键
void Key_Test(void *argument);
#endif

2.Key.c

声明对象Key_board 

#include "stm32f4xx_hal.h"
#include "key.h"

#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"

KeyState_t Key_board = {
    .GPIOx = KEY_GPIO_Port,
    .GPIO_PIN = KEY_Pin,
    .cnt = 0,
    .bit = BIT0,
	.key_value=0,
    .key_short_value = 1,
	.key_long_value = 2,
};

#if 0
static uint8_t Key_Init(void)
{
    //This section is generated by Cube
    return 0;
}
#endif


//定时器读取按键
void time_read_key(KeyState_t *key_state)
{
	if (HAL_GPIO_ReadPin(key_state->GPIOx, key_state->GPIO_PIN) == RESET  && key_state->bit==BIT0)
	{
			key_state->cnt=0;
			key_state->bit = BIT1;
	}
	if(key_state->bit == BIT1)
	{
		key_state->cnt++;

		if(HAL_GPIO_ReadPin(key_state->GPIOx, key_state->GPIO_PIN) == SET )
		{
			if(key_state->cnt >= cnt_short_delay&&key_state->cnt < cnt_long_delay)
			{
				key_state->bit = BIT2;
			}
			else if(key_state->cnt >= cnt_long_delay)
			{
				key_state->bit = BIT3;
			}
			else
				key_state->bit = BIT0;
			
				key_state->cnt = 0;
		}
	}
}

//获取键值
static int Key_GetNum(KeyState_t *key_state)
{
	if(key_state->bit==BIT2)
	{
		key_state->bit=BIT0;
		key_state->key_value=key_state->key_short_value;
		return key_state->key_value;
	}
	if(key_state->bit==BIT3)
	{
		key_state->bit=BIT0;
		key_state->key_value=key_state->key_long_value;
		return key_state->key_value;
	}
	return 0;
}

int Key_Return_Num(void)
{
	if(Key_GetNum(&Key_board)!=0)
	{
		return Key_board.key_value;
	}
	return 0;
}

int value_KEY=0;
QueueHandle_t g_xQueueKey; /* 按键队列 */
void Key_Test(void *argument)
{
	
    while (1)
    {
		if(g_xQueueKey!=NULL)			//创建队列成功
		{
			int keyValue = Key_Return_Num();
			if (keyValue != 0) 
			{
    			value_KEY = keyValue;
    			xQueueSendToBack(g_xQueueKey, &value_KEY, pdMS_TO_TICKS(50));
			}
		}
		vTaskDelay(10);
    }
}




3.定时器调用

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用HAL库实现STM32F103单片机定时器触发ADC转换的代码实现。 首先需要在CubeMX中配置好ADC和定时器的参数,然后在main.c文件中编写以下代码: ```c #include "stm32f1xx_hal.h" ADC_HandleTypeDef hadc1; TIM_HandleTypeDef htim2; void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_ADC1_Init(void); static void MX_TIM2_Init(void); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_ADC1_Init(); MX_TIM2_Init(); HAL_TIM_Base_Start(&htim2); //启动定时器 HAL_ADC_Start(&hadc1); //启动ADC uint32_t adc_value; //定义变量存储ADC转换结果 while (1) { HAL_ADC_PollForConversion(&hadc1, 100); //等待ADC转换完成 if (HAL_ADC_GetState(&hadc1) == HAL_ADC_STATE_EOC_REG) //判断ADC转换完成状态 { adc_value = HAL_ADC_GetValue(&hadc1); //获取ADC转换结果 //处理ADC转换结果 } } } void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; __HAL_RCC_PWR_CLK_ENABLE(); __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) { Error_Handler(); } } static void MX_ADC1_Init(void) { ADC_ChannelConfTypeDef sConfig = {0}; hadc1.Instance = ADC1; hadc1.Init.ScanConvMode = DISABLE; hadc1.Init.ContinuousConvMode = ENABLE; hadc1.Init.DiscontinuousConvMode = DISABLE; hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T2_CC2; //设置ADC触发源为定时器2的CC2输出 hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc1.Init.NbrOfConversion = 1; if (HAL_ADC_Init(&hadc1) != HAL_OK) { Error_Handler(); } sConfig.Channel = ADC_CHANNEL_0; //设置采样通道为ADC1的通道0 sConfig.Rank = ADC_REGULAR_RANK_1; sConfig.SamplingTime = ADC_SAMPLETIME_28CYCLES_5; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); } } static void MX_TIM2_Init(void) { TIM_ClockConfigTypeDef sClockSourceConfig = {0}; TIM_MasterConfigTypeDef sMasterConfig = {0}; htim2.Instance = TIM2; htim2.Init.Prescaler = 35999; //设置定时器分频系数,定时器时钟频率为72MHz/(35999+1)=2kHz htim2.Init.CounterMode = TIM_COUNTERMODE_UP; htim2.Init.Period = 999; //设置定时器计数周期为1000个时钟周期,即500ms产生一次触发信号 htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; if (HAL_TIM_Base_Init(&htim2) != HAL_OK) { Error_Handler(); } sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK) { Error_Handler(); } } static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); } ``` 在以上代码中,HAL_ADC_Init()函数用于初始化ADC,HAL_ADC_ConfigChannel()函数用于配置ADC的采样通道,HAL_TIM_Base_Init()函数用于初始化定时器,HAL_TIM_Base_Start()函数用于启动定时器,HAL_ADC_Start()函数用于启动ADC,HAL_ADC_PollForConversion()函数用于等待ADC转换完成,HAL_ADC_GetValue()函数用于获取ADC转换结果。 需要注意的是,在MX_ADC1_Init()函数中,使用了ADC_EXTERNALTRIGCONV_T2_CC2宏定义来设置ADC触发源为定时器2的CC2输出,这个宏定义在stm32f1xx_hal_adc.h头文件中定义。而在MX_TIM2_Init()函数中,使用了TIM_TRGO_UPDATE宏定义来设置定时器触发输出为更新事件触发。 以上就是使用HAL库实现STM32F103单片机定时器触发ADC转换的代码实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值