当前课程知识点:ARM微控制器与嵌入式系统 >  第五章 ARM微控制器的各种外设 >  5.5.3 ARM微控制器外设:PWM编程实例—电子音乐 >  5.5.3 ARM微控制器外设:PWM编程实例—电子音乐

返回《ARM微控制器与嵌入式系统》慕课在线视频课程列表

5.5.3 ARM微控制器外设:PWM编程实例—电子音乐在线视频

5.5.3 ARM微控制器外设:PWM编程实例—电子音乐

下一节:E4 实验四 数码管显示编程实操

返回《ARM微控制器与嵌入式系统》慕课在线视频列表

5.5.3 ARM微控制器外设:PWM编程实例—电子音乐课程教案、知识点、字幕

各位同学大家好

我是清华大学工程物理系的曾鸣老师

欢迎大家继续我们的

ARM微控制器与嵌入式系统的MOOC之旅

那么这个单元呢

进入了我认为我们在这个课里

最最好玩的单元之一

那么我们真的要用一个引脚

来产生PWM的脉冲信号

来把我们的音乐给玩起来

我们前面做了很多的铺垫

PWM什么原理啊

一个引脚接在PTC8

是PWM模块的Channel4

等等怎么编程

这些基本知识都有了

最最核心内容是我们怎么把它玩起来呢

我们来看看我们的电路

之前提到我们这个引脚

是通过了一个晶体管来控制了一个蜂鸣器

这是一个频率调制的蜂鸣器

也就是说它播放出的音高

是跟我们给它的电信号的频率

在很大的一个可听到的范围内是一致的

换言之我们产生什么频率的脉冲电信号

给这个蜂鸣器

这个蜂鸣器就会得到不同频率的声音

那么我们很多同学都学过

高中物理或者大学物理

都知道声音的三要素

这个频率决定了音高对吧

当然还有响度还有音色

这个在一个简单蜂鸣器里我们就不探讨了

我们只讨论频率

放一个最简单的电子音乐

那么我们的音高怎么对应不同的频率呢

那么我们看一看这张图

显示了钢琴的这个黑白琴键

每一个因素对应的频率

我们这是一门电子学的课

当然不会回忆从巴赫的时代开始

怎么制定这个钢琴率

但是大家有一个概念

就是不同的音高肯定对应不同频率

有一些同学可能不熟的一个概念

是从1、2、3、4、5、1、6、7

到这个低音、高音的八度之间

它的频率刚好是2倍的关系

也就是高音1低音1之间的频率

正好是二分之一的关系

所以我们的中央C

C大调的1

它的频率非常好记

是261.5赫兹

那么对应的高音1

就是523赫兹

所以我们在这张表上

可以查到每一个音所应该产生的频率

都在这个百赫兹量级

我们都知道人的耳朵的听觉范围

是从几十赫兹到四万赫兹左右这个范围

所以我们要控制我们的电信号

产生这些对应的频率

去驱动我们的蜂鸣器

我们就能听到这些声音

这里要讲的是

其实有很多同学的耳朵非常的好

你会听这个音准不准

特别像曾老师这种五音不全的

我们在编程的时候又是一个计算机爱好者

我最开始的时候会觉得

哎呀这个261.5赫兹

523赫兹这种数实在是不美

太难记了

我会特别喜欢用2的整数幂

比如256赫兹

512赫兹这不挺好嘛

然后编程序

编着编着就忘了

直到有一天有个同学跟我说曾老师

你给的例程这个音实在是太不准了

所以大家可以看一看

你的PWM寄存器的值的设置

如何得到这些值

那么有的同学说

我如果不是C大调怎么办呢

音乐好的同学当然你可以去对不同的调

去查你的音所对应的频率

那么有了这些音

我们从哪里得到一个曲子呢

这当然也不是问题了

现在有很多什么钢琴爱好者网络

什么各种歌曲歌谱网

特别音乐不识五线谱的同学

曲盲的同学你可以在网上找到像这样的简谱

比如说很怀旧

这个1995年前后《仙剑奇侠传》

这个游戏的第一代

它的谱 它的曲 背景音乐

就可以在网上找到

那有的同学喜欢看韩剧

比如说你可以找这个《Kiss the Rain》

这样一首钢琴曲的简谱

那么找到这些谱

你知道了它的谱的构成

我们用一种非常

解构主义非常不美的方式

从计算机爱好者的角度来看这些东西

它就变得不那么艺术了

它是什么呢

它是一个由不同频率和不同的持续时间长度

