第2章 蜂鸣器实验

第二章 蜂鸣器实验

1. 导入

上一章,我们介绍了 STM32F4 的 IO 口作为输出的使用,这一章,我们将通过另外一个例子讲述 STM32F4 的 IO 口作为输出的使用。 在本章中,我们将利用一个 IO 口来控制板载的有源蜂鸣器,实现蜂鸣器控制。

2. 蜂鸣器简介

探索者 STM32F4 开发板板载的蜂鸣器是电磁式的有源蜂鸣器:

这里的有源不是指电源的“源”,而是指有没有自带震荡电路,有源蜂鸣器自带了震荡电路,一通电就会发声;无源蜂鸣器则没有自带震荡电路,必须外部提供 2~5Khz 左右的方波驱动,才能发声。

前面我们已经对 STM32F4 的 IO 做了简单介绍,上一章,我们就是利用 STM32 的 IO 口直接驱动 LED 的,本章的蜂鸣器,我们能否直接用 STM32 的 IO 口驱动呢? 让我们来分析下: STM32F4 的单个 IO 最大可以提供 25mA 电流(来自数据手册),而蜂鸣器的驱动电流是 30mA左右,两者十分相近,但是全盘考虑, STM32F4 整个芯片的电流, 最大也就 150mA,如果用 IO 口直接驱动蜂鸣器,其他地方用电就得省着点了…所以,我们不用 STM32F4 的 IO 直接驱动蜂鸣器,而是通过三极管扩流后再驱动蜂鸣器,这样 STM32F4 的 IO 只需要提供不到 1mA 的电流就足够了。

3. 硬件设计

本章需要使用到的硬件有:

  1. 指示灯DS0

  2. 蜂鸣器

DS0 在上一章已有介绍,而蜂鸣器在硬件上也是直接连接好了的, 不需要经过任何设置,直接编写代码就可以了。 蜂鸣器的驱动信号连接在 STM32F4 的 PF8 上。

屏幕截图 2024 09 05 165006

图中我们用到一个 NPN 三极管(S8050)来驱动蜂鸣器, R61 主要用于防止蜂鸣器的误发声。当 PF.8 输出高电平的时候,蜂鸣器将发声, 当 PF.8 输出低电平的时候,蜂鸣器停止发声。

4. 软件设计

4.1 编程目标

  • LED初始化

  • 驱动蜂鸣器

4.2 代码分析

上一章我们与标准库进行了比较,这一章作为基础,我们详细分析HAL库函数

  • LED宏定义
#ifndef _LED_H
#define _LED_H
#include "sys.h"

#define LED0 PFout(9)  // LED0
#define LED1 PFout(10) // LED1

void LED_Init(void);

#endif

LED0LED1 是宏定义,代表对特定引脚(PF9 和 PF10)的访问。PFout(n) 是一个宏,用于控制 GPIOF 的输出引脚。具体来说:

  • PFout(9) 会使能 GPIOF 的第 9 引脚的输出。
  • PFout(10) 会使能 GPIOF 的第 10 引脚的输出。

这两个宏通常用来在程序中简化对 LED 的控制。

示例代码:

假设你有一个函数用于打开或关闭 LED:

void LED_Toggle(uint8_t led) 
{
    if(led == 0) 
    {
        LED0 = !LED0; // 切换 LED0 的状态
    } 
    else if(led == 1) 
    {
        LED1 = !LED1; // 切换 LED1 的状态
    }
}

如果你调用 LED_Toggle(0);,它会切换 PF9 引脚的电平,从而改变连接到该引脚的 LED 的状态。同样,LED_Toggle(1); 切换 PF10 引脚的电平。

  • LED初始化函数
