浅谈用 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 ;结束音乐 ;========================================= (未完待续)-------仅供参考! |