构成的二维数组

是不是被我这么一讲

大家顿时失去了对音乐那种美好的感觉

但是我们编程的时候

确实无奈

我们一定要把它转换成

可以用程序表达的方式

好 那么问题来了

如果我们写了一个很有意思的小程序

我们做了一个很有意思的功能

希望我们的微控制器 配置蜂鸣器

加上PWM模块

前面讲的编程把音乐玩起来

大家怎么实现它

那么与之类似的还有一个问题

就有同学说曾老师你讲了很多外设

你什么时候教我们

来把这个东西给封装起来

封装成函数加以使用

所以今天的内容不是一次实验

而是我给大家讲一讲这些思想

然后带着大家把它给实现

那么在这样一种编程实现里

我觉得思维上

可能会有四个步骤要加以考虑

第一个步骤我们PWM模块会有基础的时钟

这个时钟是20.97兆除以128

得到一个频率大约是百K量级

所以我把它define成了一个宏

在我们的代码的第一句

然后第二个概念呢

我们以这个时钟为单元进行计数

我们会设置一个计数器的值

决定当前的这个引脚

所对应这个模块的周期

周期被寄存器决定了

反过来就决定了频率

所以其实我们可以计算我们给寄存器

所应该设的值应该是

我们的系统时钟TPM模块所使用的时钟

也就这百K赫兹这个时钟

与我们目标频率做除法得到的商

大家想想这个概念

所以我们用我们已有的输入时钟频率

除以我们想要得到的比如说523赫兹

或者261.5赫兹

这个音乐的频率

这两者一除得到的值 取整

应该是我们给这个周期寄存器

这个MOD寄存器未来将要设置的值

它会决定PWM模块输出信号的频率

所以我们提前可以把我们要的不同音的

音高的这些目标值

这些寄存器将要设的值

像曾老师给的代码这样

尝试都定义成一个一个的宏

那么我会使用L1到L7

M1到M7

还有这个高音的1到高音的7

来表示三个8度里头的

1、2、3、4、5、6、7 对不对

然后当然我还会00这样的值来表达休止符

暂时不放音乐

那么一旦完成了这一系列的宏定义

我们未来对于这个寄存器设置的时候

只用设置这些宏

这些比较形象的宏

M3、M0

并能把它配置我们要的音高

使我们的代码

进行了第一次的封装 变得简化

第二个层面呢

就是对于我们所学到的PWM模块

去做串口的时候

大家已经开始有这种感觉

我们会尝试把它封装成有限个函数

来方便我们的主程序或者别的程序

在代码复用的情况下灵活的调用

那么在我们播放音乐

这样一个特别简单的功能里

我们可以把它封装如右所示的这两个函数

一个是我们TPM或者PWM模块的

init函数初始化

那么这个里头其实就完成了上节课

我给大家讲过的那几个初始化的步骤

配置时钟打开

配置时钟源

配置引脚给PWM模块用

配置TPM模块的初始值寄存器

那么我下面把它封装成了一个特别小的函数

来设置当前PWM模块这个通道

这个模块所产生的频率

那么目前这个函数的写法我只给了一个参数

这个参数是什么呢

就是前面我们每个音高的宏定义

对应的要给

周期的那个MOD寄存器

将要赋予的值

我作为参数给这个函数

所以这个函数一调用

我给了一个参数给他

他就把我们当前的PWM模块

配置为我将要要的那个频率

改变频率

然后里头我有一句话

第二句话大家注意读一读

是将这个C4V

也就是我们通道4的

这个占空比的这个寄存器

设置为了

我们周期这个值的一半

也就使我们的占空比永远是50%

频率高 频率低

设置的周期值大 周期值小

它总是它的一半

那么我们这里留了个引子

大家思考一下

如果我们改这个占空比

可能会有什么效果

声音的三要素

频率 响度和音色

所以愿意动脑筋同学你可以联想

他可能会对声音的音量产生影响

所以这个尾巴留给大家以后自己尝试改

我们可以尝试把这个函数

改成两个参数的函数进一步的封装

同时设置频率又设置音量

这个留给大家以后

那么第二个问题已经讲完

就是有了这两个函数

我们完成了对于这个模块的

一个封装 对不对

我们有了对于音高

以一种宏的方式表达出来

我们有了模块封装成初始化函数

和改变频率的函数

接下来是什么呢

接下来还有两个问题

在下一页我会给大家讲

一个就是如何把我们刚才查简谱的

那种曲子表征为C语言计算机编程