#include "led.h"
// 初始化PB1为输出.并使能时钟        
// LED IO初始化
void LED_Init(void)
{
    GPIO_InitTypeDef GPIO_Initure;
    __HAL_RCC_GPIOF_CLK_ENABLE(); // 开启GPIOF时钟
    GPIO_Initure.Pin = GPIO_PIN_9|GPIO_PIN_10;// PF9,10
    GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP;  // 推挽输出
    GPIO_Initure.Pull = GPIO_PULLUP;          // 上拉
    GPIO_Initure.Speed = GPIO_SPEED_HIGH;     // 高速
    HAL_GPIO_Init(GPIOF, &GPIO_Initure);
    HAL_GPIO_WritePin(GPIOF, GPIO_PIN_9, GPIO_PIN_SET); // PF9置1,默认初始化后灯灭
    HAL_GPIO_WritePin(GPIOF, GPIO_PIN_10, GPIO_PIN_SET);// PF10置1,默认初始化后灯灭
}
  1. #include "led.h"
    包含自定义的头文件 led.h,用于引入 LED 控制相关的定义和声明。

  2. void LED_Init(void)
    LED_Init 函数用于初始化 LED 控制的相关 GPIO 引脚。

  3. GPIO_InitTypeDef GPIO_Initure;
    定义一个结构体 GPIO_Initure,用于配置 GPIO 引脚的参数。

  4. __HAL_RCC_GPIOF_CLK_ENABLE();
    使能 GPIOF 时钟。__HAL_RCC_GPIOF_CLK_ENABLE() 是一个宏,调用该宏会设置 RCC (时钟控制) 寄存器以开启 GPIOF 的时钟,确保对 GPIOF 的操作可以进行。

  5. GPIO_Initure.Pin = GPIO_PIN_9 | GPIO_PIN_10;
    配置要初始化的 GPIO 引脚为 PF9 和 PF10。GPIO_PIN_9GPIO_PIN_10 是 STM32 HAL 库定义的常量,表示第 9 和第 10 引脚。

  6. GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP;
    设置 GPIO 引脚为推挽输出模式 (GPIO_MODE_OUTPUT_PP)。推挽输出模式可以提供强驱动能力,使引脚输出高电平或低电平。

  7. GPIO_Initure.Pull = GPIO_PULLUP;
    配置 GPIO 引脚上拉电阻 (GPIO_PULLUP)。上拉电阻将引脚在未被驱动时保持在高电平状态。

  8. GPIO_Initure.Speed = GPIO_SPEED_HIGH;
    设置 GPIO 引脚的输出速度为高速 (GPIO_SPEED_HIGH)。这意味着引脚能够以更高的频率进行电平切换。

  9. HAL_GPIO_Init(GPIOF, &GPIO_Initure);
    调用 HAL_GPIO_Init() 函数来初始化 GPIOF 引脚。该函数接受两个参数:

  • GPIOF:要初始化的 GPIO 端口。
  • &GPIO_Initure:指向 GPIO_Initure 结构体的指针,包含了引脚配置的所有参数。
  1. HAL_GPIO_WritePin(GPIOF, GPIO_PIN_9, GPIO_PIN_SET);
    将 GPIOF 的第 9 引脚设置为高电平 (GPIO_PIN_SET)。这会使连接到 PF9 的 LED 熄灭(假设 LED 是负逻辑)。

  2. HAL_GPIO_WritePin(GPIOF, GPIO_PIN_10, GPIO_PIN_SET);
    将 GPIOF 的第 10 引脚设置为高电平 (GPIO_PIN_SET)。这会使连接到 PF10 的 LED 熄灭。

  • 蜂鸣器宏定义
#ifndef __BEEP_H
#define __BEEP_H
#include "sys.h"
//LED端口定义
#define BEEP PFout(8) // 蜂鸣器控制IO 
void BEEP_Init(void); //初始化

#endif

定义了一个宏 BEEP,用于控制蜂鸣器。PFout(8) 是一个宏或函数,通常用于访问 GPIO 端口 PF 的第 8 位。这个宏或函数会在 sys.h 或其他相关文件中定义。PFout(8) 可能是一个宏,用于设置或读取 GPIOF 的第 8 引脚的状态。

  • 蜂鸣器初始化函数
#include "beep.h"

// 初始化PF8为输出.并使能时钟        
// LED IO初始化
void BEEP_Init(void)
{
    GPIO_InitTypeDef GPIO_Initure;
    __HAL_RCC_GPIOF_CLK_ENABLE();           //开启GPIOF时钟
    GPIO_Initure.Pin = GPIO_PIN_8;          // PF8
    GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP;// 推挽输出
    GPIO_Initure.Pull = GPIO_PULLUP;        // 上拉
    GPIO_Initure.Speed = GPIO_SPEED_HIGH;   // 高速
    HAL_GPIO_Init(GPIOF, &GPIO_Initure);

    HAL_GPIO_WritePin(GPIOF,GPIO_PIN_8, GPIO_PIN_RESET); // 蜂鸣器对应引脚GPIOF8拉低,
}

这段代码初始化了 GPIOF 的第 8 引脚,以控制连接到该引脚的蜂鸣器。这里的配置包括:

  1. 使能 GPIOF 时钟__HAL_RCC_GPIOF_CLK_ENABLE() 用于启用 GPIOF 的时钟,使能后 GPIOF 引脚可以进行操作。

  2. 配置 GPIO 引脚

  • GPIO_Initure.Pin = GPIO_PIN_8;:设置要配置的引脚为 PF8。
  • GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP;:将引脚配置为推挽输出模式,以便能驱动蜂鸣器。
  • GPIO_Initure.Pull = GPIO_PULLUP;:配置上拉电阻,保持引脚在空闲时为高电平。
  • GPIO_Initure.Speed = GPIO_SPEED_HIGH;:设置引脚为高速,以提高响应速度。
  1. 初始化引脚HAL_GPIO_Init(GPIOF, &GPIO_Initure); 将上述配置应用到 GPIOF 的第 8 引脚。

  2. 设置引脚状态HAL_GPIO_WritePin(GPIOF, GPIO_PIN_8, GPIO_PIN_RESET); 将 PF8 引脚拉低,初始状态下关闭蜂鸣器。

