基于STM32F103,用蜂鸣器播放歌曲

article/2025/9/10 13:02:51

本文的内容,分为下面几部分:

1,参考网上例程;

2,移植,运行,查看,尽力理解代码;
3,调整测试参数;
4,添加一首歌曲。
        

下面详细描述一下过程:

一,参考网上例程

主要参考的是这一篇《使用STM32F103控制蜂鸣器发声播放音乐》,地址如下:
使用STM32F103控制蜂鸣器发声播放音乐_blue@sky的博客-CSDN博客_stm32蜂鸣器音乐代码
看起来代码比较简洁,就两个文件,就开始移植到自己的板子上。


二,移植,运行,查看代码,尽力理解代码

说明一下,我使用的芯片类型是stm32F103C8,集成开发环境用的是Keil5 MDK-ARM,仿真器使用JLINK。
查看板子上的蜂鸣器接口,相应修改下代码中的引脚。这个和硬件相关,每个人只能根据自己的硬件来调整。
然后是将这个引脚配置成推挽输出,默认是低电平,输出高电平可以驱动蜂鸣器响报警。
然后是开关的操作,Buzzer_On(),Buzzer_Off()来替换;
然后就开始运行,能听到蜂鸣声响,但是刺刺啦啦的,不像音乐。
没有办法,偷懒不行啦,就只好开始看程序了,尽力去理解代码。毕竟代码在手,任我蹂躏,哈哈!
大体理解了一遍程序,调整了几个延时相关的值,发现效果有所好转,比较像音乐了。
但是,到底对不对,对于例程中的歌曲《红尘情歌》,我没听过啊,比较不出来对不对,好不好。
如果能添加一首自己熟悉的歌曲,就能判断了。不过,先别着急,慢慢来。先来个最简单的,就是先听听“多瑞咪”吧。

    u8 music[]={13,1,2,3,4,5,6,7,8};//音调 测试基础音u8 time[] ={4, 4,4,4,4,4,4,4,4};//持续时长

例子中,歌曲由两个数组来表示,一个是音调,一个是这个音调的持续时长。
音调数组music[],里面的数字看起来就是123,与曲谱上的一样,它是怎么实现那个声音的呢?
看代码,是这么调用的:   

 tone[music[i]]

也就是说,是把它作为索引传给了tone[]数组,而tone[]的定义如下:    

	//             低7  1   2   3   4   5   6   7  高1 高2  高3 高4 高5 不发音uc16 tone[] = {247,262,294,330,349,392,440,294,523,587,659,698,784,1000};//音频数据表

这个数组中的数值,又有什么用呢?
注释说是音频数据。根据蜂鸣器的原理,就是输出不同频率的PWM波,即可发出不同的声音(音符)。然后将不同的音符组合起来就是一个曲子。所以这里的数据应该是用于控制蜂鸣器的发声频率的。
看看调用的地方:

        for(e=0;e<((u16)time[i])*tone[music[i]]/yanshi;e++){Sound((u32)tone[music[i]]);}

查看一下Sound()这个函数,这可是核心函数:

void Sound(u16 frq)
{u32 time;if(frq != 1000){time = 500000/((u32)frq);PBeep = 1;delay_us(time);PBeep = 0;delay_us(time);}elsedelay_us(1000);
}

其实也很简单,就是打开蜂鸣器,持续一会,然后关闭蜂鸣器,持续同样时间。
然后再看看调用的地方:

        for(e=0;e<((u16)time[i])*tone[music[i]]/yanshi;e++){Sound((u32)tone[music[i]]);}

是用时长来做控制,重复调用了许多次Sound()播放声音。这样持续起来,听起来就是一个音符了。

跑起来程序,让我们来听听“多瑞咪”!
嗯~~有点问题,有个音听起来不对劲!仔细听,数了数,对应的应该是7(第8个音),再仔细看一遍:

	//             低7  1   2   3   4   5   6   7  高1 高2  高3 高4 高5 不发音uc16 tone[] = {247,262,294,330,349,392,440,294,523,587,659,698,784,1000};//音频数据表

