STM32CubeMX系列|按键输入

按键输入

1. 实验介绍

本实验介绍如何使用STM32F103的IO口作为输入使用。IO口作为输入使用时,是通过读取IDR的内容来读取IO口的状态的。
本实验利用板载的4个按键,来控制板载的两个LED的亮灭和蜂鸣器。其中KEY_UP控制蜂鸣器;K1控制D1,按一次亮再按一次灭;K2控制D2,按一次亮再按一次灭;K3同时控制D1和D2,按一次它们的状态就翻转一次

2. 硬件设计

用到的硬件资源有:

  • 指示灯D1、D2
  • 蜂鸣器BUZ
  • 4个按键:KEY_UP、K1、K2、K3

硬件连接原理图如下,注意K1、K2、K3是低电平有效的,而KEY_UP是高电平有效,并且外部都没有上下拉电阻,所以需要在STM32F1内部设置上下拉;
STM32F103芯片单个IO口最大输出电流是25mA,而蜂鸣器的驱动电流是30mA左右,整个芯片的输出电流最大为150mA,如果在蜂鸣器上就消耗30mA,那么芯片的其他IO口及外设电流就比较拮据了,因此此处不会直接使用IO口驱动蜂鸣器,而是通过三极管把电流放大后再驱动蜂鸣器,这样IO口只需提供不到1mA的电流就可以控制蜂鸣器

在这里插入图片描述

3. 软件设计

3.1 STM32CubeMX设置
  • RCC设置外接HSE,时钟设置为72M
  • PC0和PC2设置为GPIO推挽输出模式、上拉、高速、默认输出电平为高电平
  • PB5设置为GPIO推挽输出、高速模式
  • PA0设置为GPIO输入模式、下拉模式;PE2/PE3/PE4设置为GPIO输入模式、上拉模式

在这里插入图片描述

  • 输入工程名,选择工程路径(不要有中文),选择MDK-ARM V5;勾选Generated periphera initialization as a pair of ‘.c/.h’ files per IP ;点击GENERATE CODE,生成工程代码
3.2 MDK-ARM软件编程
  • 在gpio.c文件中可以看到PC0/PC1/PB5/PA0/PE2/PE3/PE4管脚的初始化函数
void MX_GPIO_Init(void)
{
    
    
  GPIO_InitTypeDef GPIO_InitStruct = {
    
    0};
  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOE_CLK_ENABLE();		//开启GPIOE时钟
  __HAL_RCC_GPIOC_CLK_ENABLE();		//开启GPIOC时钟
  __HAL_RCC_GPIOA_CLK_ENABLE();		//开启GPIOA时钟
  __HAL_RCC_GPIOB_CLK_ENABLE();		//开启GPIOB时钟
  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOC, LED1_Pin|LED2_Pin, GPIO_PIN_SET);	//LED1/LED2默认输出是电平为高电平
  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(BUZ_GPIO_Port, BUZ_Pin, GPIO_PIN_RESET);	//BUZ默认输出是电平为低电平	
  /*Configure GPIO pins : PEPin PEPin PEPin */
  GPIO_InitStruct.Pin = K_LEFT_Pin|K_DOWN_Pin|K_RIGHT_Pin;		//PE2/PE3/PE4
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;						//输入
  GPIO_InitStruct.Pull = GPIO_PULLUP;							//上拉
  HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
  /*Configure GPIO pins : PCPin PCPin */
  GPIO_InitStruct.Pin = LED1_Pin|LED2_Pin;						//PC0/PC1
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;					//推挽输出
  GPIO_InitStruct.Pull = GPIO_PULLUP;							//上拉
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;					//高速
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
  /*Configure GPIO pin : PtPin */
  GPIO_InitStruct.Pin = K_UP_Pin;								//PA0
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;						//输入
  GPIO_InitStruct.Pull = GPIO_PULLDOWN;							//下拉
  HAL_GPIO_Init(K_UP_GPIO_Port, &GPIO_InitStruct);
  /*Configure GPIO pin : PtPin */
  GPIO_InitStruct.Pin = BUZ_Pin;								//PB5
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;					//推挽输出
  GPIO_InitStruct.Pull = GPIO_NOPULL;							//无上下拉
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;					//高速
  HAL_GPIO_Init(BUZ_GPIO_Port, &GPIO_InitStruct);
}
  • 在工程的应用文件目录下创建key.c文件,编写按键相关函数
