STM32按键控制蜂鸣器鸣笛

检测扩展板上的KEY1状态,控制蜂鸣器鸣笛。每按一次按键,蜂鸣器响一声。

配置引脚信息

根据原理图可知:蜂鸣器的控制引脚连接的是STM32芯片的PC5引脚。需要将PC5设置为GPIO_Output模式,并且修改标签(Label)为BEEP,其他配置如下图所示。

image-20220308180058144

image-20220308180450165

image-20220308182008836

2.按键KEY1连接的是PD2引脚。需要将PD2设置为GPIO_Input模式,并且修改标签(Label)为KEY1,其他配置如下图所示。

image-20220308180924554

image-20220308180842219

image-20220308181859196

保存并生成代码。

添加文件结构

通过图形化配置了引脚信息,生成的代码已经包含系统初始化内容,所以不需要额外再初始化系统配置。

1.为了管理方便,我们新建一个BSP源码文件夹。在鼠标移动项目名称那里点击右键->New->Source Folder

image-20220309141245124

image-20220309141714873

2.将BSP添加到环境中。点击Project->Properties->C/C++ Build->settings->MCU GCC Compiler->include paths,再点击添加按钮将../BSP填入并保存。

image-20220309142715170

image-20220309142452345

3.新建一个bsp.h和一个bsp.c文件,右键BSP->New->Header File/Source File,然后输入对应名称即可。

这两个文件主要负责链接main.c中的部分函数,可以避免重复写代码。

image-20220309143541320

4.在bsp.h增加以下内容:将LED的控制做成宏定义的方式,简单快捷。新建Bsp_Init()函数主要负责初始化,Bsp_Loop()主要负责主程序内容。Bsp_Led_Show_State_Handle()函数主要负责LED指示灯闪烁效果,用于提示系统正在运行。

#ifndef __BSP_H__
#define __BSP_H__

/* Import HAL related library  导入HAL相关库 */
#include "main.h"
#include "gpio.h"

#include "stm32f1xx_hal.h"
#include "stm32f103xe.h"


/* Import device driver library  导入设备驱动库 */
#include "bsp_beep.h"
#include "bsp_key.h"

/* DEFINE */
#define LED_ON()         HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, SET)
#define LED_OFF()        HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, RESET)
#define LED_TOGGLE()     HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin)


/* functions */
void Bsp_Init(void);
void Bsp_Loop(void);
void Bsp_Led_Show_State_Handle(void);


#endif /* __BSP_H__ */

在main.c文件中导入bsp.h头文件。

在main函数中调用Bsp_Init()。

在while(1)中调用Bsp_Loop()。

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2022 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under BSD 3-Clause license,
  * the "License"; You may not use this file except in compliance with the
  * License. You may obtain a copy of the License at:
  *                        opensource.org/licenses/BSD-3-Clause
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "bsp.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 */

  /* 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 */
  Bsp_Init();
  /* USER CODE END 2 */

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

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

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

  /** 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.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != 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_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != 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 */

核心代码解释

在BSP中新建蜂鸣器的驱动库bsp_beep.h和bsp_beep.c文件。在bsp_beep.h中增加以下内容:

#ifndef __BSP_BEEP_H__
#define __BSP_BEEP_H__

#include "main.h"


#define BEEP_STATE_OFF       0
#define BEEP_STATE_ON_ALWAYS 1
#define BEEP_STATE_ON_DELAY  2


#define BEEP_ON()        HAL_GPIO_WritePin(BEEP_GPIO_Port, BEEP_Pin, SET)
#define BEEP_OFF()       HAL_GPIO_WritePin(BEEP_GPIO_Port, BEEP_Pin, RESET)


void Beep_Timeout_Close_Handle(void);
void Beep_On_Time(uint16_t time);


#endif

其中Beep_Timeout_Close_Handle()函数需要每10毫秒调用一次,这样才可以保证Beep_On_Time()函数设置时间后按照正常的效果进行。Beep_On_Time(time)中time表示蜂鸣器开启的时间,如果time=0,则关闭蜂鸣器,如果time=1则蜂鸣器一直响,如果time>=10,则蜂鸣器响time毫秒后自动关闭(time应是10的倍数)。

在BSP中新建蜂鸣器的驱动库bsp_key.h和bsp_key.c文件。在bsp_key.h中增加以下内容:

#ifndef __BSP_KEY_H__
#define __BSP_KEY_H__

#include "gpio.h"


#define KEY_PRESS           1
#define KEY_RELEASE         0

#define KEY_MODE_ONE_TIME   1
#define KEY_MODE_ALWAYS     0


uint8_t Key1_State(uint8_t mode);


#endif /* __BSP_KEY_H__ */

其中Key1_State(mode)函数的功能是检测按键是否被下,需要每10毫秒调用一次。mode可以输入0或者1,mode=0表示按下KEY1就一直返回KEY_PRESS,松开才返回KEY_RELEASE,mode=1表示不管按下KEY1多长时间,都只返回一次KEY_PRESS,其他情况都返回KEY_RELEASE。

