STM32 | 有源蜂鳴器響,無源蜂鳴器播音樂

目錄

?Overview

有源蜂鳴器

無源蜂鳴器

有源蜂鳴器控制

GPIO配置

控制程序

無源蜂鳴器控制

反轉GPIO控制

GPIO配置

控制接口

PWM控制

GPIO配置

控制函數

改變頻率播音樂

原理

1. 頻率決定音調

2. 占空比決定音量

GPIO初始化

結構體定義和音符頻率表

?播放接口

播放生日快樂歌


?Overview

有源蜂鳴器

【結構與工作原理】

內部集成了振蕩電路,只需提供直流電源(通常為 3-5V)即可發聲,頻率固定(常見為 2-4kHz)。

【驅動電路】

驅動簡單,直接通過 GPIO 控制通斷即可。需注意添加限流電阻(約 100Ω)保護 IO 口。

無源蜂鳴器

【結構與工作原理】

內部不含振蕩電路,需要外部提供 PWM(脈沖寬度調制)信號驅動,通過調整頻率和占空比可發出不同音調

【驅動電路】

需要 PWM 信號驅動,需配置 STM32 的定時器產生特定頻率的方波。例如,若需發出 4kHz 的聲音,則 PWM 頻率應設為 4kHz。

有源蜂鳴器控制

GPIO配置

我的這個有源蜂鳴器模塊帶三個引腳,分別是VCC,I/O和GND,I/O口輸入高電平時,蜂鳴器響。

(也有一些有源蜂鳴器只有兩個引腳,當電壓差滿足驅動就會響)

  • 連接I/O引腳的GPIO引腳,配置為簡單的輸出即可。
// 外部有源蜂鳴器
void ExtActiveBuzzerInit()
{GPIO_InitTypeDef  GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);	 //使能GPIOE端口時鐘GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;				 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽輸出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	 //速度為50MHzGPIO_Init(GPIOE, &GPIO_InitStructure);	 //根據參數初始化GPIO_ResetBits(GPIOE, GPIO_Pin_2);//輸出0,關閉蜂鳴器輸出
}

控制程序

  • 一秒響,一秒不響
void task1_task(void *pvParameters)
{ExtActiveBuzzerInit();while(1){SetExtActiveBuzzer(1);printf("SetExtActiveBuzzer(1)\r\n");delay_ms(1000);SetExtActiveBuzzer(0);printf("SetExtActiveBuzzer(0)\r\n");delay_ms(1000);}
}

無源蜂鳴器控制

????????無源蜂鳴器內部不含振蕩電路,需要外部提供 PWM(脈沖寬度調制)信號驅動,通過調整頻率和占空比可發出不同音調。

????????不使用 PWM 的情況下,也可以通過 GPIO 軟件翻轉模擬 PWM 信號驅動無源蜂鳴器

反轉GPIO控制

因為想觀察不同的頻率,所以我配置了兩個GPIO,以不同頻率做電平翻轉

GPIO配置

void ExtPassiveBuzzerInit()
{GPIO_InitTypeDef  GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);	    //使能GPIOE端口時鐘GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;	                //BEEP 端口配置GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		    //推挽輸出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	        //速度為50MHzGPIO_Init(GPIOE, &GPIO_InitStructure);	                    //根據參數初始化GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;GPIO_Init(GPIOE, &GPIO_InitStructure);}

控制接口

一個基礎的循環周期為100us

  • 對于PE1,每100us后,電平翻轉一次,所以方波周期是200us,頻率就是5KHz
  • 對于PE3,每1000us(1ms)后,電平翻轉一次,所以方波周期是2ms,頻率就是500Hz

頻率決定音調的高低,而更高的頻率通常會讓人感覺 “更刺耳”

