STM32歌唱《孤勇者》(标准库)
先说一下自己玩两年的单片机的想法吧,玩了大概有两年了,从刚刚开始的不知所措,到现在的成熟,终于还是搞明白了一件事,编程思路,远远比源码更重要,所以,我接下来会给大家完整的介绍,完成此项目的心得,太心酸了。最后也会把main函数里面完整的代码粘出来。
此项目是哔哩哔哩上面看到的一个小玩意,B站上面的利用的51单片机,而我移植他们的一部分程序,加载到32单片机上了。
实验现象:
https://www.bilibili.com/video/BV1j34y1W7RU/?vd_source=f6d73e725f237ac544554b57b2c58f16
首先,有一块带无源蜂鸣器的板子,一定是无源蜂鸣器,无源蜂鸣器,会根据加载不同频率的信号,发出不同的声音。
然后,就是乐理知识,每一个音符的频率大小是多少,我也找出来了,这里有低音、中音、高音三种。最基础也就7个:哆来咪发唆啦西;但是这里面又多出来带#号的音符:例:低音4#:表示,比音调4高半个音,比音调5低半个音,就记住比前一个高,比后一个低就行了,咱们有不学音乐,大致了解就行了。
还有就是对于音调的区分:在简谱中,不带点的基本符号叫做中音;在基本符号上面加上一个点叫高音;加两个点叫倍高音;加三个点叫超高音;在基本符号下面加一个点叫低音;加两个点叫倍低音;加三个点叫超低音。
高音的音乐很少很少,而且《孤勇者》也没有用到高音,所以在程序中定义一个数组来存放这些基础音调的频率,我们演奏的歌曲的时候,需要哪个,直接调用,就可以完成曲子了。
基础符号后面的点表示的意思:
那个点是附点,他的时值是他前面时值的一半。也就是说。如果附点前面音符是一拍,那么那个附点就是半拍。如果前面音符是2拍,那附点就是一拍时值。如果前面是四拍的音符,那附点就是2拍。如果附点前面时值是半拍,那么附点就是四分之一拍。
基础音符的频率用一个数组来表示出来。有低音,中音,高音。大部分歌曲都是有这三种音符组成,大家也可以找一下别的歌曲的频率和音符。
我的程序中定义数组:
unsigned int music_table[] =
{ 130,139,147,156,165,175,185,196,208,220,233,247, //0-11 超低音262,277,294,311,329,349,370,392,415,440,466,494, //12-23 低音,正常音符下面有一个点523,554,587,622,659,698,740,784,830,880,932,988, //24-35 中音,正常音符0, //0:不发声音,停止播放,在音乐中叫休止符1046,1109,1175,1245,1319,1397,1480,1568,1661,1760,1865,1976// 高音,正常音符上面有一个点
};
先解释,数组中数据怎么演奏出来吧,定义了两个数组,第一个数组表示基础音符的频率,第二个数组存放《孤勇者》乐谱的频率组合所对应第一个数组的地址。利用数组嵌套的方式去调用。
j=music_table[music[x]];
最基础的源码贴出来了,该拿出来,《孤勇者》的乐谱了,我也找了出来;演奏的是我用红色框起来的那段高潮部分,我也用一个数组来保存这段乐谱:
有人看见就蒙圈了:我来解释一下数组里面数据什么意思;下面还有一个宏定义,来表示这些数据
B6N:表示音符6的低音;
B6H:表示音符6的高音;
36:表示第一个数组的第36的数据0;也就是刚刚上面代码中的休止符,表示停顿。
unsigned char music[] =
{
B6N,B7N,B1H,B2H,B7N,B1H,B1H,36,
//爱 你 孤 身 走 暗 巷
B1H,B7N,B1H,B2H,B7N,B1H,B1H,36,
//爱 你 不 跪 的 模 样
B1H,B2H,B3H,B2H,B3H,B2H,B3H,36,
//爱 你 对 峙 过 绝 望
B3H,B2H,B3H,36,B5H,B5H,B3H,36,
//不 肯 哭 一 场
B6N,B7N,B1H,B2H,B7N,B1H,B1H,36,
//爱 你 破 烂 的 衣 裳
B1H,B7N,B1H,B2H,B7N,B1H,B1H,36,
//却 敢 赌 命 运 的 枪
B1H,B2H,B3H,B2H,B3H,B2H,B3H,36,
//爱 你 和 我 那 么 像
B3H,B2H,B3H,36,B5H,B5H,B3H,36,36,
//缺 口 都 一 样
B5H,B3H,B3H,36,36,B5H,B3H,36,36,
//去 吗 配 吗
B5H,B3H,B5H,B6H,B3H,B5H,36,
//这 褴 褛 的 披 风
B5H,B3H,B5H,B3H, 36,
//战 马 斩 啊
B5H,B3H,B5H,B6H,B3H,B5H,36,
//以 最 卑 微 的 梦B5H,B5H,B3H,B2H,B2H,B2H,B1H,B3H,B3H,B2H,B2H,B2H,B1H,B1H,B6N,36,36,
//掷 那 黑 夜 中 的 呜 咽 与 怒 吼B5H,B5H,B3H,B2H,B2H,B2H,B1H,B3H,B3H,B2H,B2H,B2H,B1H,B1H,B6N,36,
//谁 说 站 在 光 里 的 才 算 英 雄
};
还有一个宏定义:
#define B6N 19
#define B7N 21
#define B1H 23
#define B2H 24
#define B3H 26
#define B4H 28
#define B5H 29
#define B6H 31
《孤勇者》对应的音符组合,每个音符的频率在第一个数组的位置。
接下来就是控制频率了,频率就是在一秒钟跳变了几次,所以我就直接利用延迟函数,来控制每次跳变的时间,也就是周期的一半:
j:表示频率,控制每个音符持续多长时间,控制每的音符的周期
i:也表示频率,控制while(i--)控制周期
delay_us(500000/j):1/262等于周期T(s),换成一半周期的,单位us的周期
i=j*0.6;//半节拍(控制每个音符持续多少时间)while(i--)//控制周期(1s跳变多少次){GPIO_Trgger();delay_us(500000/j);// 1/262等于周期T(s),换成一半周期的,单位us的周期}
main函数的程序:没有多少新东西,就是那个时间控制的有点微妙,多看几遍;
#include "stm32f10x.h"
#include "SysTick.h"
#include "usart.h"
#include "gpio.h" #define B6N 19
#define B7N 21
#define B1H 23
#define B2H 24
#define B3H 26
#define B4H 28
#define B5H 29
#define B6H 31unsigned int music_table[] = {130,139,147,156,165,175,185,196,208,220,233,247,//0-11半音262,277,294,311,329,349,370,392,415,440,466,494,//12-23 低音523,554,587,622,659,698,740,784,830,880,932,988,0};//24-35 中音unsigned char music[] = {B6N,B7N,B1H,B2H,B7N,B1H,B1H,36,//爱 你 孤 身 走 暗 巷B1H,B7N,B1H,B2H,B7N,B1H,B1H,36,//爱 你 不 跪 的 模 样B1H,B2H,B3H,B2H,B3H,B2H,B3H,36,//爱 你 对 峙 过 绝 望B3H,B2H,B3H,36,B5H,B5H,B3H,36,//不 肯 哭 一 场B6N,B7N,B1H,B2H,B7N,B1H,B1H,36,//爱 你 破 烂 的 衣 裳B1H,B7N,B1H,B2H,B7N,B1H,B1H,36,//却 敢 赌 命 运 的 枪B1H,B2H,B3H,B2H,B3H,B2H,B3H,36,//爱 你 和 我 那 么 像B3H,B2H,B3H,36,B5H,B5H,B3H,36,36,//缺 口 都 一 样B5H,B3H,B3H,36,36,B5H,B3H,36,36,//去 吗 配 吗B5H,B3H,B5H,B6H,B3H,B5H,36,//这 褴 褛 的 披 风B5H,B3H,B5H,B3H, 36,//战 马 斩 啊B5H,B3H,B5H,B6H,B3H,B5H,36,//以 最 卑 微 的 梦B5H,B5H,B3H,B2H,B2H,B2H,B1H,B3H,B3H,B2H,B2H,B2H,B1H,B1H,B6N,36,36,//掷 那 黑 夜 中 的 呜 咽 与 怒 吼B5H,B5H,B3H,B2H,B2H,B2H,B1H,B3H,B3H,B2H,B2H,B2H,B1H,B1H,B6N,36,//谁 说 站 在 光 里 的 才 算 英 雄}; int main(void)
{uint16_t i=0,j=0;unsigned int x=0,endx=0;My_USART_Init();SysTick_Init(72);My_GPIOInit();endx = sizeof(music);while(1){j=music_table[music[x]];i=j*0.6;//半节拍(控制每个音符持续多少时间)while(i--)//控制周期(1s跳变多少次){GPIO_Trgger();delay_us(500000/j);// 1/262等于周期T(s),换成一半周期的,单位us的周期}if(j==0)//休止符{delay_ms(200);GPIO_Trgger_JQD();}x++;if(x>=endx)x=0;}
}
STM32歌唱《孤勇者》(标准库)相关推荐
- stm32简易示波器(标准库)
简介 此项案例是基于正点原子精英板制作的一个简易示波器,可以读取信号的频率和幅值,并可以通过按键改变采样频率和控制屏幕的更新暂停. (输入最大3.3V,由ADC参考电压决定) 将PA6与PA4相连,可 ...
- 【STM32】PWM 输出 (标准库)
Author:AXYZdong 自动化专业 工科男 有一点思考,有一点想法,有一点理性! 定个小小目标,努力成为习惯!在最美的年华遇见更好的自己! CSDN@AXYZdong,CSDN首发,AXYZd ...
- STM32标准库、HAL库特点与应用
新手在入门STM32的时候,一般大多数都会选用标准库和HAL库,而极少部分人会通过直接配置寄存器进行开发. 对于刚入门的朋友可能没法直观了解这些不同开发发方式彼此之间的区别,本文试图以一种非常直白的方 ...
- STM32F103ZET6新建标准库的工程
1.背景: 主要记录STM32芯片在使用标准库的情况下如何新建工程. 2.工程的准备 1)下载并安装STM32F103的芯片包 2)准备好STM32的固件库 2.1:芯片包的下载 芯片包官方链接:ht ...
- 将STM32的标准库编译成lib
转载自:http://www.cnblogs.com/zyqgold/p/3189719.html 以前一直使用STM32的标准库,需要一步步地将代码加进去,将编译选项设置好,然后再编译整个工程. 这 ...
- IAR新建stm32工程,完美移植stm32标准库(附源码)
开发环境:Window 10 64bit 开发工具:IAR Embedded Workbench 硬件:stm32f103c8t6 基于IAR 开发工具,新建立STM32F1系列的最小开发例程,并加入 ...
- keil stm32标准库放在哪里_STM32之PWM
脉冲宽度调制 脉冲宽度调制是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效且应用十分广泛的技术,例如直流电机的控制.开关电源的输出调制.信号的传递也离不开脉冲宽度调制. 我们接下将要讨论的便 ...
- 了解库开发,我们从STM32标准库开发学起
摘要:从STM32新建工程.编译下载程序出发,让新手由浅入深,尽享STM32标准库开发的乐趣. 自从CubeMX等图像配置软件的出现,同学们往往点几下鼠标就解决了单片机的配置问题.对于追求开发速度的业 ...
- STM32标准库修改HSI时钟教程
目录 前言 一.官方标准库是如何改变时钟的? 二.修改系统时钟 前言 在我们常用的STM32 Blue Pill(如下图所示)上,一般在学习时都会使用默认的72Mhz晶振.但当我们自己设计电路板时,如 ...
最新文章
- R语言使用pROC包绘制ROC曲线实战:roc函数计算AUC值、plot.roc函数绘制ROC曲线、添加置信区间、为回归模型中的每个因子绘制ROC曲线并在同一个图中显示出来
- bat脚本监控tomcat并启动_Windows server利用批处理脚本判断端口启动tomcat的方法
- ffplay 分析(音频从Frame(解码后)队列取数据到SDL输出)
- NIPS风波 | 获奖者登台开炮:ML是炼金术,大神LeCun强硬回怼
- Nginx upstream性能优化
- linux操作实例,linux下的一些文档操作实例 | Soo Smart!
- html不支持js,解决Firefox不支持Js的InnerHtml问题
- MangoDB基础-02
- 2007最新最强杀毒软件破解大全
- php集成坏境下载,常见php集成环境安装包
- pdf怎么编辑修改内容?以下方法你都知道吗
- 德鲁克谈《自我管理》笔记摘要
- 浅谈车联网与大数据分析
- ubuntu设置相机为固定焦距
- 案例:世界500强如何打造汽车后市场智慧门店
- Matplotlib可视化②——3D绘制散点图曲面图折线图等高线图
- Flutter路由处理routes技巧
- SoapUI的一些基本设置
- 【XSS漏洞03】XSS漏洞验证、语句构造与绕过方法
- 【blade的UI设计】理解前端MVC与分层思想