三、STM32学习---IO口(LED、按键检测)

前言

GPIO的基础使用----输入、输出。以及示例输入--LED、输出---按键检测

一、Cubemx

根据引脚名查找引脚。

配置输出模式:

1、推挽输出:可以直接输出高电平。

2、开漏输出:高电平需要使用上拉电阻,吸收电流的能力强点。

 输入模式

 

二、keil5

配置Keil5

 输出

void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
功能:输出电平
GPIO_PIN_RESET: 低电平
GPIO_PIN_SET: 高电平

void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
功能:反转电平

输入

GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
功能:检测电平
返回值:当前电平

按键检测示例

key.c

#include "ZC_KEY.h"
///
///本模块自定义///
_ZC_key_drive Key[key_num]={0};  			//按键 
static bool zc_org[key_org_num]={0}; 	//组
/初始化/
void Key_Init(void)
{
	for(int i=0 ; i < key_num ; i++)
	{
		Key[i].id=i;
		Key[i].time_target=50;
	}
}
///
///函数///	
/*
功能:按键信息检测
传递值:按键id
返回值:是否触发  1  触发   0 空闲
*/
static bool get_KEY_val(int id)
{	 
	switch (id)
  {
  	case 0:
		{
			if(WAKE_UP)
				return 1;
		}
		break;
		case 1:
		{
			if(!KEY0_pin)
				return 1;
		}
			break;
		case 2:
		{
			if(!KEY1_pin)
				return 1;
		}
			break;
		case 3:
		{
			if(!KEY2_pin)
				return 1;
		}
			break;
  	default:
			return 0;
  }	
	return 0;
}
/*
功能:   触发处理函数
传递值:按键id
返回值:无
*/
static void KEY_deal(int id)
{
	switch (id)
  {
  	case 0:
		{
			HAL_GPIO_WritePin(GPIOB, LED1_Pin,GPIO_PIN_RESET);
		}
  	break;
  	case 1:
		{
			HAL_GPIO_WritePin(GPIOB, LED1_Pin,GPIO_PIN_SET);
		}
  	break;
		case 2:
		{
			HAL_GPIO_WritePin(GPIOB, LED0_Pin,GPIO_PIN_RESET);
		}
  	break;
		case 3:
		{
			HAL_GPIO_WritePin(GPIOB, LED0_Pin,GPIO_PIN_SET);
		}
  	break;
		case 4:
		{
		
		}
  	break;
  	default:
  		break;
  }
}
/*
功能:按键信息判断函数,根据是否触发进行相关处理
传递值:按键的id
返回值:
*/
static void KEY_deal1(int i)
{
	if(get_KEY_val(Key[i].id))
	{
		if(Key[i].time == Key[i].time_target)
		{
			Key[i].state =1;
				
			if(Key[i].Batter)
				Key[i].time = 0;
			else
				Key[i].time++;
				
			if(Key[i].organiza > 0)
				zc_org[Key[i].organiza] = 1;
				
			KEY_deal(Key[i].id);
		}
		else if(Key[i].time < Key[i].time_target)
			Key[i].time++;
	}
	else 
	{
		Key[i].state =0;
		Key[i].time = 0;
		zc_org[Key[i].organiza] = 0;
	}
		
}

/*
功能:按键检测 1ms轮训一次
传递值:
返回值:
*/
void KEY_process(void)
{
	for(int i=0 ; i < key_num ; i++)
	{
		if(Key[i].organiza == 0 || (zc_org[Key[i].organiza] == 0))
		{
			KEY_deal1(i);
		}
		else if(Key[i].organiza != 0)
		{
				if(Key[i].state)
				{
					KEY_deal1(i);
				}
				else
					Key[i].time = 0;
		}
	}
}

key.h

#ifndef _H_ZC_KEY_H_
#define _H_ZC_KEY_H_


/*
本模块是按键检测及处理,功能有连击/单击、分组(组里的信息不能同时触发)、延时
输入:	按键信息
输出 : 按键处理函数
*/
/宏定义与头文件//
#include "gpio.h"
#include <stdbool.h>

#define key_num  5    		//按键个数
#define key_org_num 3			//分组数

/* 按键错误枚举 */
typedef enum
{
	key_no_err=0,					//无错误
}ZC_key_ERR;

/* 按键错误枚举 */

/*按键*/
typedef struct
{
	int id;													//按键id号
	bool state;											//按键状态    1  触发  0 空闲
	bool Batter;										//连击 1   单击 0
	int organiza;										//组号 0 单独  非0 组号
	uint16_t time;									//延时计数时间
	uint16_t time_target;						//延时目标时间
	ZC_key_ERR error;								//错误
}_ZC_key_drive;

extern _ZC_key_drive Key[key_num];

#define WAKE_UP  	HAL_GPIO_ReadPin(WK_UP_GPIO_Port,WK_UP_Pin) 
#define KEY0_pin  HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin) 
#define KEY1_pin  HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin) 
#define KEY2_pin  HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin)  

///
extern void KEY_process(void);//按键轮询处理
extern void Key_Init(void);
void Key_detection(void);
#endif




main.c

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2022 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "ZC_KEY.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
	uint32_t sys1ms=0;
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  /* USER CODE BEGIN 2 */
	Key_Init();//按键初始化
  /* USER CODE END 2 */

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

    /* USER CODE BEGIN 3 */
		if(HAL_GetTick() - sys1ms >= 1)
		{
			sys1ms = HAL_GetTick();
			KEY_process();//按键轮训
		}
		
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 25;
  RCC_OscInitStruct.PLL.PLLN = 432;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 2;
  RCC_OscInitStruct.PLL.PLLR = 2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Activate the Over-Drive mode
  */
  if (HAL_PWREx_EnableOverDrive() != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

这个按键检测的功能: 检测多个信息;多个信息为一组,一组只能触发一个信息;单次或连续检测;延时防抖

总结

本文实现IO口的基本功能与一个按键检测示例。

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值