找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4503|回复: 3
收起左侧

单片机电子琴设计中怎么存音乐

[复制链接]
ID:185632 发表于 2017-6-5 15:57 | 显示全部楼层 |阅读模式
五一单片机中电子琴的中音乐的那种音律怎么用代码啊什么表示
回复

使用道具 举报

ID:164602 发表于 2017-6-5 18:12 | 显示全部楼层
这个问题有点复杂。一个个地说吧。
首先是音乐的知识:
第一:音乐与频率的关系——标准A = 440 Hz,8度音的频率为原來音频率的2倍。我们不是搞音乐的,这个就不多说。
第二:音阶与频率的具体关系:
音階      Octave0 Octave1  Octave2  Octave3
Do  C      262      523     1047     2093
    Db      277      554    1109     2217
Re  D       294      587     1175     2349
    Eb      311       622     1245     2489
Mi  E       330       659     1329     2637
Fa   F      349      698     1397     2794
    Gb      370      740     1480     2960
Sol  G      392       784     1568    3136
    Ab      415       831    1661     3322
La  A       440       880     1760     3520
    Bb      466       923    1865      3729
Si   B       494       988      1976     3951
有了这些知识,就可以用单片机控制频率,让蜂鸣器发出音乐了。
怎么编程呢?
给你一个程序:
/*
本实例利用无源蜂鸣器发出音乐声音。
还用到了定时计数器0
*/


#include <reg51.h>
#define uint unsigned int
#define uchar unsigned char


sbit voice=P1^5;//蜂鸣器I/O口


uchar code sound[]={0xff,


/*
软件使用规则:
下面已经定义好了简谱对应的频率数据
节拍数据为:
四分之一拍:0x10
四分之二拍:0x20
四分之三拍:0x30
      一拍:0x40
一又四分之一拍:0x60
      两拍:0x80
      三拍:0xc0


音乐数据是这样的:两个十六进制数据,表达一个音符,它包含信息有:第一个数据为音阶,第二数据为节拍,一定是成对放置。
*/




//此后为音乐乐谱,全部为3拍
0x60,0xc0,//低音阶1,2,3,4,5,6,7
0x55,0xc0,
0x4c,0xc0,
0x48,0xc0,
0x40,0xc0,
0x39,0xc0,
0x33,0xc0,


0x30,0xc0,//中音阶1,2,3,4,5,6,7
0x2b,0xc0,
0x26,0xc0,
0x24,0xc0,
0x20,0xc0,
0x1c,0xc0,
0x19,0xc0,


0x18,0xc0,//高音阶1,2,3,4,5,6,7
0x15,0xc0,
0x13,0xc0,
0x12,0xc0,
0x10,0xc0,
0x0e,0xc0,
0x0d,0xc0,


0x26,0x20,0x2b,0x20,0x26,0x80,0xff,0x20,0x2b,0x20,0x26,0x20,0x26,0x10,//两只蝴蝶
0x2b,0x10,0x30,0x80,0xff,0x40,0x39,0x20,0x30,0x20,0x2b,0x40,0x2b,0x20,
0x26,0x20,0x2b,0x20,0x30,0x20,0x39,0x20,0x39,0x10,0x30,0x10,0x40,0x80,
0x40,0x80,0x26,0x20,0x2b,0x20,0x26,0x80,0xff,0x20,0x2b,0x20,0x26,0x20,
0x26,0x10,0x2b,0x10,0x30,0x80,0xff,0x40,0x39,0x20,0x30,0x20,0x2b,0x40,
0x2b,0x20,0x26,0x20,0x2b,0x20,0x30,0x20,0x39,0x20,0x30,0x20,0x2b,0xc0,
0x26,0x20,0x2b,0x20,0x26,0x80,0xff,0x20,0x2b,0x20,0x26,0x20,0x26,0x10,
0x2b,0x10,0x30,0xc0,0x39,0x20,0x30,0x20,0x2b,0x40,0x2b,0x20,0x26,0x20,
0x2b,0x20,0x30,0x20,0x39,0x20,0x39,0x10,0x30,0x10,0x40,0xc0,0x26,0x20,
0x20,0x20,0x20,0x80,0xff,0x20,0x20,0x20,0x1c,0x20,0x20,0x20,0x26,0xc0,
0x2b,0x20,0x2b,0x20,0x2b,0x60,0x2b,0x20,0x26,0x20,0x2b,0x20,0x30,0x20,
0x39,0x20,0x39,0x20,0x30,0x20,0x30,0x20,0x30,0xc0,0xff,0x40,0xff,0x40,
0xff,0x20,0x20,0x20,0x20,0x20,0x1c,0x20,0x18,0x20,0x19,0x20,0x19,0x20,
0x1c,0x20,0x26,0x20,0x2b,0x20,0x2b,0x20,0x26,0x20,0x26,0x80,0xff,0x20,
0x26,0x20,0x26,0x20,0x20,0x20,0x1c,0x40,0x1c,0x40,0xff,0x20,0x39,0x20,
0x26,0x20,0x2b,0x20,0x2b,0xc0,0x26,0x20,0x20,0x20,0x20,0x20,0x26,0x20,
0x20,0x40,0xff,0x20,0x18,0x40,0x19,0x20,0x1c,0x20,0x1c,0x10,0x19,0x10,
0x26,0x40,0xff,0x20,0x1c,0x20,0x1c,0x20,0x19,0x20,0x1c,0x20,0x20,0x20,
0x26,0x20,0x2b,0x20,0xff,0x20,0x26,0x20,0x2b,0x20,0x26,0x20,0x20,0x80,
0xff,0x20,0x20,0x20,0x20,0x20,0x1c,0x20,0x18,0x20,0x19,0x20,0x19,0x20,
0x1c,0x20,0x26,0x20,0x2b,0x20,0x2b,0x20,0x26,0x20,0x26,0x80,0xff,0x20,
0x26,0x20,0x26,0x20,0x20,0x20,0x1c,0x40,0x1c,0x40,0xff,0x20,0x39,0x20,
0x26,0x20,0x2b,0x20,0x2b,0xc0,0x26,0x20,0x20,0x20,0x20,0x20,0x26,0x20,
0x20,0x40,0xff,0x20,0x18,0x40,0x19,0x20,0x1c,0x20,0x1c,0x10,0x19,0x10,
0x26,0x40,0xff,0x20,0x1c,0x20,0x1c,0x20,0x19,0x20,0x1c,0x20,0x20,0x20,

0x26,0x20,0x2b,0x20,0xff,0x20,0x40,0x40,0x39,0x20,0x30,0xc0,0xff,0xc0,



0xff,0xc0,//休止符


,0x00};