这样设置后,你可以通过改变 PF8 引脚的电平来控制蜂鸣器的开关。

  • 主函数
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "beep.h"

int main(void)
{ 
    HAL_Init();                  // 初始化HAL库    
    Stm32_Clock_Init(336,8,2,7); // 设置时钟,168Mhz
    delay_init(168);             // 初始化延时函数
    LED_Init();                  // 初始化LED    
    BEEP_Init();                 // 初始化蜂鸣器

    while(1)
    {
        HAL_GPIO_WritePin(GPIOF, GPIO_PIN_9, GPIO_PIN_RESET); // DS0拉低,亮   等同LED0=0;
        HAL_GPIO_WritePin(GPIOF, GPIO_PIN_8, GPIO_PIN_RESET); // BEEP引脚拉低,等同BEEP=0;
        delay_ms(300);                                        // 延时300ms
        HAL_GPIO_WritePin(GPIOF, GPIO_PIN_9, GPIO_PIN_SET);   // DS0拉高,灭   等同LED0=1;
        HAL_GPIO_WritePin(GPIOF, GPIO_PIN_8, GPIO_PIN_SET);   // BEEP引脚拉高,等同BEEP=1;
        delay_ms(300);                                        
     }
}
  1. 初始化 HAL 库HAL_Init() 用于初始化 HAL 库,准备好硬件抽象层的功能。

  2. 设置时钟Stm32_Clock_Init(336, 8, 2, 7); 配置系统时钟为 168 MHz。这通常涉及设置 PLL(相位锁环)参数。

  3. 初始化延时函数delay_init(168); 设置延时函数所需的时钟频率。

  4. 初始化 LED 和蜂鸣器LED_Init()BEEP_Init() 分别用于初始化 LED 和蜂鸣器的 GPIO 引脚。

  5. 主循环

  • 点亮 LED 和蜂鸣器:将 PF9 和 PF8 引脚拉低,点亮 LED 和开启蜂鸣器。
  • 延时delay_ms(300); 使系统等待 300 毫秒。
  • 熄灭 LED 和蜂鸣器:将 PF9 和 PF8 引脚拉高,熄灭 LED 和关闭蜂鸣器。
  • 再次延时delay_ms(300); 使系统再等待 300 毫秒。

5. 小结

前面的章节倒是很容易,本章我们主要学习的还是控制GPIO输出,无他-就一个函数而-HAL_GPIO_WritePin(),我们可以详细地说明一下:

HAL_GPIO_WritePin() 是 STM32 HAL 库中用于操作 GPIO(通用输入输出)引脚的一个函数。它用于设置指定 GPIO 引脚的电平状态(高或低)。这个函数的详细说明如下:

函数原型

void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);

参数说明

  1. GPIOx:
  • 类型:GPIO_TypeDef*
  • 说明:指定要操作的 GPIO 端口。常见的端口包括 GPIOAGPIOBGPIOCGPIODGPIOEGPIOF, 等。
  1. GPIO_Pin:
  • 类型:uint16_t
  • 说明:指定要操作的 GPIO 引脚。可以是一个引脚的掩码,如 GPIO_PIN_0GPIO_PIN_1GPIO_PIN_2, 等。这些宏定义通常在 STM32 HAL 库的头文件中定义。
  1. PinState:
  • 类型:GPIO_PinState
  • 说明:设置 GPIO 引脚的状态。可以是以下两种状态之一:
    • GPIO_PIN_RESET:表示将引脚设置为低电平(0)。
    • GPIO_PIN_SET:表示将引脚设置为高电平(1)。

功能

HAL_GPIO_WritePin() 函数通过直接操作 GPIO 控制寄存器来设置引脚的电平状态。它会根据传入的 PinState 参数将指定的引脚设置为高电平或低电平。

示例

假设你要将 GPIOA 端口的第 5 号引脚设置为高电平,代码如下:

HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);

如果要将 GPIOB 端口的第 12 号引脚设置为低电平,代码如下:

HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);

应用场景

  • 点亮/熄灭 LED:通常使用 HAL_GPIO_WritePin() 来控制 LED 的开关状态。
  • 控制继电器:通过设置 GPIO 引脚来控制继电器的开关。
  • 驱动其他外设:可以用于控制其他外设的开关状态,例如马达、蜂鸣器等。

通过这个函数,你可以灵活地操作 STM32 微控制器的 GPIO 引脚,以满足各种应用需求。


2024.9.27 第一次修订,后期不再维护

posted @ 2024-09-27 15:15  hazy1k  阅读(17)  评论(0编辑  收藏  举报