buzzer模块
1 目的:
A 很多产品中都要使用蜂鸣器模块,有的产品中蜂鸣器只需要做为按键音,提示用户有按键按下,有的产品中蜂鸣器做为告警声,不同的警告有不同的蜂鸣音。
B 虽然蜂鸣器直接用MCU的GPIO控制即可,置IO高或低,蜂鸣器就会鸣叫或关闭,但是在有的产品中,它的控制却并不简单。例如:出现A告警以滴滴2声的方式鸣叫,出现B告警以滴滴滴3声的方式鸣叫,更有的产品,以某种方式鸣叫10次后停 止,所以要按以上方式控制好蜂鸣器其实并不简单,没有一两个小时激烈的脑力活动是做不出这些功能的,至少对我来说是这样。
C 综上,经过一番思考后特开发了以下蜂鸣器模块,支持以滴滴滴3声的方式鸣叫,鸣叫次数可以通过参数控制,参数为0xFFFF时一直鸣叫直至断电,支持普通的按键提示音,即短时间鸣叫后自动停止。
D 如果有多种类型的告警提示音,可以在 BUZZER_ALARM 结构体内在定义一个函数指针,在定义BUZZER_ALARM对象的时候赋值不同的告警处理函数即可 bzr_alarming_process()。
E 该模块使用方法,把 bzr_buzzing_process(); bzr_alarming_process();函数放入主循环中,在函数要启动蜂鸣器或使蜂鸣器发出告警音的地方直接调用bzr_buzzing(),bzr_alarming()即可。
2 代码:
#include "main.h" #include "buzzer.h" #include "stm32f1xx_hal.h" /* USER CODE BEGIN 0 */ #define portBUZZER_PORT GPIOA #define portBUZZER_PIN GPIO_PIN_6 uint8_t bzr_enabled; uint16_t bzr_duration; uint32_t bzr_time_stamp; void bzr_buzzing(uint16_t duration) { // OPEN the port corresponde to buzzer pin HAL_GPIO_WritePin(portBUZZER_PORT,portBUZZER_PIN,GPIO_PIN_SET); WRITE_REG(bzr_enabled,1); bzr_time_stamp = HAL_GetTick(); bzr_duration = duration; } void bzr_buzzing_process(void) //the main loop called this function every cycle { if(bzr_enabled){ if(( HAL_GetTick()- bzr_time_stamp)>bzr_duration){ //shut down the corresponde buzzer pin. HAL_GPIO_WritePin(portBUZZER_PORT,portBUZZER_PIN,GPIO_PIN_RESET); CLEAR_REG(bzr_enabled); } } } // type1: 滴-滴-滴 --- 滴-滴-滴 // type2: 滴--滴 -- 滴--滴 typedef struct{ uint8_t type;// uint16_t sound_time; uint16_t silent_time; }BUZZER_ALARM;//存在多种报警的时候报警函数分别处理。不同类型处理采用函数指针,在使能报警时,根据不同type的报警,指针指向不同类型的报警函数。 //为了不把问题复杂化,定义下面宏 //#define SOUND_TIME 200 //#define SLIENT_TIME 200 uint8_t bzr_alarm_enabled;//报警使能 uint32_t bzr_alarm_stamp;//报警使能时的时间戳 uint8_t bzr_alarm_state;//报警状态机 uint8_t bzr_alarm_times;//报警次数 uint16_t bzr_alarm_interval;//报警间隔 void bzr_alarming(uint16_t times, uint16_t interval) { WRITE_REG(bzr_alarm_enabled,1); bzr_alarm_stamp = HAL_GetTick(); bzr_alarm_state = 0; bzr_alarm_times = times; bzr_alarm_interval = interval; } BUZZER_ALARM bzr={ .type = 1, .sound_time = 60, .silent_time = 50, }; void bzr_alarming_process(void) //call this function every cycle { if(bzr_alarm_enabled){ if(bzr_alarm_times){ switch(bzr_alarm_state){ case 0://响 bzr_buzzing(bzr.sound_time); bzr_alarm_state=1; break; case 1://停 if((HAL_GetTick()-bzr_alarm_stamp) >( bzr.sound_time + bzr.silent_time)){ bzr_alarm_state=2; } break; case 2://响 bzr_buzzing(bzr.sound_time); bzr_alarm_state=3; break; case 3://停 if((HAL_GetTick()-bzr_alarm_stamp) >(bzr.sound_time+ bzr.silent_time+ bzr.sound_time + bzr.silent_time)){ bzr_alarm_state=4; } break; case 4://响 bzr_buzzing(bzr.sound_time); bzr_alarm_state=5; break; case 5://停 if((HAL_GetTick()-bzr_alarm_stamp) >( bzr.sound_time + bzr.silent_time+ bzr.sound_time + bzr.silent_time+bzr.sound_time+bzr_alarm_interval)){ bzr_alarm_stamp =HAL_GetTick(); bzr_alarm_state=0; bzr_alarm_times--; } break; } } else{ bzr_alarm_enabled =0; } } }