uchar zdjs=0, jp;//jp为节拍变量,


void del(yj);//yj为音阶变量,延时为了乐音高低


void main(void)
{
        uint dpjs=0;//读数据的指针
        uchar yj;
        TMOD=0x01;//定时器0,工作方式1:16位定时器(0~65535),定时器模式,由运行控制位TR0开启
        IE=0x82;//中断允许寄存器设置,等于以下分别的设置:EA=1总中断允许,ET0=1定时器中断0允许;
        TH0=0xd8;//给定时器赋初值,即定时时间的长短:12MHz下10ms
        TL0=0xf0;
        TR0=1;//启动定时器0
        while(1)
        {  
                zdjs=0;//节拍长短的计数器计数变量
                dpjs++; yj=sound[dpjs];
                dpjs++; jp=sound[dpjs];
                while(zdjs!=jp)
                {
                        if(yj!=0xff)
                        {
                                if(yj!=0)
                                {
                                        voice=!voice;
                                        del(yj);
                                }
                                else
                                {
                                        dpjs=0;
                                        break;
                                }
                        }
                        else
                        {
                                voice=1;
                                del(jp);
                        }
                }
        }
}


void time0() interrupt 1
{
        TH0=0xd8;//定时10ms,12M
        TL0=0xf0;
        zdjs++;
}


void del(yj)
{
        uchar yj2=2;
        while(yj!=0)
        {      
                while(yj2!=0)
                {
                        yj2--;
                }
                        yj2=2;
                        yj--;  
        }  

}

好了,电子音乐已经可以通过51单片机进行演奏了。

还可以有其它的演奏办法:
第一:上述程序不是唯一的,只要能控制好蜂鸣器发声音的频率,就可以发出音乐。
第二:还可以通过电子电路的设计,通过双稳态电路(模拟电路)或其它芯片,可以得到发音乐的结果。小孩玩的电子琴,就是这样来的。网上很多资料,这里不多说了。

两只蝴蝶简谱011.jpg
回复

使用道具 举报

ID:77589 发表于 2023-5-15 11:11 | 显示全部楼层
当然用数组存放啊!如果数据太多,外挂Flash啊!
回复

使用道具 举报

ID:1034262 发表于 2023-5-15 16:27 | 显示全部楼层
可以参考MIDI。
或者自己定义,节拍速率,音符、时值。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表