使用庫函數控制蜂鳴器(STC8)
在STC8系列單片機中,可以通過庫函數或直接操作寄存器來控制蜂鳴器。以下是基于STC8庫函數的常用方法:
GPIO板蜂鳴器
#include "GPIO.h"
#include "Delay.h"void GPIO_config() { GPIO_InitTypeDef info;info.Mode = GPIO_OUT_PP; // 推挽輸出info.Pin = GPIO_Pin_0; // 引腳GPIO_Inilize(GPIO_P0, &info);// 拉低引腳P00 = 0;
}void main() {u16 i; // 16位GPIO_config(); // 周期:高低電平和 2ms// 頻率:周期的倒數 1s/2ms ===> 1000ms/2ms = 500HZ // 1次循環是2ms,持續2s,控制多少次 2000ms/2ms = 1000for (i = 0; i < 1000; i++) {P00 = 1;delay_ms(1);P00 = 0;delay_ms(1);}while (1){delay_ms(250);}
}
pwm版蜂鳴器
#include "GPIO.h"
#include "Delay.h"
#include "NVIC.h" // 中斷配置
#include "Switch.h" // 引腳切換
#include "STC8H_PWM.h"void GPIO_config() { //推挽輸出 P00P0_MODE_OUT_PP(GPIO_Pin_0); // 推挽輸出默認是高電平P00 = 0; // 拉低
}// PWMB 配置
// #define PERIOD (MAIN_Fosc / 523)
void PWM_config(u16 hz) // hz為0,停止,不為0, 播放的頻率
{PWMx_InitDefine PWMx_InitStructure;u16 Period;if (hz != 0) Period = (MAIN_Fosc / hz);// 配置PWM6PWMx_InitStructure.PWM_Mode = CCMRn_PWM_MODE1; //模式, CCMRn_FREEZE,CCMRn_MATCH_VALID,CCMRn_MATCH_INVALID,CCMRn_ROLLOVER,CCMRn_FORCE_INVALID,CCMRn_FORCE_VALID,CCMRn_PWM_MODE1,CCMRn_PWM_MODE2PWMx_InitStructure.PWM_Duty = 0.5 * Period; //PWM占空比時間, 0~PeriodPWMx_InitStructure.PWM_EnoSelect = ENO5P; //輸出通道選擇, ENO1P,ENO1N,ENO2P,ENO2N,ENO3P,ENO3N,ENO4P,ENO4N / ENO5P,ENO6P,ENO7P,ENO8PPWM_Configuration(PWM5, &PWMx_InitStructure); //初始化PWM, PWMA,PWMB// 配置PWMBPWMx_InitStructure.PWM_Period = Period - 1; //周期時間, 0~65535PWMx_InitStructure.PWM_DeadTime = 0; //死區發生器設置, 0~255if (hz != 0) {PWMx_InitStructure.PWM_MainOutEnable= ENABLE; //主輸出使能, ENABLE,DISABLEPWMx_InitStructure.PWM_CEN_Enable = ENABLE; //使能計數器, ENABLE,DISABLE} else {PWMx_InitStructure.PWM_MainOutEnable= DISABLE; //主輸出使能, ENABLE,DISABLEPWMx_InitStructure.PWM_CEN_Enable = DISABLE; //使能計數器, ENABLE,DISABLE}PWM_Configuration(PWMB, &PWMx_InitStructure); //初始化PWM通用寄存器, PWMA,PWMB// 切換PWM通道PWM5_SW(PWM5_SW_P00); // 初始化PWMB的中斷NVIC_PWM_Init(PWMB,DISABLE,Priority_0);
}void main() {// C D E F G A B C`u16 hz[] = {523, 587, 659, 698, 784, 880, 988, 1047};// C` D` E` F` G` A` B` C``//u16 hz[] = {1047, 1175, 1319, 1397, 1568, 1760, 1976, 2093};u8 i;EAXSFR(); /* 擴展寄存器訪問使能 */GPIO_config(); // GPIO配置for (i = 0; i < 8; i++) {PWM_config(hz[i]); // PWM配置delay_ms(250);delay_ms(250);}PWM_config(0); // 停止while (1){}
}
生成脈沖信號驅動有源蜂鳴器
對于需脈沖驅動的有源蜂鳴器,可使用延時函數生成PWM信號:
// PWMB 配置
// #define PERIOD (MAIN_Fosc / 523)
void PWM_config(u16 hz) // hz為0,停止,不為0, 播放的頻率
{PWMx_InitDefine PWMx_InitStructure;u16 Period;if (hz != 0) Period = (MAIN_Fosc / hz);// 配置PWM6PWMx_InitStructure.PWM_Mode = CCMRn_PWM_MODE1; //模式, CCMRn_FREEZE,CCMRn_MATCH_VALID,CCMRn_MATCH_INVALID,CCMRn_ROLLOVER,CCMRn_FORCE_INVALID,CCMRn_FORCE_VALID,CCMRn_PWM_MODE1,CCMRn_PWM_MODE2PWMx_InitStructure.PWM_Duty = 0.5 * Period; //PWM占空比時間, 0~PeriodPWMx_InitStructure.PWM_EnoSelect = ENO5P; //輸出通道選擇, ENO1P,ENO1N,ENO2P,ENO2N,ENO3P,ENO3N,ENO4P,ENO4N / ENO5P,ENO6P,ENO7P,ENO8PPWM_Configuration(PWM5, &PWMx_InitStructure); //初始化PWM, PWMA,PWMB// 配置PWMBPWMx_InitStructure.PWM_Period = Period - 1; //周期時間, 0~65535PWMx_InitStructure.PWM_DeadTime = 0; //死區發生器設置, 0~255if (hz != 0) {PWMx_InitStructure.PWM_MainOutEnable= ENABLE; //主輸出使能, ENABLE,DISABLEPWMx_InitStructure.PWM_CEN_Enable = ENABLE; //使能計數器, ENABLE,DISABLE} else {PWMx_InitStructure.PWM_MainOutEnable= DISABLE; //主輸出使能, ENABLE,DISABLEPWMx_InitStructure.PWM_CEN_Enable = DISABLE; //使能計數器, ENABLE,DISABLE}PWM_Configuration(PWMB, &PWMx_InitStructure); //初始化PWM通用寄存器, PWMA,PWMB// 切換PWM通道PWM5_SW(PWM5_SW_P00); // 初始化PWMB的中斷NVIC_PWM_Init(PWMB,DISABLE,Priority_0);
}PWM_config(523);
使用數組中的頻率驅動蜂鳴器
若需驅動無源蜂鳴器,需通過定時器生成特定頻率的方波:
#include "Buzzer.h"//這個是我封裝的庫函數// PWMB 配置
static void PWM_config(u16 hz) // hz為0,停止,不為0, 播放的頻率
{PWMx_InitDefine PWMx_InitStructure;u16 Period;if (hz != 0) Period = (MAIN_Fosc / hz);// 配置PWM6PWMx_InitStructure.PWM_Mode = CCMRn_PWM_MODE1; //模式, CCMRn_FREEZE,CCMRn_MATCH_VALID,CCMRn_MATCH_INVALID,CCMRn_ROLLOVER,CCMRn_FORCE_INVALID,CCMRn_FORCE_VALID,CCMRn_PWM_MODE1,CCMRn_PWM_MODE2PWMx_InitStructure.PWM_Duty = 0.5 * Period; //PWM占空比時間, 0~PeriodPWMx_InitStructure.PWM_EnoSelect = ENO5P; //輸出通道選擇, ENO1P,ENO1N,ENO2P,ENO2N,ENO3P,ENO3N,ENO4P,ENO4N / ENO5P,ENO6P,ENO7P,ENO8PPWM_Configuration(PWM5, &PWMx_InitStructure); //初始化PWM, PWMA,PWMB// 配置PWMBPWMx_InitStructure.PWM_Period = Period - 1; //周期時間, 0~65535PWMx_InitStructure.PWM_DeadTime = 0; //死區發生器設置, 0~255if (hz != 0) {PWMx_InitStructure.PWM_MainOutEnable= ENABLE; //主輸出使能, ENABLE,DISABLEPWMx_InitStructure.PWM_CEN_Enable = ENABLE; //使能計數器, ENABLE,DISABLE} else {PWMx_InitStructure.PWM_MainOutEnable= DISABLE; //主輸出使能, ENABLE,DISABLEPWMx_InitStructure.PWM_CEN_Enable = DISABLE; //使能計數器, ENABLE,DISABLE}PWM_Configuration(PWMB, &PWMx_InitStructure); //初始化PWM通用寄存器, PWMA,PWMB// 切換PWM通道PWM5_SW(PWM5_SW_P00); // 初始化PWMB的中斷NVIC_PWM_Init(PWMB,DISABLE,Priority_0);
}// 初始化
void Buzzer_init() {EAXSFR(); /* 擴展寄存器訪問使能 *///推挽輸出 P00P0_MODE_OUT_PP(GPIO_Pin_0); // 推挽輸出默認是高電平P00 = 0; // 拉低
}// 按照指定頻率播放
void Buzzer_play(u16 hz_value) {if (hz_value == 0) return;PWM_config(hz_value);
}u16 hz[] = {523 * 1, 587 * 1, 659 * 1, 698 * 1, 784 * 1, 880 * 1, 988 * 1, 523 * 2, 587 * 2, 659 * 2, 698 * 2, 784 * 2, 880 * 2, 988 * 2, 523 * 4, 587 * 4, 659 * 4, 698 * 4, 784 * 4, 880 * 4, 988 * 4, 523 * 8, 587 * 8, 659 * 8, 698 * 8, 784 * 8, 880 * 8, 988 * 8,
};// 按照指定音節播放 1 2 3 4 5 6 7 8 ……
void Buzzer_beep(u8 hz_idx) {if (hz_idx == 0) return;PWM_config(hz[hz_idx - 1]);
}// 停止播放
void Buzzer_stop() {PWM_config(0);
}void delay_ms_pro(unsigned int ms) {do{delay_ms(1);}while(--ms);
}#define L1 1
#define L2 2
#define L3 3
#define L4 4
#define L5 5
#define L6 6
#define L7 7#define N0 0#define N1 L1 + 7
#define N2 L2 + 7
#define N3 L3 + 7
#define N4 L4 + 7
#define N5 L5 + 7
#define N6 L6 + 7
#define N7 L7 + 7#define H1 N1 + 7
#define H2 N2 + 7
#define H3 N3 + 7
#define H4 N4 + 7
#define H5 N5 + 7
#define H6 N6 + 7
#define H7 N7 + 7u8 code notes[] = {N6, N7, H1, N7, H1, H3, N7, N3, N3, N6, N5, N6, H1, N5, N0, N3, N3, N4, N3, N4, H1,N3, N0, H1, H1, H1, N7, N4, N4, N7, N7, N0, N6, N7, H1, N7, H1, H3, N7, N0, N3, N3, N6, N5, N6, H1,N5, N0, N3, N4, H1, N7, N7, H1, H2, H2, H3, H1, N0, H1, N7, N6, N6, N7, N5, N6, N0, H1, H2, H3, H2, H3, H5,H2, N0, N5, N5, H1, N7, H1, H3, H3, N0, N0, N6, N7, H1, N7, H2, H2, H1, N5, N5, N0, H4, H3, H2, H1,H3, H3, N0, H3, H6, H5, H5, H3, H2, H1, N0, H1, H2, H1, H2, H2, H5, H3, N0, H3,H6, H5, H3, H2, H1, N0, H1, H2, H1, H2, H2, N7, N6, N0,
};u8 code durations[] = {2, 2, 6, 2, 4, 4, 12, 2, 2, 6, 2, 4, 4, 8, 4, 2, 2, 6, 2, 2, 6,8, 2, 2, 2, 2, 6, 2, 4, 4, 8, 4, 2, 2, 6, 2, 4, 4, 8, 4, 2, 2, 6, 2, 4, 4,12, 2, 2, 4, 2, 2, 4, 4, 2, 2, 2, 4, 4, 4, 2, 2, 2, 4, 4, 8, 4, 2, 2, 6, 2, 4, 4,8, 4, 2, 2, 2, 2, 4, 4, 8, 4, 4, 2, 2, 4, 4, 2, 2, 6, 2, 4, 4, 4, 4, 4, 4,16, 8, 4, 4, 8, 4, 4, 2, 2, 4, 2, 2, 4, 2, 2, 2, 4, 8, 4, 4,8, 8, 2, 2, 8, 2, 2, 4, 2, 2, 2, 4, 8, 4,
};// 天空之城
void Buzzer_sky_city() {u8 i;u8 len = sizeof(notes) / sizeof(notes[0]);for (i = 0; i < len; i++) {Buzzer_beep(notes[i]);delay_ms_pro(50 * durations[i]);// 播完一個音,適當停止一下,不是必須得Buzzer_stop();delay_ms(10);}Buzzer_stop(); // 停止
}
注意事項
- 有源蜂鳴器只需電平控制,無源蜂鳴器需頻率信號
- 驅動電流較大時建議增加三極管或MOS管放大信號
- STC8系列不同型號的寄存器可能存在差異,需查閱對應數據手冊
以上代碼示例適用于STC8H系列,其他STC8子系列需根據具體手冊調整寄存器配置。實際開發中建議使用STC官方提供的頭文件(如STC8H.h)以確保兼容性。