【应用C】C语言实现可配置带回调函数的蜂鸣器驱动


  如果你需要用蜂鸣器制造一段有节奏音乐的需求,则可以移植代码进行使用:

  • 代码所占code少于0.5K
  • 可移植性高,只需要提供底层PWM_Set()和配置对应音乐节奏节点
  • 注意:系统需要存在一个至少为10ms的时钟中断

01 - Buzzer.h

#ifndef __BUZZER_H__
#define __BUZZER_H__
#include "MCU.h"
 
typedef enum {
    beepOff = 0,
    beepButton,
    beepAlarm,
 
    beepMax
} buzzerMode_t;
 
typedef void (*fpBuzzerCallBack)(void);
/* 可以在SetMode后调用,每次SetMode会把cb置为NULL。设置后可以在对应Mode蜂鸣结束后回调函数cb */
extern void buzzerSetCallBackFunc(fpBuzzerCallBack cb);
 
extern void buzzerService_10ms(void);
extern void buzzerSetMode(buzzerMode_t Mode);
 
#endif

02 - Buzzer.c

#include "buzzer.h"
extern void PWM_SetFreq(uint16_t FreqHZ);
 
#define BuzzerMaxNode   4
 
/* 自定义音频节点 */
typedef struct {
    uint16_t FreqHZ;                /* 蜂鸣器频率 */
    uint8_t On;                     /* 打开时间(10ms单位) */
    uint8_t Off;                    /* 关闭时间(10ms单位) */
} buzzerNode;
 
/* 自定义一段音频 */
typedef struct {
    uint8_t DataLen;                /* Data的使用长度 */
    uint8_t RepeatCounter;          /* 重复的次数 */
    uint8_t RepeatIntervalTime;     /* 每次重复的间隔(10ms单位) */
    buzzerNode Data[BuzzerMaxNode]; /* 音频节点数组 */
} buzzerInfo_t;
 
 
code buzzerInfo_t buzzerButton = {
    1,
    0,
    0,
    {
        { 2600, 10, 0 },
        { 0, 0, 0 },
        { 0, 0, 0 },
        { 0, 0, 0 },
    },
};
 
code buzzerInfo_t buzzerAlarm = {
    2,
    3,
    50,
    {
        { 1400, 50, 50 },
        { 2600, 50, 50 },
        { 0, 0, 0 },
        { 0, 0, 0 },
    },
};
 
buzzerInfo_t code *buzzerTask[beepMax] = {
    NULL,
    &buzzerButton,
    &buzzerAlarm,
};
 
typedef struct {
    buzzerInfo_t Info;
    uint8_t DataIdx;
    uint8_t Status;
    uint8_t OnOffTimer;
    buzzerMode_t Mode;
    fpBuzzerCallBack CallBackFunc;
} buzzer_t;
buzzer_t buzzer;
 
void buzzerService_10ms(void)
{
    if (buzzer.DataIdx < buzzer.Info.DataLen) {
        buzzer.OnOffTimer++;
        switch (buzzer.Status) {
            case 0:
                PWM_SetFreq(buzzer.Info.Data[buzzer.DataIdx].FreqHZ);
                buzzer.OnOffTimer = 0;
                buzzer.Status++;
                break;
            case 1:
                if (buzzer.OnOffTimer >= buzzer.Info.Data[buzzer.DataIdx].On) {
                    PWM_SetFreq(0);
                    buzzer.OnOffTimer = 0;
                    buzzer.Status++;
                }
                break;
            case 2:
                if (buzzer.OnOffTimer >= buzzer.Info.Data[buzzer.DataIdx].Off) {
                    buzzer.DataIdx++;
                    if (buzzer.DataIdx < buzzer.Info.DataLen) {
                        PWM_SetFreq(buzzer.Info.Data[buzzer.DataIdx].FreqHZ);
                        buzzer.OnOffTimer = 0;
                        buzzer.Status = 1;
                    } else {
                        PWM_SetFreq(0);
                        if (buzzer.Info.RepeatCounter) {
                            buzzer.OnOffTimer = 0;
                            buzzer.DataIdx = 0;
                            buzzer.Status = 3;
                        } else {
                            if (buzzer.CallBackFunc) {
                                buzzer.CallBackFunc();
                            }
                            memset(&buzzer, 0, sizeof(buzzer_t));
                        }
                    }
                }
                break;
            case 3:
                if (buzzer.OnOffTimer >= buzzer.Info.RepeatIntervalTime) {
                    buzzer.Info.RepeatCounter--;
                    buzzer.OnOffTimer = 0;
                    buzzer.DataIdx = 0;
                    buzzer.Status = 0;
                }
                break;
            default:
                break;
        }
    } else {
        PWM_SetFreq(0);
    }
}
 
/* SetMode后调用,可以在对应Mode蜂鸣结束后回调函数cb */
void buzzerSetCallBackFunc(fpBuzzerCallBack cb)
{
    buzzer.CallBackFunc = cb;
}
 
void buzzerSetMode(buzzerMode_t Mode)
{
    if ((Mode > beepOff) && (Mode < beepMax)) {
        if (buzzer.Mode != Mode) {
			memset(&buzzer, 0, sizeof(buzzer_t));
			memcpy(&buzzer.Info, buzzerTask[Mode], sizeof(buzzerInfo_t));
			buzzer.Mode = Mode;
        }
    } else {
        memset(&buzzer, 0, sizeof(buzzer_t));
    }
}
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值