可以呈现和记录的数据结构

如何设计一种程序的机制

让这些函数

这些宏定义和这个数据结构

有机的运行起来

成为一种音乐的播放

是不是还有这两个问题

我来带着大家理清

如何把一个程序表达出来

那么对于数据结构

我刚才说过

其实我是故意说的

一个音乐从一个非常不美的

编程的角度去看

它不是美妙的艺术和旋律

而是一个由音高和音长组成的

二维的一个数组

或者叫每一个源都是一个二维的向量

那么这样一个音高和一个音长

一一对应

我们用一个数据结构来表征它

我们可以有很多种灵活的方法

比如说有的同学学C语言学的好一点的

我会用联合体

我们会用结构体

我会用更复杂的公式

但是根据曾老师多年的教学经验我会发现

学我们这样一门课的入门的同学

往往你最熟悉的数据结构也就仅限于数组

那OK数组就数组

我们用两个数组

来一一对应记录我们的简谱

比如说我这里放了一个简谱

是《玛丽的小羊》对不对

那么大家会发现有了我上一页所讲的

宏定义这张谱

是不是变得非常可读啊

我们以M3、M2、M1

是不是就很容易看出我们标记的是

3212这样的简谱构成了一个数组

每一个源对应一个音高

那么与之一一对应的

我们用另外一个构建的数组

来记录每个音的音长

我们以0X01为单元记录一个八分之一音符

这样把半拍、一拍

分别用不同的音长加以记录

是不是我们就成功的

将一个最最简单的曲谱

表征为了两个数组对吧

然后我在这两个数组的尾部

都留了一个00和0FF这样的特殊字符

来表征告诉我们的程序

这是曲子的结尾部分

便于我们待会编程来使用

那好如果我们不看曾老师给出的代码

大家想一想这些东西都有了

你自己怎么写一个程序把它的音乐放出来

可能绝大多数同学最容易想到的

还是在for循环里头

在main函数里头我写个delay函数

把delay的时间调调调调到这个

最小的音乐的时间长度节拍单元

然后每过一个delay单元

去查一查是不是要放下一个音

然后从数组分别取出下一个源进行播放

然后播放再到一个delay的时候呢

看看这个音的音长有没有播放完

我们可以拿这个音的长度函数做减减运算

减到0为止

这些有些同学可能能想到

然后当这个音的长度播放完了

再在数组里各取下一个源

切换到下一个音的长度

和这个音高来进行播放

在这个过程当中

调用我们刚才封装好的PWM函数的

改变频率的那个接口函数

是不是一种编程思想

那么这个思想如果能想到这一步

其实已经非常不错了

那么在这里我给出的例程呢

是跟我们上一个单元直接关联的

曾老师课非常有意思

就是我会把知识一个一个串起来

每一个单元模块去嵌套着使用前面的知识

大家一个单元都不要落

你就会发现你的本领越来越大

那么在这里我们要使用的是什么呢

是我们最最简单的那个

SysTick时钟中断函数

我们配置好一个时钟中断函数

调一调时钟中断发生的周期频率

比如说我这个SYSTICK_Init里头

我把它调成了八分之一秒发生一次中断

来对应一个这个八分之一音符对吧

那么我们这个时钟中断

每八分之一秒发生一次

我的时钟中断的SysTick_Handler

这个中断响应函数是不是就如我这样所写

里头的函数提示

其实就是我刚才所讲的这个思想 代码

大家可以停下来仔细读一读

就是依次取这个数组里头的源

然后根据这个数组里头的音高

调整PWM里面播放的音高

调用PWM接口函数

同时把这个音

所要播放的音长记录下来

做减减运算

然后根据进入中断的次数

来决定这个音是否播放完了

一旦播放完了用一个指针变量

去寻找下一个源

把这个数组里对应的

下一个源取出来 进行播放

直到遇到数组里头特殊字符表征的

这个曲子的尾部

当然我们在程序上可以灵活

决定我们把程序写成这个曲子

滚动播放 还是播放一遍就停

那么这样就实现了

用中断模式驱动下的一个

音乐的播放

那么我多一个问题

这样一种方式编写

我反复给大家加深对于中断的概念

跟我们最开始说的用main函数里头

用delay来做

有什么好处呢

给大家想几秒钟

大家会发现这样子写了函数以后

我们的main其实仍然是空的

我们播放音乐整个功能

只是在main函数里

增加了一个中断的初始函数

在时钟中断的服务函数里

完成了音乐的播放

