STM32蜂鳴器播放音樂

STM32蜂鳴器播放音樂

STM32蜂鳴器播放音樂 Do, Re, Mi, Fa,

1. 功能概述

本系統基于STM32F7系列微控制器,實現了以下功能:

  1. 通過7個按鍵控制蜂鳴器發聲,按鍵對應不同的音符。
  2. 每個按鍵對應一個音符(Do, Re, Mi, Fa, Sol, La, Si),按下按鍵時蜂鳴器播放對應音符的聲音。
  3. 利用PWM技術控制蜂鳴器發聲頻率,實現不同音符的效果。
  4. 按鍵松開時蜂鳴器停止發聲,防止連續觸發。

在這里插入圖片描述

2. 硬件接線

2.1 按鍵與GPIO連接

系統使用STM32F7的GPIOB端口,連接7個按鍵,其中:

  • 按鍵1: GPIO_PIN_0
  • 按鍵2: GPIO_PIN_1
  • 按鍵3: GPIO_PIN_3
  • 按鍵4: GPIO_PIN_4
  • 按鍵5: GPIO_PIN_5
  • 按鍵6: GPIO_PIN_6
  • 按鍵7: GPIO_PIN_7

每個按鍵的另一端連接到地(GND),GPIO引腳配置為上拉輸入模式(GPIO_PULLUP)。

2.2 蜂鳴器與GPIO連接

蜂鳴器通過GPIOA的PA6引腳與STM32連接:

  • PA6配置為TIM3_CH1通道的PWM輸出。
  • 蜂鳴器的一端連接到PA6,另一端連接到GND。

2.3 電源

  • STM32主控板通過USB供電。
  • 所有按鍵和蜂鳴器的電源均由STM32供電。

3. 軟件實現原理

3.1 功能模塊

軟件設計主要包含以下功能模塊:

3.1.1 PWM模塊
  • 利用定時器TIM3的PWM功能產生控制蜂鳴器的信號。
  • 根據不同音符的頻率設置PWM的周期(ARR)值,調整占空比控制音量。
3.1.2 按鍵掃描模塊
  • 周期性讀取GPIOB的引腳狀態,判斷按鍵是否按下。
  • 通過數組 KeyStatus[] 保存每個按鍵的狀態(按下為1,松開為0)。
3.1.3 音符播放模塊
  • 根據按鍵狀態決定是否播放音符。
  • 使用Play_Tone()函數設置PWM頻率并播放音符。
  • 使用Stop_Tone()函數停止蜂鳴器播放。

3.2 軟件流程

3.2.1 主程序流程

主程序主要流程如下:

  1. 初始化系統時鐘和HAL庫。
  2. 配置GPIO用于按鍵輸入和蜂鳴器輸出。
  3. 初始化TIM3定時器的PWM功能。
  4. 主循環中:
    • 調用按鍵掃描函數Keypad_Read()更新按鍵狀態。
    • 檢查每個按鍵狀態,對應播放音符。
    • 播放音符后延時一定時間避免重復觸發。
    • 調用Stop_Tone()停止蜂鳴器播放。
3.2.2 按鍵掃描流程

按鍵掃描采用循環遍歷方式:

  1. 定義GPIOB引腳的數組 pins[],保存每個按鍵對應的GPIO引腳。
  2. 遍歷引腳數組,調用HAL_GPIO_ReadPin()讀取每個按鍵狀態。
  3. 如果引腳電平為低(GPIO_PIN_RESET),表示按鍵被按下。
  4. 更新 KeyStatus[] 數組。
3.2.3 音符播放流程

音符播放利用PWM實現:

  1. 根據音符頻率計算PWM的自動重裝載值(ARR)。
  2. 調用__HAL_TIM_SET_AUTORELOAD()更新TIM3的ARR值。
  3. 調用__HAL_TIM_SET_COMPARE()設置占空比。
  4. 開始PWM輸出,蜂鳴器發聲。
  5. 延時指定時間后停止PWM輸出。

主函數代碼:

