新时代驱动代码写法(以蜂鸣器模块为例)
前言
当我们现在有一个需求,需要控制蜂鸣器模块的鸣叫时,在今天我们已经完全可以借助AI之力来帮助我们了,但是想要更好的利用ai我们就需要懂得一些相关知识,这样才能写出一个更能满足我们要求的代码。比如你要先知道蜂鸣器模块分为有源蜂鸣器和无源蜂鸣器,以及蜂鸣器模块有几个引脚,是用的通信协议控制还是直接输出高低电平控制等等,但是如果你不知道这些也没关系,只要你会用提示词这些也都不是问题,下面就以我让ai帮我写一个蜂鸣器驱动为例
下面的buzzer.c和buzzer.h主播已经试过了,是可以直接移植使用的
Step1(上淘宝)
首先拿到你直接买的模块去淘宝上搜索一下也能了解到一些相关信息

然后我们就可以了解到这个模块一共3个引脚(VCC、IO、GND),是通过单片机引脚输出高或低电平控制的
Step2(巧问AI)
这里直接放出我的提示词给大家参考,大家要是还有什么好用的提示词可以评论区一起交流
推荐大家问gemini,我当时GPT,Claude,gemini都用了,感觉gemini效果最好。如果你不知道怎么使用Gemini,可以看一下我这篇文章
使用 Gemini 的简单教程(学生认证账号方案)-CSDN博客
你好,我现在想请你帮我写一个可以用在STM32中的蜂鸣器模块的库,就是当我单片机的型号变量或者蜂鸣器的触发电平变了之后我能够通通过修改几个参数然后就能够继续用,你能懂我的意思吗,然后尽量高内聚低耦合,然后有些地方我可能说的不清除,现在你有什么想和我交流的吗
然后正常来说ai就会问你一些东西,然后你就回答他问你的就行
继续回复Gemini
确认蜂鸣器类型(最重要)-----我的是有源蜂鸣器 运行环境与依赖—STM32 HAL库 功能复杂度—Level 2 (实用版)或者Level 3 (高级异步版)
得到Gemini给我们生成的代码,这里给大家参考
Code
buzzer.h
#ifndef __BUZZER_H
#define __BUZZER_H
#include "main.h" // 包含HAL库定义
// 定义蜂鸣器的触发电平
typedef enum {
BUZZER_ACTIVE_LOW = 0, // 低电平触发(响)
BUZZER_ACTIVE_HIGH = 1 // 高电平触发(响)
} Buzzer_ActiveLevel_t;
// 蜂鸣器的工作状态(内部使用)
typedef enum {
BUZZER_STATE_IDLE = 0, // 空闲
BUZZER_STATE_ON, // 正在响
BUZZER_STATE_OFF_WAIT // 响完了,正在等待间隔(用于连续鸣叫)
} Buzzer_State_t;
// 蜂鸣器句柄对象(核心结构体)
typedef struct {
// --- 硬件配置 (初始化时设置) ---
GPIO_TypeDef* GPIOx; // GPIO端口,如 GPIOA
uint16_t GPIO_Pin; // GPIO引脚,如 GPIO_PIN_5
Buzzer_ActiveLevel_t ActiveLevel; // 有效电平
// --- 运行时状态 (用户无需手动修改) ---
Buzzer_State_t State; // 当前状态
uint32_t StartTime; // 状态开始的时间戳
uint32_t OnDuration; // 响持续时间 (ms)
uint32_t OffDuration; // 停顿持续时间 (ms)
uint16_t BeepCount; // 剩余鸣叫次数
} Buzzer_HandleTypeDef;
// --- 函数接口 ---
// 初始化(绑定GPIO)
void Buzzer_Init(Buzzer_HandleTypeDef* hbuzzer, GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, Buzzer_ActiveLevel_t ActiveLevel);
// 核心处理函数(需在主循环 while(1) 中不断调用)
void Buzzer_Process(Buzzer_HandleTypeDef* hbuzzer);
// 功能1:简单响一声 (非阻塞)
void Buzzer_Beep(Buzzer_HandleTypeDef* hbuzzer, uint32_t duration_ms);
// 功能2:复杂模式 (响on_ms,停off_ms,循环count次)
void Buzzer_BeepPattern(Buzzer_HandleTypeDef* hbuzzer, uint32_t on_ms, uint32_t off_ms, uint16_t count);
// 功能3:强制停止
void Buzzer_Stop(Buzzer_HandleTypeDef* hbuzzer);
#endif
**buzzer.c **
#include "buzzer.h"
// 内部函数:设置物理电平
static void Buzzer_WritePin(Buzzer_HandleTypeDef* hbuzzer, uint8_t state) {
// state: 1=响, 0=不响
GPIO_PinState pinState;
if (hbuzzer->ActiveLevel == BUZZER_ACTIVE_HIGH) {
// 高电平触发:响=Set, 不响=Reset
pinState = (state == 1) ? GPIO_PIN_SET : GPIO_PIN_RESET;
} else {
// 低电平触发:响=Reset, 不响=Set
pinState = (state == 1) ? GPIO_PIN_RESET : GPIO_PIN_SET;
}
HAL_GPIO_WritePin(hbuzzer->GPIOx, hbuzzer->GPIO_Pin, pinState);
}
// 初始化
void Buzzer_Init(Buzzer_HandleTypeDef* hbuzzer, GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, Buzzer_ActiveLevel_t ActiveLevel) {
hbuzzer->GPIOx = GPIOx;
hbuzzer->GPIO_Pin = GPIO_Pin;
hbuzzer->ActiveLevel = ActiveLevel;
hbuzzer->State = BUZZER_STATE_IDLE;
hbuzzer->BeepCount = 0;
// 初始化后默认关闭
Buzzer_WritePin(hbuzzer, 0);
}
// 简单响一声
void Buzzer_Beep(Buzzer_HandleTypeDef* hbuzzer, uint32_t duration_ms) {
Buzzer_BeepPattern(hbuzzer, duration_ms, 0, 1);
}
// 复杂模式设定
void Buzzer_BeepPattern(Buzzer_HandleTypeDef* hbuzzer, uint32_t on_ms, uint32_t off_ms, uint16_t count) {
hbuzzer->OnDuration = on_ms;
hbuzzer->OffDuration = off_ms;
hbuzzer->BeepCount = count;
if (count > 0) {
// 立即开始响第一次
hbuzzer->State = BUZZER_STATE_ON;
hbuzzer->StartTime = HAL_GetTick(); // 记录当前时间
Buzzer_WritePin(hbuzzer, 1); // 物理开启
}
}
// 强制停止
void Buzzer_Stop(Buzzer_HandleTypeDef* hbuzzer) {
hbuzzer->State = BUZZER_STATE_IDLE;
hbuzzer->BeepCount = 0;
Buzzer_WritePin(hbuzzer, 0);
}
// 核心状态机(放在 while(1) 里)
void Buzzer_Process(Buzzer_HandleTypeDef* hbuzzer) {
if (hbuzzer->State == BUZZER_STATE_IDLE) {
return; // 空闲状态,啥也不做
}
// 获取当前时间
uint32_t now = HAL_GetTick();
switch (hbuzzer->State) {
case BUZZER_STATE_ON:
// 检查响的时间是否到了
if (now - hbuzzer->StartTime >= hbuzzer->OnDuration) {
// 时间到,关闭蜂鸣器
Buzzer_WritePin(hbuzzer, 0);
hbuzzer->BeepCount--; // 次数减1
if (hbuzzer->BeepCount > 0) {
// 如果还有剩余次数,进入等待间隔状态
hbuzzer->State = BUZZER_STATE_OFF_WAIT;
hbuzzer->StartTime = now;
} else {
// 没有次数了,回到空闲
hbuzzer->State = BUZZER_STATE_IDLE;
}
}
break;
case BUZZER_STATE_OFF_WAIT:
// 检查间隔等待时间是否到了
if (now - hbuzzer->StartTime >= hbuzzer->OffDuration) {
// 时间到,再次开启蜂鸣器
Buzzer_WritePin(hbuzzer, 1);
hbuzzer->State = BUZZER_STATE_ON;
hbuzzer->StartTime = now;
}
break;
default:
hbuzzer->State = BUZZER_STATE_IDLE;
break;
}
}
如何使用(高内聚低耦合的体现)
假设你用 CubeMX 配置了 PB0 也是蜂鸣器引脚,默认高电平。
在 main.c 中:
/* USER CODE BEGIN Includes */
#include "buzzer.h"
/* USER CODE END Includes */
/* USER CODE BEGIN PV */
// 1. 定义一个句柄变量(这就是对象)
Buzzer_HandleTypeDef myBuzzer;
/* USER CODE END PV */
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init(); // CubeMX生成的初始化
// 2. 初始化你的蜂鸣器对象 (这一步实现了硬件解耦)
// 假设你的蜂鸣器接在 PB0,且是 高电平触发(Active High)
Buzzer_Init(&myBuzzer, GPIOB, GPIO_PIN_0, BUZZER_ACTIVE_HIGH);
// 场景A:开机响一声,长达 500ms
Buzzer_Beep(&myBuzzer, 500);
while (1) {
// 3. 必须在循环里持续调用处理函数(它是非阻塞的,运行极快)
Buzzer_Process(&myBuzzer);
// --- 模拟业务逻辑 ---
// 场景B:模拟按键按下,滴滴两声(响100ms, 停100ms, 重复2次)
if (Read_Key_Example() == PRESSED) {
Buzzer_BeepPattern(&myBuzzer, 100, 100, 2);
}
// 场景C:严重报警,急促响5次
if (Error_Occured()) {
Buzzer_BeepPattern(&myBuzzer, 50, 50, 5);
}
}
}
为什么这符合你的要求?
- 高内聚: 所有关于蜂鸣器的逻辑(怎么响、响多久、什么时候停)全在
buzzer.c内部消化了。main函数只管发号施令(“响3声”)。 - 低耦合:
- 换引脚了? 只需要在
main.c的Buzzer_Init里把GPIOB改成GPIOA。 - 换蜂鸣器了? 原来是高电平触发,现在买了个低电平触发的?只需要把
BUZZER_ACTIVE_HIGH改成BUZZER_ACTIVE_LOW。 - 无需改动库文件: 你完全不需要打开
buzzer.c去修改任何代码。
- 换引脚了? 只需要在
- 非阻塞: 你看
Buzzer_BeepPattern里没有HAL_Delay。它只是设置了状态就返回了。真正的延时是在while(1)的Buzzer_Process里通过对比系统时间戳完成的。这意味着蜂鸣器在响的时候,你的 OLED 屏幕依然可以刷新,按键依然可以响应。
Step3(移植到自己的工程中去)
这里就不做演示了,因为每个人工程可能不一样,但是只要之前移植过一些东西那么移植这个就没有问题。
因为我这篇文章主要是想让大家知道现在可以让ai来写驱动的,就不用再画时间自己写了,我们就是监工了,但是要像让AI能很好的完成任务那么我们的提示词使用也是大有文章的
更多推荐



所有评论(0)