有源蜂鳴器內(nèi)含振蕩源,只要一通電就發(fā)聲,但發(fā)生頻率固定,音色單一;無源蜂鳴器內(nèi)部不含振蕩源,內(nèi)部結(jié)構(gòu)相當(dāng)于電磁場揚聲器,可以通過給他輸出一定頻率的信號才能發(fā)聲。
人耳能聽到的頻率范圍在20Hz--20kHz之間,通過STM32的GPIO引腳快速切換高低電平輸出就能實現(xiàn)無源蜂鳴器的發(fā)聲,切換的頻率不同,發(fā)出的音調(diào)就不一樣。
二、音樂播放的實現(xiàn)
一段音樂就是不同頻率的聲音按一定的時間節(jié)拍轉(zhuǎn)換發(fā)出。所以音樂包含音調(diào)和節(jié)拍信息。
如果要實現(xiàn)歌曲“紅塵情歌”,要準(zhǔn)備相應(yīng)的數(shù)據(jù)。
歌譜如下:
程序中首先準(zhǔn)備音頻數(shù)據(jù)表:
// 低Si Do Re Mi Fa So La Si ?高Do?高Re?高M(jìn)i?高Fa?高So 無
uc16 tone[] ={247,262,294,330,349,392,440,294,523, 587, 659, 698, 784, 1000};
u8 music[]={ 5,5,6,8,7,6,5,6,13,13,……};//音調(diào)
u8 time[] = { 2,4,2,2,2,2,2,8,4, 4, ……}; //節(jié)拍時間
依次從音調(diào)數(shù)組中取music[i],然后根據(jù)music[i]的值在tone數(shù)組中得到該音的發(fā)聲頻率(tone[music[i]]),調(diào)用sound函數(shù)控制蜂鳴器發(fā)聲,聲音的發(fā)聲時間有time數(shù)組控制。
三、項目創(chuàng)建與配置
1、創(chuàng)建項目文件夾(設(shè)為pMusic)
2、通過Keil5創(chuàng)建新項目,保存在所創(chuàng)建的文件夾中(設(shè)項目名為pMusic),選擇MCU芯片為"STM32F103ZE"(本程序使用的硬件為:STM32-PZ6806L開發(fā)板)
3、在pMusic項目文件夾中新建"CMSIS"、"Device"、"Public"、"Startup"、"User"和"Lib"文件夾。
① 在"CMSIS"文件夾中復(fù)制"core_cm3.h"和"core_cm3.c"文件;
② 在" Device "文件夾中復(fù)制"stm32f10x.h"、"system_stm32f10x.h"和"system_stm32f10x.c"文件;
③ 在" Startup "文件夾中復(fù)制"startup_stm32f10x_hd.s"文件;
④在"Lib"文件夾中新建"inc"和"src"兩個子文件夾,在"inc"文件夾中復(fù)制"misc.h"、"stm32f10x_gpio.h"和"stm32f10x_rcc.h"文件;在"src"文件夾中復(fù)制"misc.c"、"stm32f10x_gpio.c"和"stm32f10x_rcc.c"文件;
4、為項目添加"CMSIS"、"Device"、"Public"、"Startup"、"User"和"Lib"組,并將上述C程序文件和"startup_stm32f10x_hd.s"啟動文件加入到相應(yīng)組中。展開項目樹如下:
5、打開“項目配置”對話框,在"Output"選項卡中選擇"Create HEX File",在"C/C++"選項卡中的"Include Paths"中添加如下包含路徑:".CMSIS;", ".Device;", ".Libinc;",".Public;"。
(以上步驟可以參看:使用STM32固件庫操作控制LED燈(CMSIS) 使用STM32固件庫函數(shù)操作控制LED燈
6、在"stm32f10x.h"中添加函數(shù)參數(shù)檢查宏
(參看:使用STM32固件庫函數(shù)操作控制LED燈)
#ifdef USE_FULL_ASSERT
/**
* @brief 這個assert_param宏用于函數(shù)參數(shù)檢查
* @param expr:如果expr是 false,就調(diào)用 assert_failed函數(shù)報告源文件名和
* 失敗的行號,如果expr是 true ,就返回一個空值
* @retval None
*/
#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */
void assert_failed(uint8_t* file, uint32_t line);
#else
#define assert_param(expr) ((void)0)
#endif /* USE_FULL_ASSERT */
7、新建一個文件(system.h),保存到"Public"文件夾中,內(nèi)容為:
#ifndef __SYSTEM__H
#define __SYSTEM__H
#include "stm32f10x.h"
//定義位帶地址宏
#define BITBAND(addr,bitnum) ((addr&0xF0000000) + 0x02000000 + ((addr&0x000FFFFF)<<5) + (bitnum<<2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define BIT_ADDR(addr,bitnum) MEM_ADDR(BITBAND(addr,bitnum))
//IO口地址映射
//數(shù)據(jù)輸出寄存器地址
#define GPIOA_ODR_Addr (GPIOA_BASE + 12)
#define GPIOB_ODR_Addr (GPIOB_BASE + 12)
#define GPIOC_ODR_Addr (GPIOC_BASE + 12)
#define GPIOD_ODR_Addr (GPIOD_BASE + 12)
#define GPIOE_ODR_Addr (GPIOE_BASE + 12)
#define GPIOF_ODR_Addr (GPIOF_BASE + 12)
#define GPIOG_ODR_Addr (GPIOG_BASE + 12)
//數(shù)據(jù)輸入寄存器地址
#define GPIOA_IDR_Addr (GPIOA_BASE + 12)
#define GPIOB_IDR_Addr (GPIOB_BASE + 12)
#define GPIOC_IDR_Addr (GPIOC_BASE + 12)
#define GPIOD_IDR_Addr (GPIOD_BASE + 12)
#define GPIOE_IDR_Addr (GPIOE_BASE + 12)
#define GPIOF_IDR_Addr (GPIOF_BASE + 12)
#define GPIOG_IDR_Addr (GPIOG_BASE + 12)
#endif
該文件定義了GPIO端口位帶操作的宏。
(位帶操作請參看:通過位帶地址操作GPIO在數(shù)碼管顯示數(shù)字)
8、新建文件"SysTick.h",保存到"Public"文件夾中,內(nèi)容為:
#ifndef __SysTick__H
#define __SysTick__H
#include "stm32f10x.h"
void SysTick_Init(u8 SYSCLK);
void delay_us(u32 nus);
void delay_ms(u16 nms);
#endif
新建文件"SysTick.c",保存到"Public"文件夾中,內(nèi)容為:
#include "SysTick.h"
#include "misc.h"
u8 fac_us = 0;
u16 fac_ms = 0;
void SysTick_Init(u8 SYSCLK)
{
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
fac_us = SYSCLK / 8;
fac_ms = (u16)fac_us*1000;
}
void delay_us(u32 nus)
{
u32 temp;
SysTick->LOAD = nus * fac_us;
SysTick->VAL = 0;
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
do{
temp = SysTick->CTRL;
}while((temp&0x01)&&(!(temp&(1<<16))));
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
SysTick->VAL = 0;
}
void delay_ms(u16 nms)
{
u32 temp;
SysTick->LOAD = nms * fac_ms;
SysTick->VAL = 0;
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
do{
temp = SysTick->CTRL;
}while((temp&0x01)&&(!(temp&(1<<16))));
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
SysTick->VAL = 0;
}
這兩個文件實現(xiàn)了通過SysTick精準(zhǔn)延時的函數(shù),提供給后續(xù)的音頻頻率產(chǎn)生程序使用。
(關(guān)于SysTick,請參看:在STM32項目中使用SysTick實現(xiàn)延時)
將"SysTick.c"文件添加到項目的"Public"組中。
9、實現(xiàn)發(fā)聲
①開發(fā)板無源蜂鳴器的電路連接如下:
從電路連接可以看出通過MCU的PB5(GPIOB_5)控制蜂鳴器的發(fā)聲。
②在項目文件夾的"User"文件夾下新建"Beep"文件夾,在項目中新建"beep.h"文件,保存在"User/Beep"文件夾中,文件內(nèi)容為:
#ifndef __BEEP__H
#define __BEEP__H
#include "system.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
//定義GPIOB的位地址變量宏
#define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n)
#define PBeep PBout(5)
#define BEEP_PORT GPIOB
#define BEEP_PIN GPIO_Pin_5
#define BEEP_PORT_RCC RCC_APB2Periph_GPIOB
void BEEP_Init(void);
void Sound(u16 frq);
void play(void);
#endif
③在項目中新建"beep.c"文件,保存在"User/Beep"文件夾中,文件內(nèi)容為:
#include "beep.h"
#include "systick.h"
void BEEP_Init(void)
{
GPIO_InitTypeDef GPIO_mode;
RCC_APB2PeriphClockCmd( BEEP_PORT_RCC, ENABLE ); //使能GPIOB時鐘
GPIO_mode.GPIO_Pin = BEEP_PIN;
GPIO_mode.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_mode.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(BEEP_PORT, &GPIO_mode); //設(shè)置GPIOB_5為推挽輸出,50MHz速度
}
void Sound(u16 frq)
{
u32 n;
if(frq != 1000) //如果頻率不為1000則按頻率輸出,否則只延時
{
n = 500000/((u32)frq);
PBeep = 0;
delay_us(n);
PBeep = 1;
delay_us(n);
}else
delay_us(1000);
}
void play(void)
{
// 低7 1 2 3 4 5 6 7 高1 高2 高3 高4 高5 不發(fā)音
uc16 tone[] = {247,262,294,330,349,392,440,294,523,587,659,698,784,1000};//音頻數(shù)據(jù)表
//紅塵情歌
u8 music[]={ 5,5,6,8,7,6,5,6,13,13,//音調(diào)
5,5,6,8,7,6,5,3,13,13,
2,2,3,5,3,5,6,3,2,1,
6,6,5,6,5,3,6,5,13,13,
5,5,6,8,7,6,5,6,13,13,
5,5,6,8,7,6,5,3,13,13,
2,2,3,5,3,5,6,3,2,1,
6,6,5,6,5,3,6,1,
上一篇:S3C2440核心板原理圖設(shè)計:與SDRAM接線分析
下一篇:stm32使用MDK開發(fā)中的一些常見問題
推薦閱讀最新更新時間:2025-06-27 04:02



設(shè)計資源 培訓(xùn) 開發(fā)板 精華推薦
- Microchip 升級數(shù)字信號控制器(DSC)產(chǎn)品線 推出PWM 分辨率和 ADC 速度業(yè)界領(lǐng)先的新器件
- 意法半導(dǎo)體STM32MP23x:突破成本限制的工業(yè)AI應(yīng)用核心
- 意法半導(dǎo)體推出用于匹配遠(yuǎn)距離無線微控制器STM32WL33的集成的匹配濾波芯片
- ESP32開發(fā)板連接TFT顯示屏ST7789跳坑記
- 如何讓ESP32支持analogWrite函數(shù)
- LGVL配合FreeType為可變字體設(shè)置字重-ESP32篇
- 使用樹莓派進(jìn)行 ESP32 Jtag 調(diào)試
- ESP32怎么在SPIFFS里面存儲html,css,js文件,以及網(wǎng)頁和arduino的通訊
- ESP32 freeRTOS使用測試
- AD8034ARTZ-REEL7 有限輸入范圍高速峰值檢波器的典型應(yīng)用電路
- TC77DM-PICTL、TC77 熱傳感器 PICtail 演示板
- 使用 ON Semiconductor 的 RC5050 的參考設(shè)計
- DC1017A,LT5558EUF 演示板,600 - 1100 MHz I-Q 調(diào)制器,具有 Hi-Z BB Rin,Vcm = 2.1V
- EVAL-AD7706EBZ,用于 AD7705、5V、3 通道、16 位、Sigma Delta ADC 的評估板
- LDK120C18R 1.8V低壓降穩(wěn)壓器典型應(yīng)用(D版)電路
- LT1307BCS8 外部控制突發(fā)模式操作的典型應(yīng)用電路
- 使用 Analog Devices 的 ADuM4160BRWZ 的參考設(shè)計
- ADP1046ADC1-EVALZ,適用于 ADP1046A 寬輸入范圍、全橋相移拓?fù)涞脑u估板
- LT3763HFE 20A、同步、5V 穩(wěn)壓器的典型應(yīng)用電路
- 臺積電計劃兩年后停止氮化鎵晶圓生產(chǎn),納微轉(zhuǎn)投力積電
- 研華新品搭載最新 AMD Ryzen 嵌入式 8000 系列處理器,驅(qū)動AI 智能新篇章
- 美國EDA恢復(fù)供應(yīng)?
- 從追趕到超越:的盧深視的“AI +三維機器視覺“破局之戰(zhàn)
- 常用的音頻處理器有哪些應(yīng)用場景
- 研究顯示2035年全球酒店服務(wù)機器人市場規(guī)模有望達(dá)125億美元
- i9-14900HX對比一款換湯不換藥的馬甲老U R9-8945HX
- 納祥科技2W 24位數(shù)字功放NX4920,可用于AI語音播報、WIFI播放器
- 常用解調(diào)器的定義和工作原理
- 從性能與網(wǎng)絡(luò)傳輸出發(fā),講講鐵威馬MAX系列為什么一騎絕塵