他完全没有改变我们原有main函数的

那些结构和功能

所以这样一种模式

使我们在做完了音乐功能里

我们非常容易并行的

去开发我们程序所希望完成的其他功能

也非常容易在一个

已经有完善功能的程序里

添加音乐播放功能

多多少少大家会发现

中断这样一种前后台的模式

帮助我们把我们的代码给剥离开

使我们的任务

使我们的程序

变得更加的清晰 易懂

那么贯穿这样一种思想里头

我们实现了一个非常好玩的音乐播放

而我更希望大家的是去读一读这些代码

你能不能有更好的主意

更巧妙的代码来实现音乐的播放

把我们这个板子从现在开始

越来越有意思的给玩起来

那就是这节课的

这个单元的内容

到这儿结束

ARM微控制器与嵌入式系统课程列表:

第一章 概览

-1.1 课程概览

--1.1 课程概览

-1.2 如何学好嵌入式系统

--1.2 如何学好嵌入式系统

第二章 绪论

-2.1 计算机的基本概念、发展历史

--2.1 计算机的基本概念、发展历史

-2.2 从晶体管到CPU

--2.2 从晶体管到CPU

-2.3 概念CPU、微控制器MCU和嵌入式系统

--2.3 概念CPU、微控制器MCU和嵌入式系统

-2.4 八卦计算机史

--2.4 八卦计算机史与创新

-2.5 不同领域、不同系列的嵌入式系统

--2.5 不同领域、不同系列的嵌入式系统

-2.6 ARM历史与MKL25Z128 MCU

--2.6 ARM历史与MKL25Z128 MCU

--2.6 ARM历史与MKL25Z128 MCU【习题】

--2.6 ARM历史与MKL25Z128 MCU【讨论】

第三章 MCU基础

-3.1 CPU的基本结构和运行机制

--3.1 CPU的基本结构和运行机制

-3.2.1 堆栈的概念

--3.2.1 堆栈的概念

--3.2.1 堆栈的概念【习题】

-3.2.2 堆栈的概念-头脑体操

--3.2.2 头脑体操

-3.3.1 ARM的体系结构

--3.3.1 ARM的体系结构

--3.3.1 ARM的体系结构【习题】

-3.3.2 ARM的体系结构-头脑体操

--3.3.2 ARM的体系结构-头脑体操

-3.4.1 中断的概念和机制

--3.4.1 中断的概念和机制

-3.4.2 中断子程的概念和编程

--3.4.2 中断子程的概念和编程

-3.5 复位、时钟、存储器和总线

--3.5 复位、时钟、存储器和总线

--3.5 复位、时钟、存储器和总线【习题】

-3.6 小结:MCU的总体结构和程序运行机制

--3.6 小结:MCU的总体结构和程序运行机制

--3.6 小结:MCU的总体结构和程序运行机制【习题】

第四章 ARM微控制器的开发

-4.1 第一种外设:IO

--4.1 第一种外设:IO

-4.2 IO外设的编程实操-点亮LED

--4.2 IO外设的编程实操-点亮LED

-4.3 IO外设的进阶知识

--4.3 IO外设的进阶知识

-4.4 嵌入式开发的基本概念与工具链

--4.4 嵌入式开发的基本概念与工具链

-4.5 嵌入式开发的进阶知识

--4.5 嵌入式开发的进阶知识

-4.6 嵌入式开发中的C语言(上)

--4.6 嵌入式开发中的C语言(上)

--4.6 嵌入式开发中的C语言(上)【习题】

-4.7 嵌入式开发中的C语言(下)

--4.7 嵌入式开发中的C语言(下)

--4.7 嵌入式开发中的C语言(下)【习题】

-E0.1 实验零 开发板的初步认识与工具链的安装

--E0.1 实验零 开发板的初步认识与工具链的安装

-E0.2 实验零 体验一个例程的编译与下载

--E0.2 实验零 体验一个例程的编译与下载

-E0.3 实验零 编写第一个程序:点亮核心板LED

--E0.3 实验零 编写第一个程序:点亮核心板LED

-E1 实验一 点灯秘籍

--E1 实验一 点灯秘籍

第五章 ARM微控制器的各种外设

-5.1 ARM微控制器外设学习概述

--5.1 ARM微控制器外设学习概述

-5.2.1 ARM微控制器外设:通讯

--5.2.1 ARM微控制器外设:通讯

-5.2.2 ARM微控制器外设:异步串行通讯UART的原理(上)