这个音对应的是294,在这个数组中有些不协调啊!
其他的数据,都是按从小到大的顺序排列的,这个数怎么比左右的数都小啊?
难道写错了?如果也按是顺序来的话,我看改为494比较协调。
那就改改呗,代码在手嘛,哈哈!
改了下,一听,还真就顺耳了,我是不是天才,哈哈!(A:天才?我看是多了两横。B:我看不光是要去掉两横,还要去掉一个“才”字。)
闲话少说,继续调试。    


三,调整测试参数

    到现在,大体能听出来是个音乐了,但是播放太快了(与板子上硬件相关),不太舒服,调调延时吧。
    大体相关的有几个参数:
    1,持续时长,就是time[]数组,但是,一旦调整,需要每个参数都修改一遍,太累了。
    2,有没有修改一处,所有音符的播放时长都变的?
    有!就是这个:
    yanshi = 2;//10;
    把它调小,循环播放的次数是增加的,也就是音符的持续时间变长了。
    3,还有一个值,就是前面Sound()函数中的time值,这个值影响的是音调准不准。具体怎么计算的,我也没搞明白,就是多试了几个值,挑了个听着舒服的。

对这几个参数一顿调整后,“多瑞咪”听着就很顺畅了。

下面,最激动人心的时刻到了!
    

四,添加一首歌曲


早就想添加一首歌曲了,不过真要开始添加,也还有点忐忑,得弄首自己熟悉的吧,不能弄太复杂的吧,嗯,来首儿歌吧,就选《小燕子》吧。
先上网找个谱子,仔细看看,嗯,也就是搞定两个数组嘛,一个音调,一个音长。
查看乐谱,如下:
    
真到了转换简谱到数组的时候,这时就能发现选择儿歌的好处了,所有的音调都在tone[]数组中,也就是说,在低音7到高音5之间。让我们再看一遍这个数组:

	//             低7  1   2   3   4   5   6   7  高1 高2  高3 高4 高5 不发音uc16 tone[] = {247,262,294,330,349,392,440,494,523,587,659,698,784,1000};//音频数据表

如果搞了一个复杂的歌曲,音调的范围超过了这个范围,就需要自己研究下那些新音符对应的是什么频率值了。
至于时长,这里是用的4表示1拍的时长。这样,半拍(一个音符下有一道横线)就是2,四分之一拍(一个音符下有两道横线)就是1了,还有两拍的,就是8。
这样,音调与时长都搞定了,是不是就ok了?
嗯,基本上可以这么说,不过,还有些小细节,例如,在两个音符中间的一个小点是什么?
我在这里就犯过错,我还以为是休止符(不知道是从那里获取的错误信息!也许真的有必要将大脑中的知识点都梳理一遍),后来查了一下,这玩意叫附点,看介绍:
附点的符号很简单,就是单纯音符后面的小圆点。附点的作用是:将前面挨着它的单纯音符的时值延长一半。
还有一个小细节,就是在一句歌词唱完之后,需要停顿一会,这时候,就用上了音频数据表中一个特殊的值:1000,前面注意看的话,在Sound()中就有对它的特殊处理,就是不开启蜂鸣器,只是一个延时。 
这时再听听,就有些感觉了哈!
后面就是根据整体感觉,做点微调了,例如,我就调整了下尾部拖音的时长,本来是8(两拍),我改为6(一拍半),似乎听起来更好听了,哈哈!

下面是我修改后的代码:

#include "beep.h"
#include "stm32f10x.h"
#include "gpioHandler.h"
#include "timerHandler.h"void BEEP_Init(void)
{   GPIO_InitTypeDef  GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	 //使能A端口时钟GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;	 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速度50MHzGPIO_Init(GPIOB, &GPIO_InitStructure);	  //初始化GPIOD3,6GPIO_SetBits(GPIOB,GPIO_Pin_5);	
}void Sound(u16 frq)
{u32 time;if(frq != 1000){
//		time = 500000/((u32)frq);time = 100000/((u32)frq);
//		PBeep = 1;Buzzer_On();//打开蜂鸣器--根据自己的硬件情况调整,通常就是控制蜂鸣器的gpio引脚置1delay_us(time);
//		PBeep = 0;Buzzer_Off();//关闭蜂鸣器--根据自己的硬件情况调整,通常就是控制蜂鸣器的gpio引脚置0delay_us(time);}elsedelay_us(1000);
}
void play_music(void)
{//             低7  1   2   3   4   5   6   7  高1 高2  高3 高4 高5 不发音uc16 tone[] = {247,262,294,330,349,392,440,494,523,587,659,698,784,1000};//音频数据表//小燕子u8 music[]={3,5,8,6,5,13,//音调3,5,6,8,5,13,8,10,9,8,9,8,6,8,5,13,3,5,6,5,6,8,9,5,6,13,3,2,1,2,13,2,2,3,5,5,8,2,3,5,13};u8 time[] ={2,2,2,2,6,4,//时间  2,2,2,2,6,4,6,2,4,4,2,2,2,2,6,4,6,2,4,2,2,4,2,2,6,4,2,2,4,6,4,4,2,2,4,4,4,2,2,6,4};
//	u8 music[]={13,1,2,3,4,5,6,7,8};//测试基础音
//	u8 time[] ={4, 4,4,4,4,4,4,4,4};u32 yanshi;u16 i,e;yanshi = 2;//10;  4;  2for(i=0;i<sizeof(music)/sizeof(music[0]);i++){for(e=0;e<((u16)time[i])*tone[music[i]]/yanshi;e++){Sound((u32)tone[music[i]]);}	}
}

调用的时候,就是两句代码:

	BEEP_Init();play_music();

后记:

鉴于有网友提出疑问,所以补充了部分内容:

补充 beep.h:

#ifndef __BEEP__H
#define __BEEP__H#include "stdlib.h"      void BEEP_Init(void);
void Sound2(short time);
void play_music(void);
void play_successful(void);
void play_failed(void);#endif

补充几个相关函数:

void Buzzer_On(void)
{GPIO_SetBits(BUZZER_GPIO_PORT, GPIO_Pin_5);
}void Buzzer_Off(void)
{GPIO_ResetBits(BUZZER_GPIO_PORT, GPIO_Pin_5);
}void delay_us (const uint32_t usec)
{RCC_ClocksTypeDef  RCC_Clocks;/* Configure HCLK clock as SysTick clock source */SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);RCC_GetClocksFreq(&RCC_Clocks);// Set SysTick Reload(1us) register and Enable// usec * (RCC_Clocks.HCLK_Frequency / 1000000) < 0xFFFFFFUL  -- because of 24bit timerSysTick_Config(usec * (RCC_Clocks.HCLK_Frequency / 1000000));//HCLK_Frequency=48M// 72/72000000 --> 1usec// 0.001msec = 1usec// 1Hz = 1sec, 10Hz = 100msec, 100Hz = 10msec, 1KHz = 1msec,// 10KHz = 0.1msec, 100Khz = 0.01msec, 1MHz = 1usec(0.001msec)// 1usec = 1MHz// SysTick Interrupt DisableSysTick->CTRL  &= ~SysTick_CTRL_TICKINT_Msk ;// Until Tick count is 0while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
}

更详细的定时器怎么使用的说明,参见另一篇博文:
https://blog.csdn.net/lintax/article/details/84918791?spm=1001.2014.3001.5501
 


http://chatgpt.dhexx.cn/article/piudWIj0.shtml

相关文章

Django实现音乐网站 ⑷

使用Python Django框架制作一个音乐网站&#xff0c;在系列文章3的基础上继续开发&#xff0c; 本篇主要是后台歌曲类型表、歌单表模块功能开发。 目录 表结构设计 歌曲类型表结构 歌单表结构 创建表模型 创建表 后台注册表模型 引入表模型 后台自定义 总结 表结构设计…

Django计算机毕业设计基于Web的在线音乐网站(程序+lw)Python

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

springboot+jsp云端在线音乐分享平台java

随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势&#xff0c;在线音乐平台当然也不能排除在外&#xff0c;从歌曲类型、歌手信息、歌曲信息、音乐资讯的统计和分析&#xff0c;在过程中会产…

计算机毕业设计Node.js+Express音蕾心动(源码+程序+lw+远程调试)

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

计算机毕设Node.js+Vue音蕾心动(程序+LW+部署)

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

基于jsp和ssm架构实现KTV点歌系统演示【附项目源码+论文说明】分享

