浅谈用 51hei-5 学习单片机播放音乐(1)
春节无事做,试了一下使用 51hei-5 的单片机播放音乐.
非常遗憾的是:怎么弄也不能正常放出音乐来!-----把 51hei-5 的蜂鸣器焊下来,一测量,哈哈!是一个有源蜂鸣器!----可能焊接元器件出错了!
找了一个 32Ω 的小耳机(不要使用8Ω低阻抗的).代替原来的蜂鸣器.就可以出来音乐了!(蜂鸣器具有尖锐的频率响应点,不适合播放音乐!)
找了一些 51 单片机播放音乐的例子,网络上非常多这种资源.发现这些例子对音乐程序的播放首先是对歌曲简谱进行编码.甚至还有人发布了可以编码给单片机使用的软件.
仔细分析了一下,主要有 2 种编码方式:
第一种:
仅仅使用一个表格,使用 3 字节结构,前面 2 字节是单个音符的数据,这个数据赋值给单片机的定时器后,让定时器溢出时,反转输出端口,产生一个固定频率输出.不同的数据,就有不同的频率,这样,音乐的 1 2 3 4 5 就出来了.第 3 字节是该音符输出的节拍时间.
例如:
DB 0FDH, 5BH,04H
DB 0FDH, 08H,02H
DB 0FCH,0ABH,02H
DB 0FCH, 0BH,02H
DB 0FCH, 0BH,02H
DB 0FFH,0FFH,01H
DB 0FCH, 0BH,02H
第二种:
使用 2 个表格,它专门有一个音符表格,里面包含了从低音 1 2 3.... 到 高音 1 2 3 .... 的单个音符信息.每个音符使用 2 个字节,同样它是给单片机定时器赋值后,让定时器溢出时,反转输出端口,达到输出对应的频率.
例如:
Z_TABL1: ;决定音调的定时初值.----------什么歌都可以使用
;-1
DB 0F8H,095H; _1 ====0
DB 0F9H,070H; _2 ====1
DB 0FAH,025H; _3 ====2
DB 0FAH,065H; _4 ====3
DB 0FBH,000H; _5 ====4
DB 0FBH,090H; _6 ====5
DB 0FCH,00CH; _7 ====6
;≥10-4
DB 0FCH,044H; 1 ====7
DB 0FCH,0ACH; 2 ====8
DB 0FDH,009H; 3 ====9
DB 0FDH,034H; 4 ====10
DB 0FDH,082H; 5 ====11
DB 0FDH,0C8H; 6 ====12
DB 0FEH,006H; 7 ====13
;≥20-7
DB 0FEH,022H; 1_ ====14
DB 0FEH,056H; 2_ ====15
DB 0FEH,085H; 3_ ====16
DB 0FEH,09AH; 4_ ====17
DB 0FEH,0C1H; 5_ ====18
DB 0FEH,0E1H; 6_ ====19
DB 0FEH,0FEH; 7_ ====20
;≥30-10
DB 0FFH,00AH; 1= ====21
另外一个表格就是音乐的表格了,它使用 2 个字节来表示,高字节代表指向某个音符的数字,低字节代表节拍.
例如:
Z_TABL1: ;高字节是音调索引,低字节是节拍长度
;我的祖国(前奏过门)----05=_5(低音),15=5(正常音),25=5_(高音)
DB 13,08;6
DB 13,04;6
DB 15,04;6
DB 16,08;6
DB 16,04;6
DB 21,04;6
DB 22,08;6
DB 23,04;6
DB 21,04;6
DB 22,14
DB 21,2
DB 22,4
DB 13,4
DB 15,4;_5
DB 16,4;_6
DB 17,4;_6
DB 22,4
DB 16,4
DB 17,4
DB 15,16 ;过门完成
DB 00,4
比较一下,上面 2 种方法中,第 2 种方法是很好的.它把基本音符与具体音乐分开了!可以节省大量储存空间.删除歌曲不会影响基本音符在程序里的内容.这些音符内容仅仅被不同音乐的信息来调用,无论上面歌曲,都可以使用它们.
因此,我就使用第二种方法.
接下来,要说的是怎么来编写和辨认这些信息.
当我们得到一份示例程序后,对音乐信息来说,很不直观的.谁也不能一下子看出这些数字是哪一个音符.与原始音乐乐谱完完全全变了样!
如何让程序里的数据与原始音乐对上号呢?------怎么让人一下子看出来是什么呢?
方法是:
把音乐中的 1 2 3 ..... 与音符表格对应起来.就是当你编写程序时,完完全全可以按照原始音乐的简谱照抄下来.
例如:
你可以把 "五星红旗迎风飘扬" 直接写下" 5 5 1 5 3 1 5 6 5 "!----------是不是很直观!
那么,这样如何区别其的音高呢? 同样一个 5 ,有低音,中音,高音 啊!
我们把低音写作 5 ,把中音写作 15 ,把高音写作 25 就可以准确分辨出来.
那么,这些 5 又怎么去获取对应的音符值(定时器值)呢?
我们可以让它与音符表格对应起来.例如上面的 1 2 3 ....低音部分. 表格是从 0 开始放置的,音符是从 1 开始的.那么,把低音的数字 -1 就可以查表获得数据了!
而中音部分呢? 11 是中音的 1 ,音符表格则是在第 7 行, 11-7=4 ,就是说,凡是中音数据,把它们 -4 之后,就对上表格了!
高音部分的 21 是高音的 1 ,音符表格排列在第 14 行, 21-14=7,就是说,凡是高音数据,把它们 -7 之后,就对上表格了!
而判断一个音符的高中低,则是由音符数据的高半字节是 0,1,2....来决定.非常方便!
经过这种改造,编写歌谱时就可以直接照原始歌谱抄了!---------乐曲表格数据的可读性极好!分析查错也就非常方便了!
而节拍信息也是按照原始乐谱来抄写.你可以把一个小节定义为 16 ,也可以定义为 8 或 32 ,定义数字越大,每小节容纳音符的最小时间单位就越少!通常,使用 16 是很好用的!
例如:上面说的 "五星红旗迎风飘扬" ,对应乐谱为 5 5 1 5 3 1 5 6 5 " ,按照该歌曲的节拍和上面说的音高写法,可以写成:
DB 5,4
DB 5,4
DB 11,8
DB 5 ,8
DB 13 ,8
DB 11 ,8
DB 15 ,16
DB 16 ,8
DB 15,8
当我们垂直往下读的时候,原始简谱的信息就直观出来了!(要把读 11 读成中音 1 , 15 读成中音 5 , 05 读成低音5 ......)
下面给出一个 08 奥运的"我和你" 的前面 2 句,可以直接根据数据"哼"出来.)
;===============================================
;我和你
DB 23,08 ;3_
DB 25,08 ;5_
DB 21,16 ;1_
DB 22,08 ;2_
DB 23,08 ;3_
DB 15,16 ;5
DB 21,08 ;1_
DB 22,08 ;2_
DB 23,08 ;3_
DB 25,08 ;5_
DB 22,24 ;2_
DB 00,08 ;2_
DB 23,08 ;3_
DB 25,08 ;5_
DB 21,16 ;1_
DB 22,08 ;2_
DB 23,08 ;3_
DB 16,16 ;6
DB 22,08 ;2_
DB 15,08 ;5
DB 22,08 ;2_
DB 23,08 ;3_
DB 21,24 ;1_
DB 00,08 ;结束音乐
;=========================================
(未完待续)-------仅供参考!
欢迎光临 (http://www.51hei.com/bbs/) | Powered by Discuz! X3.1 |