行业资讯
蜂鸣器驱动——支持连续、单次与模式蜂鸣的通用方案
问题背景蜂鸣器是嵌入式项目中最常用的声音反馈器件。看似简单的响一下、停一下在实际产品中往往需要多种模式开机长鸣、按键短促提示、报警间歇响、故障连续报警。直接用 HAL 库写会导致主循环中充斥时间判断逻辑。本文给出一个结构体驱动的蜂鸣器模块抽象出连续模式、单次蜂鸣和模式播放三种工作模式减少调用方的状态管理负担。驱动设计三种工作模式模式枚举值行为连续模式BUZZER_MODE_CONTINUOUS调用buzzer_on/off手动控制驱动不干预单次蜂鸣BUZZER_MODE_BEEP调用buzzer_beep(handle, 200)响 200ms 后自动关闭模式播放BUZZER_MODE_PATTERN调用buzzer_beep_pattern(handle, 3, 100, 100)响 3 声每声 100ms间隔 100ms状态机核心逻辑buzzer_update是驱动的核心需要在主循环或定时器中周期性调用。它根据当前模式自动切换蜂鸣器开关状态BEEP 模式打开蜂鸣器到达beep_duration后自动关闭计数清零PATTERN 模式在开/关状态之间按beep_duration/beep_interval交替切换直到beep_count耗尽数据结构typedef struct { uint8_t is_initialized; buzzer_gpio_t buzzer_pin; // GPIO 配置端口、引脚、有效电平、写函数 buzzer_data_t data; // 运行状态模式、计时、计数 uint32_t (*get_tick)(void); // 系统时钟获取函数指针 } buzzer_handle_t;通过get_tick函数指针解耦系统时钟来源HAL_GetTick、定时器、RTOS tick 均可。API 参考函数说明buzzer_init(handle)初始化句柄默认关闭buzzer_on(handle)打开蜂鸣器连续模式buzzer_off(handle)关闭蜂鸣器buzzer_toggle(handle)翻转蜂鸣器状态buzzer_beep(handle, duration_ms)单次蜂鸣指定时长buzzer_beep_pattern(handle, count, duration_ms, interval_ms)模式蜂鸣buzzer_update(handle)状态更新需在主循环/定时器中周期调用buzzer_get_state(handle)获取当前开关状态使用示例#include driver_buzzer.h buzzer_handle_t buzzer; int main(void) { // 初始化蜂鸣器GPIOB_PIN_0高电平有效 buzzer.buzzer_pin.port GPIOB; buzzer.buzzer_pin.pin GPIO_PIN_0; buzzer.buzzer_pin.active_level 1; buzzer.buzzer_pin.write_pin (void(*)(GPIO_TypeDef*,uint16_t,GPIO_PinState))HAL_GPIO_WritePin; buzzer.get_tick (uint32_t(*)(void))HAL_GetTick; buzzer_init(buzzer); // 1. 连续模式——手动控制 buzzer_on(buzzer); HAL_Delay(1000); buzzer_off(buzzer); // 2. 单次蜂鸣 200ms buzzer_beep(buzzer, 200); // 3. 三短声报警模式 buzzer_beep_pattern(buzzer, 3, 100, 100); while (1) { buzzer_update(buzzer); // 必须在主循环中周期调用 HAL_Delay(10); } }注意事项buzzer_update必须在主循环或定时器中断中周期性调用建议 10~50Hz否则定时自动关闭和模式切换不会生效active_level字段区分高电平有效和低电平有效的硬件设计模式播放时beep_count参数内部会转换为总开关次数count × 2 - 1外部调用时只需传入响几声所有 API 都做了空指针检查传入 NULL 会静默返回总结本驱动通过一个简洁的状态机把蜂鸣器的三种典型使用场景封装到位。连续模式交给调用方自由控制单次和模式蜂鸣则由buzzer_update自动管理时序大幅简化主循环逻辑。完整源码driver_buzzer.h/** * file driver_buzzer.h * brief 蜂鸣器驱动头文件 * author 江 * version V1.0.0 * date 2026.03.19 */ #ifndef __DRIVER_BUZZER_H #define __DRIVER_BUZZER_H #include stm32f1xx_hal.h // 蜂鸣器状态定义 typedef enum { BUZZER_OFF 0, // 蜂鸣器关闭 BUZZER_ON 1 // 蜂鸣器开启 } buzzer_state_t; // 蜂鸣器模式定义 typedef enum { BUZZER_MODE_CONTINUOUS 0, // 连续模式 BUZZER_MODE_BEEP 1, // 蜂鸣模式 BUZZER_MODE_PATTERN 2 // 模式播放 } buzzer_mode_t; // GPIO引脚配置结构体 typedef struct { GPIO_TypeDef* port; // GPIO端口 uint16_t pin; // GPIO引脚 uint8_t active_level; // 有效电平0-低电平有效1-高电平有效 void (*write_pin)(GPIO_TypeDef* port, uint16_t pin, GPIO_PinState state); // 写引脚函数指针 } buzzer_gpio_t; // 蜂鸣器数据结构体 typedef struct { buzzer_state_t state; // 当前状态 buzzer_mode_t mode; // 当前模式 uint16_t beep_duration; // 蜂鸣持续时间ms uint16_t beep_interval; // 蜂鸣间隔时间ms uint8_t beep_count; // 蜂鸣次数 uint32_t last_toggle_time; // 上次切换时间 } buzzer_data_t; /** * brief 蜂鸣器句柄结构体 */ typedef struct { uint8_t is_initialized; // 是否已初始化 buzzer_gpio_t buzzer_pin; // 蜂鸣器GPIO配置 buzzer_data_t data; // 蜂鸣器数据 uint32_t (*get_tick)(void); // 获取系统时间函数指针 } buzzer_handle_t; // 函数声明 void buzzer_init(buzzer_handle_t* handle); void buzzer_on(buzzer_handle_t* handle); void buzzer_off(buzzer_handle_t* handle); void buzzer_toggle(buzzer_handle_t* handle); void buzzer_beep(buzzer_handle_t* handle, uint16_t duration_ms); void buzzer_beep_pattern(buzzer_handle_t* handle, uint8_t count, uint16_t duration_ms, uint16_t interval_ms); void buzzer_update(buzzer_handle_t* handle); buzzer_state_t buzzer_get_state(const buzzer_handle_t* handle); uint8_t buzzer_is_initialized(const buzzer_handle_t* handle); #endif /* __DRIVER_BUZZER_H */ driver_buzzer.c/** * file driver_buzzer.c * brief 蜂鸣器驱动程序 * author 江 * version V1.0.0 * date 2026.03.19 */ #include driver_buzzer.h /** * brief 初始化蜂鸣器 * param handle: 蜂鸣器句柄指针 * retval 无 */ void buzzer_init(buzzer_handle_t* handle) { if (handle NULL) { return; } // 初始化数据结构 handle-data.state BUZZER_OFF; handle-data.mode BUZZER_MODE_CONTINUOUS; handle-data.beep_duration 0; handle-data.beep_interval 0; handle-data.beep_count 0; handle-data.last_toggle_time 0; handle-is_initialized 1; // 初始化时关闭蜂鸣器 buzzer_off(handle); } /** * brief 开启蜂鸣器 * param handle: 蜂鸣器句柄指针 * retval 无 */ void buzzer_on(buzzer_handle_t* handle) { if (handle NULL || !handle-is_initialized) { return; } if (handle-buzzer_pin.active_level) { handle-buzzer_pin.write_pin(handle-buzzer_pin.port, handle-buzzer_pin.pin, GPIO_PIN_SET); } else { handle-buzzer_pin.write_pin(handle-buzzer_pin.port, handle-buzzer_pin.pin, GPIO_PIN_RESET); } handle-data.state BUZZER_ON; } /** * brief 关闭蜂鸣器 * param handle: 蜂鸣器句柄指针 * retval 无 */ void buzzer_off(buzzer_handle_t* handle) { if (handle NULL || !handle-is_initialized) { return; } if (handle-buzzer_pin.active_level) { handle-buzzer_pin.write_pin(handle-buzzer_pin.port, handle-buzzer_pin.pin, GPIO_PIN_RESET); } else { handle-buzzer_pin.write_pin(handle-buzzer_pin.port, handle-buzzer_pin.pin, GPIO_PIN_SET); } handle-data.state BUZZER_OFF; } /** * brief 切换蜂鸣器状态 * param handle: 蜂鸣器句柄指针 * retval 无 */ void buzzer_toggle(buzzer_handle_t* handle) { if (handle NULL || !handle-is_initialized) { return; } if (handle-data.state BUZZER_ON) { buzzer_off(handle); } else { buzzer_on(handle); } } /** * brief 蜂鸣器单次蜂鸣 * param handle: 蜂鸣器句柄指针 * param duration_ms: 蜂鸣持续时间毫秒 * retval 无 */ void buzzer_beep(buzzer_handle_t* handle, uint16_t duration_ms) { if (handle NULL || !handle-is_initialized || duration_ms 0) { return; } handle-data.mode BUZZER_MODE_BEEP; handle-data.beep_duration duration_ms; handle-data.beep_count 1; handle-data.last_toggle_time handle-get_tick(); buzzer_on(handle); } /** * brief 蜂鸣器模式蜂鸣 * param handle: 蜂鸣器句柄指针 * param count: 蜂鸣次数 * param duration_ms: 每次蜂鸣持续时间毫秒 * param interval_ms: 蜂鸣间隔时间毫秒 * retval 无 */ void buzzer_beep_pattern(buzzer_handle_t* handle, uint8_t count, uint16_t duration_ms, uint16_t interval_ms) { if (handle NULL || !handle-is_initialized || count 0 || duration_ms 0) { return; } handle-data.mode BUZZER_MODE_PATTERN; handle-data.beep_duration duration_ms; handle-data.beep_interval interval_ms; handle-data.beep_count count * 2 - 1; // 计算总的开关次数 handle-data.last_toggle_time handle-get_tick(); buzzer_on(handle); } /** * brief 蜂鸣器状态更新需要在主循环或定时器中调用 * param handle: 蜂鸣器句柄指针 * retval 无 */ void buzzer_update(buzzer_handle_t* handle) { if (handle NULL || !handle-is_initialized) { return; } uint32_t current_time handle-get_tick(); uint32_t elapsed_time current_time - handle-data.last_toggle_time; switch (handle-data.mode) { case BUZZER_MODE_BEEP: if (handle-data.state BUZZER_ON elapsed_time handle-data.beep_duration) { buzzer_off(handle); handle-data.beep_count 0; } break; case BUZZER_MODE_PATTERN: if (handle-data.beep_count 0) { if (handle-data.state BUZZER_ON elapsed_time handle-data.beep_duration) { buzzer_off(handle); handle-data.last_toggle_time current_time; handle-data.beep_count--; } else if (handle-data.state BUZZER_OFF elapsed_time handle-data.beep_interval) { if (handle-data.beep_count 0) { buzzer_on(handle); handle-data.last_toggle_time current_time; handle-data.beep_count--; } } } else { // 模式播放完成确保蜂鸣器关闭并切换到连续模式 if (handle-data.state BUZZER_ON) { buzzer_off(handle); } handle-data.mode BUZZER_MODE_CONTINUOUS; } break; case BUZZER_MODE_CONTINUOUS: default: // 连续模式不需要自动更新 break; } } /** * brief 获取蜂鸣器当前状态 * param handle: 蜂鸣器句柄指针 * retval buzzer_state_t: 蜂鸣器状态 */ buzzer_state_t buzzer_get_state(const buzzer_handle_t* handle) { if (handle NULL || !handle-is_initialized) { return BUZZER_OFF; } return handle-data.state; } /** * brief 检查蜂鸣器是否已初始化 * param handle: 蜂鸣器句柄指针 * retval uint8_t: 1-已初始化0-未初始化 */ uint8_t buzzer_is_initialized(const buzzer_handle_t* handle) { if (handle NULL) { return 0; } return handle-is_initialized; }
郑州网站建设
网页设计
企业官网