基于jsp和ssm架构实现KTV点歌系统演示 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#…

Python-Django毕业设计音蕾心动(程序+Lw)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

Python+Django毕业设计音蕾心动(程序+LW+部署)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

基于jsp和ssm架构实现KTV点歌系统演示【附项目源码+论文说明】

基于jsp和ssm架构实现KTV点歌系统演示 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#…

(附源码)计算机毕业设计ssm爱音乐网站

毕设帮助&#xff0c;指导&#xff0c;本源码分享&#xff0c;调试部署(见文末) 3.4系统UML用例分析 3.4.1管理员用例 管理员登录后可进行首页、个人中心、用户管理、热门歌手管理、歌曲类型管理、歌曲信息管理、音乐视频管理、留言板管理、系统管理&#xff0c;管理员用例如…

计算机毕业设计Node.js+Vue基于Web的在线音乐网站(程序+源码+LW+部署)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离…

Python爬虫:想听榜单歌曲?使用BeautifulSoup库只需要14行代码即可搞定

目录 BeautifulSoup库安装BeautifulSoup库BeautifulSoup库简介选择解释器基础用法 节点选择器获取节点名称属性内容获取所有子节点获取所有子孙节点父节点与兄弟节点 方法选择器find_all()方法find()方法 CSS选择器嵌套选择节点获取属性与文本 通过浏览器直接Copy-CSS选择器实战…

【java毕业设计】基于B/S结构+mysql的KTV点歌系统设计与实现(程序源码)-KTV点歌系统

基于B/S结构mysql的KTV点歌系统设计与实现&#xff08;程序源码毕业论文&#xff09; 大家好&#xff0c;今天给大家介绍基于B/S结构mysql的KTV点歌系统设计与实现&#xff0c;本论文只截取部分文章重点&#xff0c;文章末尾附有本毕业设计完整源码及论文的获取方式。更多毕业设…

Django实现音乐网站 ⑽

使用Python Django框架制作一个音乐网站&#xff0c; 本篇主要是后台对歌曲类型、歌单功能原有功能进行部分功能实现和显示优化。 目录 歌曲类型功能优化 新增编辑 优化输入项标题显示 父类型显示改为下拉菜单 列表显示 父类型显示名称 过滤器增加父类型 歌单表功能优化…

原始音频数据合成音频文件_根据音频数据对歌曲类型进行分类

原始音频数据合成音频文件 Over the past few years, streaming services have become the primary means through which most people listen to their favourite music. However, this can mean that users might find it difficult to look for newer music that suits their…

vue实现多页面应用

近期做的vue项目中&#xff0c;需要新增一个系统帮助页面&#xff0c;并且要在新的窗口中打开&#xff0c;但是vue是单页面应用&#xff0c;所以只能对项目进行改造&#xff0c;变成多页面项目。 第一步:在和index.html页面同级下新增一个helpinfo.html,在src目录下新增一个js目…

创建Vue单页面应用的3种方法

创建Vue单页面应用的3种方法 首先下载Vue CLI1.命令行创建&#xff08;推荐&#xff09;2.Vue ui&#xff08;不推荐&#xff09;3.Vite&#xff08;未来流行&#xff0c;现在还不稳定&#xff09; 首先下载Vue CLI 官方链接&#xff1a;https://cli.vuejs.org/zh/guide/insta…

单页和多页应用(vue.js学习笔记)

1.什么是单页面和多页面&#xff1f; 单页&#xff1a; 单页应用将所有内容放在一个页面中&#xff0c;从而使整个页面更加流畅就用户体验而言&#xff0c;单机导航可以定位锚点&#xff0c;快速定位相应的部分&#xff0c;并轻松上下滚动。单页面应用提供的信息和一些主要内容…

Vue-router: 实现纯前端多页面应用(Vuecli+Element UI)

1.简介 1.1 为什么要用Vue-router 我想做一个带导航栏的简单web页面&#xff0c;页面的内容可以随导航栏的点击切换。第一个想法是想用webpack打包出几个页面&#xff0c;然后在每个页面的按钮上添加链接&#xff0c;但是这样做每次页面都要刷新&#xff0c;效率上存在很大问…