/***********************************************************
*函 数 名: KEY_Scan(uint8_t mode)
*功    能: 按键处理函数
*形    参: mode:0 不支持连续按;1 支持连续按
*返 回 值: 返回按键值   0:表示未有按键按下
*					  1:KEY_RIGHT按下   2:KEY_DOWN按下
*					  3:KEY_LEFT按下    4:KEY_UP按下
***********************************************************/
uint8_t KEY_Scan(uint8_t mode)
{
    
    
	static uint8_t key = 1;		//按键松开标志
	if(mode == 1){
    
    				//支持连按
		key = 1;
	}
	
	if(key&&(KEY_UP==1||KEY_DOWN==0||KEY_LEFT==0||KEY_RIGHT==0)){
    
    
		HAL_Delay(10);			//按键消抖
		key = 0;
		if(KEY_UP==1)			return K_UP_PRES;
		else if(KEY_DOWN==0)	return K_DOWN_PRES; 
		else if(KEY_LEFT==0)	return K_LEFT_PRES; 
		else if(KEY_RIGHT==0)	return K_RIGHT_PRES; 
	}
	else if(KEY_UP==0&&KEY_DOWN==1&&KEY_LEFT==1&&KEY_RIGHT==1){
    
    
		key = 1;
	}
	
	return 0;
}
  • 在工程的头文件目录下创建key.h文件,编写相关声明
#ifndef _KEY_H_
#define _KEY_H_

#include "stm32f1xx.h"

//操作HAL库函数读取IO口状态
#define KEY_RIGHT	HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_4)
#define KEY_DOWN    HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_3)
#define KEY_LEFT    HAL_GPIO_ReadPin(GPIOE,GPIO_PIN_2)
#define KEY_UP      HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)
//定义按键按下时的键值
#define KEY_RIGHT_PRES 	1
#define KEY_DOWN_PRES	2
#define KEY_LEFT_PRES	3
#define KEY_UP_PRES   	4

uint8_t KEY_Scan(uint8_t mode);

#endif
  • 在main.c函数中编写相关程序
int main(void)
{
    
    
  /* USER CODE BEGIN 1 */
	uint8_t key;
  /* 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 */
  /* USER CODE END 2 */
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    
    
		key = KEY_Scan(0);
		switch(key){
    
    
			case KEY_UP_PRES:
				HAL_GPIO_WritePin(GPIOB,BUZ_Pin,GPIO_PIN_SET);
				HAL_Delay(300);
				HAL_GPIO_WritePin(GPIOB,BUZ_Pin,GPIO_PIN_RESET);
				HAL_Delay(300);
				break;
			case KEY_LEFT_PRES:
				HAL_GPIO_TogglePin(GPIOC,LED1_Pin);
				break;
			case KEY_DOWN_PRES:
				HAL_GPIO_TogglePin(GPIOC,LED2_Pin);
				break;
			case KEY_RIGHT_PRES:
				HAL_GPIO_TogglePin(GPIOC,LED1_Pin);
				HAL_GPIO_TogglePin(GPIOC,LED2_Pin);
				break;
		}
		HAL_Delay(10);
    /* USER CODE END WHILE */
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

4. 下载验证

编译无误后下载到开发板,按下KEY_UP蜂鸣器响一下;K1控制D1,按一次亮再按一次灭;K2控制D2,按一次亮再按一次灭;K3同时控制D1和D2,按一次它们的状态就翻转一次

猜你喜欢

转载自blog.csdn.net/Chuangke_Andy/article/details/108569293