--5.2.2 ARM微控制器外设:异步串行通讯UART的原理(上)

--5.2.2 ARM微控制器外设:异步串行通讯UART的原理(上)【习题】

-5.2.3 ARM微控制器外设:异步串行通讯UART的原理(下)

--5.2.3 ARM微控制器的外设:异步串行通讯UART的原理(下)

--5.2.3 ARM微控制器外设:异步串行通讯UART的原理(下)【习题】

-5.2.4 ARM微控制器外设:RS-232串口与USB虚拟串口

--5.2.4 ARM微控制器外设:RS-232串口与USB虚拟串口

-5.2.5 ARM微控制器外设:UART的寄存器编程(上)

--5.2.5 ARM微控制器外设:UART的寄存器编程(上)

-5.2.6 ARM微控制器外设:UART的寄存器编程(下)

--5.2.6 ARM微控制器外设:UART的寄存器编程(下)

--5.2.6 ARM微控制器外设:UART的寄存器编程(下)【习题】

-E2 实验二 UART编程实操

--E2 实验二 UART编程实操

-5.3.1 ARM微控制器外设:IO的中断编程(上)

--5.3.1 ARM微控制器外设:IO的中断编程(上)

-5.3.2 ARM微控制器外设:IO的中断编程(下)

--5.3.2 ARM微控制器外设:IO的中断编程(下)

-5.4.1 ARM微控制器外设:定时器的原理

--5.4.1 ARM微控制器外设:定时器的原理

-5.4.2 ARM微控制器外设:定时器的编程

--5.4.2 ARM微控制器外设:定时器的编程

--5.4.2 ARM微控制器外设:定时器的编程【习题】

-E3 实验三 定时器中断编程实操

--E3 实验三 定时器中断编程实操

-5.5.1 ARM微控制器外设:PWM的原理

--5.5.1 ARM微控制器外设:PWM的原理

-5.5.2 ARM微控制器外设:PWM寄存器与编程

--5.5.2 ARM微控制器外设:PWM寄存器与编程

-5.5.3 ARM微控制器外设:PWM编程实例—电子音乐

--5.5.3 ARM微控制器外设:PWM编程实例—电子音乐

-E4 实验四 数码管显示编程实操

--E4 实验四 数码管显示编程实操

-5.6.1 ARM微控制器外设:SPI通讯简介

-- 5.6.1 ARM微控制器外设:SPI通讯简介

--5.6.1 ARM微控制器外设:SPI通讯简介【习题】

-5.6.2 ARM微控制器外设:SPI寄存器与编程

-- 5.6.2 ARM微控制器外设:SPI寄存器与编程

-5.6.3 ARM微控制器外设:SPI编程实例—OLED显示屏驱动

--5.6.3 ARM微控制器外设:SPI编程实例—OLED显示屏驱动

-5.7.1 ARM微控制器外设:I2C通讯简介

--5.7.1 ARM微控制器外设:I2C通讯简介

-5.7.2 ARM微控制器外设:I2C的通讯协议

--5.7.2 ARM微控制器外设:I2C的通讯协议

-5.7.3 ARM微控制器外设:I2C寄存器与编程

--5.7.3 ARM微控制器外设:I2C寄存器与编程

--5.7.3 ARM微控制器外设:I2C寄存器与编程【习题】

-5.7.4 ARM微控制器外设:I2C编程实例—加速度传感器

--5.7.4 ARM微控制器外设:I2C编程实例—加速度传感器

-5.8.1 ARM微控制器外设:ADC简介

--5.8.1 ARM微控制器外设:ADC简介

-5.8.2 ARM微控制器外设:ADC基础

--5.8.2 ARM微控制器外设:ADC基础

-5.8.3 ARM微控制器外设:ADC寄存器与编程

--5.8.3 ARM微控制器外设:ADC寄存器与编程

-E5 实验五 ADC编程实操

--E5 实验五 ADC编程实操

-E6 挑战实验

--E6 挑战实验

第六章 嵌入式系统设计

-6.1 嵌入式系统的接口与设计

--6.1 嵌入式系统的接口与设计

-6.2 嵌入式系统的实例

--6.2 嵌入式系统的实例

5.5.3 ARM微控制器外设:PWM编程实例—电子音乐笔记与讨论

也许你还感兴趣的课程:

© 柠檬大学-慕课导航 课程版权归原始院校所有,
本网站仅通过互联网进行慕课课程索引,不提供在线课程学习和视频,请同学们点击报名到课程提供网站进行学习。