void task1_task(void *pvParameters)
{int i = 0;int bE1Set = 0;int bE3Set = 0;ExtPassiveBuzzerInit();while (1){i++;if (i >= 10000) {printf("i = %d \r\n",i);i = 0;}if ( i % 2 == 0){if (bE1Set == 1){GPIO_ResetBits(GPIOE, GPIO_Pin_1);bE1Set = 0;}else{GPIO_SetBits(GPIOE, GPIO_Pin_1);bE1Set = 1;}}if ( i % 20 == 0){if (bE3Set == 1){GPIO_ResetBits(GPIOE, GPIO_Pin_3);bE3Set = 0;}else{GPIO_SetBits(GPIOE, GPIO_Pin_3);bE3Set = 1;}}// 半個周期100usdelay_us(100);}}

PWM控制

使用PA6,復用TIM3的通道1

GPIO配置

void ExtPassiveBuzzerPWMInit()
{GPIO_InitTypeDef GPIO_InitStructure;TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;TIM_OCInitTypeDef  TIM_OCInitStructure;// 使用PA6,做TIM3_CH1RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//設置該引腳為復用輸出功能,輸出TIM3 CH1的PWM脈沖波形	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; 			//TIM_CH1GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  	//復用推挽輸出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);				//初始化GPIO//初始化TIM3TIM_TimeBaseStructure.TIM_Period = 35999; 			//設置在下一個更新事件裝入活動的自動重裝載寄存器周期的值TIM_TimeBaseStructure.TIM_Prescaler = 0; 			//設置用來作為TIMx時鐘頻率除數的預分頻值 TIM_TimeBaseStructure.TIM_ClockDivision = 0; 		//設置時鐘分割:TDTS = Tck_timTIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上計數模式TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); 	//根據TIM_TimeBaseInitStruct中指定的參數初始化TIMx的時間基數單位//初始化TIM3 Channel1 PWM模式	 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; 				//選擇定時器模式:TIM脈沖寬度調制模式TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; 	//比較輸出使能TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; 		//輸出極性:TIM輸出比較極性高TIM_OC1Init(TIM3, &TIM_OCInitStructure);  						//根據T指定的參數初始化外設TIM3TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIM3在CCR1上的預裝載寄存器TIM_Cmd(TIM3, ENABLE);  //使能TIM3}

控制函數

占空比會用于實現音量高低變化

void task1_task(void *pvParameters)
{ExtPassiveBuzzerPWMInit();while(1){printf("Beep --- High Volume\r\n");// 高音量 (占空比約75%)TIM_SetCompare1(TIM3, 27000);  // 36000 * 0.75 = 27000delay_ms(1000);printf("Beep --- Low Volume\r\n");// 低音量 (占空比約10%)TIM_SetCompare1(TIM3, 3600);delay_ms(1000);}
}

改變頻率播音樂

原理

PWM(脈沖寬度調制)通過改變輸出信號的頻率占空比,可以驅動無源蜂鳴器播放音樂。

如何理解頻率和占空比的作用:

1. 頻率決定音調
  • 頻率:指 PWM 信號每秒的周期數(單位:Hz)。

  • 音調:不同頻率對應不同音符,例如:

    • Do (C4) = 262 Hz

    • Re (D4) = 294 Hz

    • Mi (E4) = 330 Hz

通過快速切換 PWM 頻率,可以組合出音樂旋律。

2. 占空比決定音量
  • 占空比:指高電平時間占整個周期的比例(通常用百分比表示)。

  • 音量:對于無源蜂鳴器,50% 占空比通常能產生最大音量,因為此時信號對稱,能充分驅動蜂鳴器振動。

GPIO初始化

和上面的函數一樣,但是留出了控制頻率的參數輸入

void ExtPassiveBuzzerAdvancePWMInit(uint32_t frequency)
{GPIO_InitTypeDef GPIO_InitStructure;TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;TIM_OCInitTypeDef  TIM_OCInitStructure;// 計算自動重裝載值和預分頻值uint32_t timer_clock = 72000000;  // 72MHzuint16_t psc = 1;uint16_t arr;// 使用PA6,做TIM3_CH1RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//設置該引腳為復用輸出功能,輸出TIM3 CH1的PWM脈沖波形	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; 			//TIM_CH1GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  	//復用推挽輸出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);				//初始化GPIO//初始化TIM3// 計算自動重裝載值,確保不超過16位arr = timer_clock / (frequency * psc);if (arr > 65535) {psc = timer_clock / (65535 * frequency) + 1;arr = timer_clock / (frequency * psc);}TIM_TimeBaseStructure.TIM_Period = arr; 			//設置在下一個更新事件裝入活動的自動重裝載寄存器周期的值TIM_TimeBaseStructure.TIM_Prescaler = psc-1; 			//設置用來作為TIMx時鐘頻率除數的預分頻值 TIM_TimeBaseStructure.TIM_ClockDivision = 0; 		//設置時鐘分割:TDTS = Tck_timTIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上計數模式TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); 	//根據TIM_TimeBaseInitStruct中指定的參數初始化TIMx的時間基數單位//初始化TIM3 Channel1 PWM模式	 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; 				//選擇定時器模式:TIM脈沖寬度調制模式TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; 	//比較輸出使能TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; 		//輸出極性:TIM輸出比較極性高TIM_OC1Init(TIM3, &TIM_OCInitStructure);  						//根據T指定的參數初始化外設TIM3TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);  //使能TIM3在CCR1上的預裝載寄存器TIM_Cmd(TIM3, ENABLE);  //使能TIM3// 設置初始占空比為50%TIM_SetCompare1(TIM3, arr / 2);}

結構體定義和音符頻率表

// 音樂結構定義
typedef struct {const uint8_t* melody;     // 音符數組const uint8_t* duration;   // 節拍數組uint8_t length;            // 音符長度
} Music_t;// 音符頻率表 (Hz)
const uint16_t notes[] = {0,    // 休止符262,  // C4 (Do)294,  // D4 (Re)330,  // E4 (Mi)349,  // F4 (Fa)392,  // G4 (Sol)440,  // A4 (La)494,  // B4 (Si)523   // C5 (Do高八度)
};

?播放接口

beat節拍,每一拍100ms

// 播放單個音符
void PlayNote(uint8_t note_index, uint8_t beat)
{uint16_t frequency;if (note_index > 8) return;  // 確保索引有效frequency = notes[note_index];if (frequency > 0) {// 初始化PWM頻率ExtPassiveBuzzerAdvancePWMInit(frequency);} else {// 休止符: 關閉PWM輸出TIM_SetCompare1(TIM3, 0);}// 播放指定節拍 (1拍 = 100ms)delay_ms(beat * 100);
}// 播放音樂
void PlayMusic(const Music_t* music)
{uint8_t i;for (i = 0; i < music->length; i++) {PlayNote(music->melody[i], music->duration[i]);}// 播放結束,關閉蜂鳴器TIM_SetCompare1(TIM3, 0);
}

播放生日快樂歌

音符(控制PWM頻率)和節拍數(控制音符對于頻率PWM持續時長)

void task1_task(void *pvParameters)
{// 定義任務局部的音樂結構體指針static Music_t birthday;// 示例音樂:生日快樂歌static const uint8_t birthday_melody[] = {5, 5, 6, 5, 1, 7, 5, 5, 6, 5, 2, 1, 5, 5, 5, 3, 1, 7, 6, 4, 4, 3, 1, 2, 1};static const uint8_t birthday_duration[] = {2, 2, 4, 4, 4, 8, 2, 2, 4, 4, 4, 8, 2, 2, 2, 4, 4, 4, 8, 2, 2, 4, 4, 4, 8};// 在任務啟動時初始化結構體birthday.melody = birthday_melody;birthday.duration = birthday_duration;birthday.length = sizeof(birthday_melody);while(1){// 循環播放生日快樂歌PlayMusic(&birthday);delay_ms(1000);  // 播放間隔}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/915416.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/915416.shtml
英文地址,請注明出處:http://en.pswp.cn/news/915416.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

第十四章 gin基礎

文章目錄Gin快速搭建一個web服務Gin數據交互JSON串內容規范Gin使用結構體返回數據給前端Gin配置POST類型的路由Gin獲取GET請求參數Gin獲取POST請求參數-form-data類型Gin獲取POST請求參數-JSON類型Gin獲取參數綁定至結構體Gin快速搭建一個web服務 下載包 \\新建一個文件&…

Baumer工業相機堡盟工業相機如何通過YoloV8的深度學習模型實現PCB的缺陷檢測(C#代碼,UI界面版)

Baumer工業相機堡盟工業相機如何通過YoloV8的深度學習模型實現PCB的缺陷檢測&#xff08;C#代碼&#xff0c;UI界面版&#xff09;工業相機使用YoloV8模型實現PCB的缺陷檢測工業相機實現YoloV8模型實現PCB的缺陷檢測的技術背景在相機SDK中獲取圖像轉換圖像的代碼分析工業相機圖…

【Vivado那些事兒】AMD-XILINX 7系列比特流加密

前提&#xff1a;加密有風險&#xff0c;操作需謹慎前言在許多項目中&#xff0c;經過漫長的等待&#xff0c;我們的 FPGA 設計終于可以投入現場部署了。前期的資金的投入及知識產權的保護&#xff0c;我們需要對現場部署的 FPGA 進行比特流保護以防止逆向工程和未經授權的重復…

RK3588 安卓adb操作

adb&#xff08;Android Debug Bridge&#xff09;是一個用于與安卓設備進行通信和控制的工具。adb可以通過USB或無線網絡連接安卓設備&#xff0c;執行各種命令&#xff0c;如安裝和卸載應用&#xff0c;傳輸文件&#xff0c;查看日志&#xff0c;運行shell命令等。adb是安卓開…

【華為機試】70. 爬樓梯

文章目錄70. 爬樓梯描述示例 1示例 2提示解題思路核心分析問題建模算法實現方法1&#xff1a;動態規劃&#xff08;標準解法&#xff09;方法2&#xff1a;空間優化動態規劃&#xff08;最優解&#xff09;方法3&#xff1a;遞歸 記憶化方法4&#xff1a;數學公式&#xff08;…

山東大學軟件學院面向對象期末復習

面向對象 文章目錄面向對象04 類封裝接口 抽象類05 消息&#xff0c;實例化&#xff0c;靜態變量方法消息動/靜態類型語言對象創建類及實例具有下面特征對象數組的創建靜態數據成員構造函數06_0 繼承繼承是向下傳遞的JAVA為什么不支持多重繼承繼承的形式特殊化繼承替換原則規范…

讓 Windows 用上 macOS 的系統下載與保姆級使用教程

模擬蘋果桌面軟件下載&#xff1a;https://xpan.com.cn/s/8NFAGT 還記得 Windows 11剛發布時&#xff0c;很多人就說“果里果氣"的&#xff0c;但界面確實做的漂亮。 不知道現在有多少小伙伴正用著macOS&#xff0c;不過我敢確定&#xff0c;喜歡macOS的人絕對不少&#…

嵌入式硬件篇---繼電器

繼電器是一種通過小電流控制大電流的電磁開關&#xff0c;廣泛應用于自動化控制、電力系統和電子設備中。以下從工作原理、應用場景和電路特點三個方面詳細介紹&#xff1a;一、工作原理繼電器本質是電磁控制的機械式開關&#xff0c;核心部件包括&#xff1a;線圈&#xff08;…

鴻蒙網絡編程系列58-倉頡版TLS數字證書查看及驗簽示例

1. TLS數字證書驗簽簡介 數字證書的簽名驗證是網絡編程中一個重要的功能&#xff0c;它保證了數字證書是由可信任的簽發方簽署的&#xff0c;在此基礎上&#xff0c;我們才可以信任該證書&#xff0c;進而信任基于該證書建立的安全通道&#xff0c;所以說&#xff0c;數字證書…

【React Native】安裝配置 Expo Router

過去開發React Native&#xff0c;所使用的路由都是React Navigation。但是這個東西使用起來非常困難&#xff0c;配置無比繁瑣。Expo&#xff0c;為了簡化操作&#xff0c;就基于React Navigation開發了Expo Router。 Expo Router用起來就要簡單的多了&#xff0c;配置也相對…

美國VPS服務器Linux內核參數調優的實踐與驗證

美國vps服務器Linux內核參數調優的實踐與驗證在云計算和虛擬化技術日益普及的今天&#xff0c;美國VPS服務器因其穩定的網絡環境和優越的性價比&#xff0c;成為眾多企業和開發者的首選。Linux內核參數的默認配置往往無法充分發揮VPS的性能潛力。本文將深入探討美國VPS服務器上…

在Vscode中使用Kimi K2模型:實踐指南,三分鐘生成個小游戲

Kimi K2是一款基于多專家&#xff08;MoE&#xff09;架構的強大代碼與代理能力基礎模型。本文將通過在VS Code及其擴展Cline和RooCode中的實際應用&#xff0c;詳細說明如何使用Kimi K2-0711-preview模型。不得不說kimi這次的K2模型就是強大&#xff0c;在vscode中配置使用體驗…

基于SpringBoot+Uniapp球場預約小程序(騰訊地圖API、Echarts圖形化分析、二維碼識別)

“ &#x1f388;系統亮點&#xff1a;騰訊地圖API、Echarts圖形化分析、二維碼識別”01系統開發工具與環境搭建前后端分離架構 項目架構&#xff1a;B/S架構 運行環境&#xff1a;win10/win11、jdk17前端&#xff1a; 技術&#xff1a;框架Vue.js&#xff1b;UI庫&#xff1a;…

windows + phpstorm 2024 + phpstudy 8 + php7.3 + thinkphp6 配置xdebug調試

windows phpstorm 2024 phpstudy 8 php7.3 thinkphp6 配置xdebug調試 下載配置phpstudyPhp.ini配置phpstorm配置xdebug運行一會就停了配置虛擬機 0localhost_90.conf 配置php.ini配置下載 在下面地址下載合適的xdebug 放到對應的php https://xdebug.org/wizard 配置phpst…

python的pywebview庫結合Flask和waitress開發桌面應用程序簡介

pywebview的用途與特點 用途 pywebview是一個輕量級Python庫&#xff0c;用于創建桌面應用程序&#xff08;GUI&#xff09;。它通過嵌入Web瀏覽器組件&#xff08;如Windows的Edge/IE、macOS的WebKit、Linux的GTK WebKit&#xff09;&#xff0c;允許開發者使用HTML/CSS/Java…

C#通過HslCommunication連接西門子PLC1200,并防止數據跳動的通用方法

textEdit30.Text ReadValue<int>(() > plc.ReadInt32("DB57.DBD16"), ref _last_num).ToString();// 通用讀取方法&#xff08;支持所有值類型&#xff09;private T ReadValue<T>(Func<OperateResult<T>> readFunc, ref T lastValue) w…

Linux切換到Jenkins用戶解決Jenkins Host key verification failed

以root或sudo user身份, 切換到jenkins用戶 su -s /bin/bash jenkins前往jenkins的home目錄 cd /var/lib/jenkins/查看.ssh下是否已經有known_hosts, 有的話, 是什么內容, 正常情況下, 這時候是沒有對應IP記錄的 cd .ssh/ more known_hosts訪問一下對應IP, 記錄公鑰 ssh 192.16…

7.17 Java基礎 | 集合框架(下)

接上文&#xff1a; 7.16 Java基礎 | 集合框架&#xff08;上&#xff09;-CSDN博客 【1】Map集合 Map 集合是一種能存儲鍵值對的數據結構。它的主要功能是依據鍵&#xff08;Key&#xff09;來快速查找對應的值&#xff08;Value&#xff09; 1、聲明 Map<Integer,Integer…

【LeetCode刷題指南】--反轉鏈表,鏈表的中間結點,合并兩個有序鏈表

&#x1f525;個人主頁&#xff1a;草莓熊Lotso &#x1f3ac;作者簡介&#xff1a;C研發方向學習者 &#x1f4d6;個人專欄&#xff1a; 《C語言》 《數據結構與算法》《C語言刷題集》《Leetcode刷題指南》 ??人生格言&#xff1a;生活是默默的堅持&#xff0c;毅力是永久的…

ubuntu上面的wps2019格式很亂在復制粘貼的時候

問題&#xff1a;在復制內容到 Ubuntu 上的 WPS 2019 出現如下問題&#xff1a;列表符號、換行和縮進錯亂&#xff0c;表現為每行前的點符號&#xff08;?&#xff09;變成不規則對齊或空格間距不統一。原因分析? 主要原因是&#xff1a;WPS 2019 在 Ubuntu 上的兼容性較差&a…