在Bsp_Init()中添加开机蜂鸣器响50毫秒,在Bsp_Loop()检测按键是否被按下,如果按下则响50毫秒后自动关闭。最下方是LED灯和蜂鸣器的控制句柄,只需要每10毫秒调用一次就可以。

// bsp.c
#include "bsp.h"

// LED显示当前运行状态,每10毫秒调用一次,LED灯每200毫秒闪烁一次。
// The LED displays the current operating status, which is invoked every 10 milliseconds, and the LED blinks every 200 milliseconds.  
void Bsp_Led_Show_State_Handle(void)
{
	static uint8_t led_count = 0;
	led_count++;
	if (led_count > 20)
	{
		led_count = 0;
		LED_TOGGLE();
	}
}


// The peripheral device is initialized  外设设备初始化
void Bsp_Init(void)
{
	Beep_On_Time(50);
}


// main.c中循环调用此函数,避免多次修改main.c文件。
// This function is called in a loop in main.c to avoid multiple modifications to the main.c file
void Bsp_Loop(void)
{
	// Detect button down events   检测按键按下事件
	if (Key1_State(KEY_MODE_ONE_TIME))
	{
		Beep_On_Time(50);
	}

	Bsp_Led_Show_State_Handle();
	// The buzzer automatically shuts down when times out   蜂鸣器超时自动关闭
	Beep_Timeout_Close_Handle();
	HAL_Delay(10);
}
//bsp_beep.c
#include "bsp_beep.h"
#include "bsp.h"

uint16_t beep_on_time = 0;
uint8_t beep_state = 0;

// 刷新蜂鸣器打开的时间
// Refreshes the buzzer time
static void Beep_Set_Time(uint16_t time)
{
	beep_on_time = time;
}

// 获取当前蜂鸣器打开的剩余时间
// Gets the remaining time of the current buzzer on
static uint16_t Beep_Get_Time(void)
{
	return beep_on_time;
}

// 刷新蜂鸣器的状态
// Refreshes the buzzer status
static void Beep_Set_State(uint8_t state)
{
	beep_state = state;
}

// 获取蜂鸣器的状态
// Gets the status of the buzzer
static uint8_t Beep_Get_State(void)
{
	return beep_state;
}

// 设置蜂鸣器开启时间,time=0时关闭,time=1时一直响,time>=10,延迟xx毫秒后自动关闭
// Set the buzzer start time. The buzzer is disabled when time is 0, keeps ringing when time is 1, and automatically shuts down after time>=10  
void Beep_On_Time(uint16_t time)
{
	if (time == BEEP_STATE_ON_ALWAYS)
	{
		Beep_Set_State(BEEP_STATE_ON_ALWAYS);
		Beep_Set_Time(0);
		BEEP_ON();
	}
	else if (time == BEEP_STATE_OFF)
	{
		Beep_Set_State(BEEP_STATE_OFF);
		Beep_Set_Time(0);
		BEEP_OFF();
	}
	else
	{
		if (time >= 10)
		{
			Beep_Set_State(BEEP_STATE_ON_DELAY);
			Beep_Set_Time(time / 10);
			BEEP_ON();
		}
	}
}

// 蜂鸣器超时自动关闭程序, 10毫秒调用一次 
// Buzzer timeout automatically shut down the program, 10 milliseconds to call once
void Beep_Timeout_Close_Handle(void)
{
	if (Beep_Get_State() == BEEP_STATE_ON_DELAY)
	{
		if (Beep_Get_Time())
		{
			beep_on_time--;
		}
		else
		{
			BEEP_OFF();
			Beep_Set_State(BEEP_STATE_OFF);
		}
	}
}


 

//bsp_key.c
#include "bsp_key.h"
#include "bsp.h"


// 判断按键是否被按下,按下返回KEY_PRESS,松开返回KEY_RELEASE
// Determine if the key is pressed, press to return KEY_PRESS, release to return KEY_RELEASE  
static uint8_t Key1_is_Press(void)
{
	if (!HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin))
	{
		return KEY_PRESS; // 如果按键被按下,则返回KEY_PRESS
	}
	return KEY_RELEASE;   // 如果按键是松开状态,则返回KEY_RELEASE
}


// 读取按键K1的状态,按下返回KEY_PRESS,松开返回KEY_RELEASE. 
// mode:设置模式,0:按下一直返回KEY_PRESS;1:按下只返回一次KEY_PRESS
// Read the state of key K1, press down to return KEY_PRESS, release to return key_release. 
// mode: setting mode, 0: press down to return KEY_PRESS;  1: KEY_PRESS is returned only once  
uint8_t Key1_State(uint8_t mode)
{
	static uint16_t key1_state = 0;

	if (Key1_is_Press() == KEY_PRESS)
	{
		if (key1_state < (mode + 1) * 2)
		{
			key1_state++;
		}
	}
	else
	{
		key1_state = 0;
	}
	if (key1_state == 2)
	{
		return KEY_PRESS;
	}
	return KEY_RELEASE;
}


/*********************************************END OF FILE**********************/

烧录程序后,开机时蜂鸣器会先响50毫秒,LED灯每隔200毫秒闪一次,每按一次按键,蜂鸣器都会响50毫秒。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值