#include "stm32f7xx.h"
#include "main.h"
#include "./tim/bsp_basic_tim.h"
#include "./led/bsp_led.h"
#include "./usart/bsp_usart.h"
#include "./beep_music/beep_music.h"
TIM_HandleTypeDef htimx; // 定義一個全局定時器句柄void SystemClock_Config(void);
void PWM_Init(void);
void Set_PWM_Frequency(uint32_t frequency);
void Play_Music(int *tune, float *duration, int length);
/*** @brief  主函數* @param  無* @retval 無*/
int main(void) 
{/* 初始化系統時鐘為216MHz */SystemClock_Config();/* 初始化LED */LED_GPIO_Config();/* 初始化基本定時器定時,1s產生一次中斷 *///TIMx_Configuration();PWM_Init();               // 初始化 PWM//	int length = sizeof(tune) / sizeof(tune[0]); // 獲取音符數量
//    Play_Music(tune, duration, length);play_music();	while(1){   }
}/*** @brief  System Clock 配置*         System Clock 配置如下 : *         System Clock source            = PLL (HSE)*         SYSCLK(Hz)                     = 216000000*         HCLK(Hz)                       = 216000000*         AHB Prescaler                  = 1*         APB1 Prescaler                 = 4*         APB2 Prescaler                 = 2*         HSE Frequency(Hz)              = 25000000*         PLL_M                          = 25*         PLL_N                          = 432*         PLL_P                          = 2*         PLL_Q                          = 9*         VDD(V)                         = 3.3*         Main regulator output voltage  = Scale1 mode*         Flash Latency(WS)              = 7* @param  無* @retval 無*/
void SystemClock_Config(void)
{RCC_ClkInitTypeDef RCC_ClkInitStruct;RCC_OscInitTypeDef RCC_OscInitStruct;HAL_StatusTypeDef ret = HAL_OK;/* 使能HSE,配置HSE為PLL的時鐘源,配置PLL的各種分頻因子M N P Q * PLLCLK = HSE/M*N/P = 25M / 25 *432 / 2 = 216M*/RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;RCC_OscInitStruct.HSEState = RCC_HSE_ON;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;RCC_OscInitStruct.PLL.PLLM = 25;RCC_OscInitStruct.PLL.PLLN = 432;RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;RCC_OscInitStruct.PLL.PLLQ = 9;ret = HAL_RCC_OscConfig(&RCC_OscInitStruct);if(ret != HAL_OK){while(1) { ; }}/* 激活 OverDrive 模式以達到216M頻率  */  ret = HAL_PWREx_EnableOverDrive();if(ret != HAL_OK){while(1) { ; }}/* 選擇PLLCLK作為SYSCLK,并配置 HCLK, PCLK1 and PCLK2 的時鐘分頻因子 * SYSCLK = PLLCLK     = 216M* HCLK   = SYSCLK / 1 = 216M* PCLK2  = SYSCLK / 2 = 108M* PCLK1  = SYSCLK / 4 = 54M*/RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; /* 在HAL_RCC_ClockConfig函數里面同時初始化好了系統定時器systick,配置為1ms中斷一次 */ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7);if(ret != HAL_OK){while(1) { ; }}  
}/*** @brief 配置系統時鐘* @retval 無*//*** @brief 初始化 PWM* @retval 無*/
void PWM_Init(void)
{// 開啟定時器和 GPIO 時鐘__HAL_RCC_TIM3_CLK_ENABLE();  // 使用 TIM3 作為示例__HAL_RCC_GPIOA_CLK_ENABLE(); // 使用 GPIOA 作為示例// 配置 PWM 輸出引腳GPIO_InitTypeDef GPIO_InitStruct = {0};GPIO_InitStruct.Pin = GPIO_PIN_6;       // 使用 PA6(TIM3_CH1)作為 PWM 輸出GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // 復用推挽模式GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);// 配置定時器htimx.Instance = TIM3;                        // 定時器實例為 TIM3htimx.Init.Prescaler = (SystemCoreClock / 1000000) - 1; // 定時器頻率分頻到 1MHz (1μs 精度)htimx.Init.CounterMode = TIM_COUNTERMODE_UP;  // 向上計數模式htimx.Init.Period = 1000 - 1;                 // 默認周期,產生 1kHz 方波htimx.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;htimx.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;HAL_TIM_PWM_Init(&htimx);                     // 初始化定時器 PWM// 配置 PWM 通道TIM_OC_InitTypeDef sConfigOC = {0};sConfigOC.OCMode = TIM_OCMODE_PWM1;           // PWM 模式 1sConfigOC.Pulse = 500;                        // 默認占空比 50%sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;   // 高電平有效sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;HAL_TIM_PWM_ConfigChannel(&htimx, &sConfigOC, TIM_CHANNEL_1); // 配置通道 1// 啟動 PWM 輸出HAL_TIM_PWM_Start(&htimx, TIM_CHANNEL_1);
}/*** @brief 設置 PWM 輸出頻率* @param frequency 頻率 (Hz)* @retval 無*/
void Set_PWM_Frequency(uint32_t frequency)
{if (frequency == 0) // 如果頻率為 0,停止 PWM 輸出{__HAL_TIM_SET_COMPARE(&htimx, TIM_CHANNEL_1, 0);return;}uint32_t period = 1000000 / frequency; // 周期 = 1秒(1000000us) / 頻率__HAL_TIM_SET_AUTORELOAD(&htimx, period - 1); // 設置自動重裝載值__HAL_TIM_SET_COMPARE(&htimx, TIM_CHANNEL_1, period / 2); // 設置占空比為 50%
}/*** @brief 播放音樂* @param tune 音符數組* @param duration 音符持續時間數組* @param length 音符數量* @retval 無*/
void Play_Music(int *tune, float *duration, int length)
{for (int i = 0; i < length; i++){if (tune[i] == 0) // 如果音符為 0,停止播放,表示間隔{Set_PWM_Frequency(0); // 停止 PWM}else{Set_PWM_Frequency(tune[i]); // 設置音符對應的頻率}HAL_Delay(duration[i] * 1000); // 持續時間(將秒轉換為毫秒)}Set_PWM_Frequency(0); // 播放完成后停止 PWM
}/*********************************************END OF FILE**********************/

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

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

相關文章

基于 OCO - 2 氧氣 A 帶輻射數據與地面臺站氣壓觀測數據構建近地面氣壓監測算法方案

基于 OCO - 2 氧氣 A 帶輻射數據與地面臺站氣壓觀測數據構建近地面氣壓監測算法方案 一、數據獲取與準備 (一)OCO - 2 氧氣 A 帶輻射數據 數據下載:從 OCO - 2 官方數據發布平臺(如 NASA 的相關數據存儲庫),按照研究所需的時間范圍(例如,近 5 年的數據以獲取足夠的樣本…

程序員英語口語練習筆記

我是一個程序員&#xff0c;專注于Java, Linux和k8s. I’m a programmer specializing in Java, Linux, and Kubernetes. 這個不是我的bug。 I don’t think this bug is caused by my work. 你能幫我看一下這個代碼嗎&#xff1f; Can you take a look at this code for me?…

網絡地址轉換技術(2)

NAT的配置方法&#xff1a; &#xff08;一&#xff09;靜態NAT的配置方法 進入接口視圖配置NAT轉換規則 Nat static global 公網地址 inside 私網地址 內網終端PC2&#xff08;192.168.20.2/24&#xff09;與公網路由器AR1的G0/0/1&#xff08;11.22.33.1/24&#xff09;做…

從零開始理解基于深度學習的語義分割模型:RCA與RCM模塊的實現

從零開始理解基于深度學習的語義分割模型:RCA與RCM模塊的實現 隨著深度學習技術的發展,圖像分割任務取得了長足的進步。本文將從一個具體的PyTorch代碼實例出發,帶大家了解一種 novel 的語義分割網絡架構——RCA(Rectangular Self-Calibration Attention)和 RCM(Rectang…

【Linux網絡-多路轉接select】

代碼&#xff1a;https://gitee.com/nanyi-c/linux/tree/master/day50 一、I/O多路轉接之select 1.初始select 系統提供select函數來實現多路復用輸入/輸出模型 select系統調用是用來讓我們的程序監視多個文件描述符的狀態變化的程序會停在select這里等待&#xff0c;直到被…

2025 年中國家電零售與創新趨勢解析:以舊換新國補激活需求,AI 技術滲透至研發、供應鏈、營銷

一、產業環境&#xff1a;政策驅動與技術變革下的挑戰與機遇 在全球經濟波動與國內消費轉型的雙重背景下&#xff0c;中國家電產業正經歷前所未有的變革。2024 年&#xff0c;家電行業面臨的 “三座大山”—— 短期消費信心低迷、中期房地產降溫、長期人口下行壓力 —— 持續施…

SpringBoot分布式項目中MyBatis實戰技巧:從配置到性能優化

引言 在分布式系統架構中&#xff0c;SpringBoot與MyBatis的組合已成為企業級開發的黃金搭檔。但在實際項目中&#xff0c;開發者常面臨多數據源管理、SQL性能優化、分布式事務等挑戰。本文將從實戰角度出發&#xff0c;分享7個關鍵技巧和避坑指南。 一、多數據源動態切換實戰…

【大模型基礎_毛玉仁】4.1 參數高效微調簡介

目錄 4 參數高效微調4.1 參數高效微調簡介4.1.1 下游任務適配1&#xff09;上下文學習&#xff08;In-context learning&#xff09;2&#xff09;指令微調&#xff08;Instruction Tuning&#xff09; 4.1.2 參數高效微調4.1.3 參數高效微調的優勢 4 參數高效微調 大語言模型…

Postman使用02、斷點、fiddler弱網測試

腳本操作 一、腳本導出 1.導出json腳本 2.打包json文件 3.下載的文件 二 .導入腳本 1.選擇文件 2.點擊導入 3.導入的接口 三.多接口運行 1.集合右鍵&#xff0c;點擊run &#xff0c;運行多個接口 2.編輯環境&#xff0c;集合&#xff0c;執行次數等 3.運行多個接口 四.運行…

深挖增長內核:好產品驅動增長的全方位解析

年前在老板的帶領下深入學習了《增長黑客》&#xff0c;并思考了在CPS站外引流的落地方案&#xff0c;最近剛好在做京東聯盟的京粉推客增長體系建設&#xff0c;再次回顧一下增長黑客方法以及記錄一下思考。 好產品才是增長的根本。增長黑客理念風靡&#xff0c;“啊哈時刻” 概…

新手小白 react-useEffect 使用場景

useEffect 是 React 中的一個非常重要的 Hook&#xff0c;用于處理組件的副作用&#xff08;side effects&#xff09;。它通常在以下幾種場景中使用&#xff1a; 1. 數據獲取 當組件加載時&#xff0c;需要從外部 API 獲取數據&#xff0c;或者從本地存儲中讀取數據。示例&a…

MySQL 調優:查詢慢除了索引還能因為什么?

文章目錄 情況一&#xff1a;連接數過小情況二&#xff1a;Buffer Pool 太小 MySQL 查詢慢除了索引還能因為什么&#xff1f;MySQL 查詢慢&#xff0c;我們一般也會想到是因為索引&#xff0c;但除了索引還有哪些原因會導致數據庫查詢變慢呢&#xff1f; 以下以 MySQL 中一條 S…

【操作系統】進程三種狀態?進程間狀態的切換?掛起態?

進程狀態 進程的五種&#xff08;三種&#xff09;狀態&#xff1a; 新建&#xff08;New&#xff09;&#xff1a;進程剛被創建&#xff0c;尚未加入到就緒隊列&#xff1b;就緒&#xff08;Ready&#xff09;&#xff1a;進程已獲得除CPU外的所有資源&#xff0c;等待被調度執…

計算機控制系統的最小拍控制器設計及仿真分析

1題目 開環傳遞函數 G(s) 2/(s(0.5s1)) &#xff0c;采樣周期 T0.5 秒&#xff0c;設計單位速度輸入下的最小拍控制器 1.1 方法1 根據課本中的步驟&#xff0c;最小拍控制器的設計步驟如下&#xff1a; 1. 確定對象的離散傳遞函數G(z)&#xff0c;并確定其零極點。 2. 確定…

哈希--哈希桶

哈希桶是哈希表&#xff08;散列表&#xff09;中的一個概念&#xff0c;是哈希表數組中的每個元素 &#xff0c;用于存儲鍵值對數據。它有以下特點和相關要點&#xff1a; 結構與原理&#xff1a;哈希表底層常由數組構成&#xff0c;數組的每個元素即哈希桶。通過哈希函數計算…

Linux多線程詳解

Linux多線程詳解 一、Linux多線程概念1.1 什么是線程1.2 進程和線程1.3 進程的多個線程共享1.4 進程和線程的關系 二、Linux線程控制2.1 POSIX線程庫2.2 線程創建2.3 獲取線程ID pthread_self2.4 線程等待pthread_join2.5 線程終止2.6 線程棧 && pthread_t2.7 線程的局…

Midscene.js自然語言驅動的網頁自動化全指南

一、概述 網頁自動化在數據抓取、UI 測試和業務流程優化中發揮著重要作用。然而&#xff0c;傳統工具如 Selenium 和 Puppeteer 要求用戶具備編程技能&#xff0c;編寫復雜的選擇器和腳本維護成本高昂。Midscene.js 通過自然語言接口革新了這一領域&#xff0c;用戶只需描述任…

winstart.wsf 病毒清理大作戰

0x00 背景 發現感染了winstart.wsf 病毒如何清理。 0x01 現象 遍歷Users下每個目錄以及C:\和C:\Windows\Temp 2個目錄寫入病毒文件。 C:\Users\Administrator\AppData\Local\Temp\winstart.wsf C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\Start Menu\Program…

多路轉接Poll

在之前我們講過select是最古老的多路轉接方案&#xff0c;古老就意味著他不是很方便使用&#xff0c;他需要用戶手動保存fd_set這個位圖結構&#xff0c;來表示讀寫事件的關注與否或者就緒性。 而且由于fd_set的大小是固定的&#xff0c;這就意味著他能管理的套接字文件描述符是…

多層感知機的簡潔實現

《動手學深度學習》-4.3-筆記 import torch from torch import nn from d2l import torch as d2l 導入必要的庫和模塊 net nn.Sequential(nn.Flatten(),nn.Linear(784, 256),nn.ReLU(),nn.Linear(256, 10))def init_weights(m):if type(m) nn.Linear:nn.init.normal_(m.we…