包含Proteus仿真,原理图,PCB及源程序
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
8音键电子琴介绍:
该设计采用AT89C52(AT89C52数据手册)单片机作为主控制芯片,外接灯光闪烁功能和8音调键。共有8个音节和4个功能按键。可播放内置乐曲,可弹奏录音,采用24C02(24C02数据手册)芯片作为EEPROM存储,掉电不掉内容,LM386(LM386数据手册)功放模块外接扬声器。
具体功能介绍:
8个弹奏键,具有很强的娱乐性。
独创--弹奏录音功能 能录音,能回放,听起来更惬意。
内置多首音乐。
4个功能按键设计,PLAY(播放)NEXT(下一首),PRE(上一首),STOP(停止)按键。
5V电源转接PIN,供电稳定,方便实用。
采用LM386功放和专用音乐喇叭,声音更柔和动听,不再是蜂鸣器的刺耳啸叫。
Altium Designer画的原理图和PCB图如下:(51hei附件中可下载工程文件):
元件清单:
主机元件清单
名称 参数 数量
电阻 470,1K、10K、10欧 若干
电位器 10K 1
发光二极管 9
电源接口 1
电解电容 10uf 1
电解电容 250uf 1
独石电容 104 1
瓷片电容 30pf 2
按键 13
晶振 12.00M 1
排针 若干
AT89S52单片机 1
AT24C08 1
扬声器 0.5W 8欧 1
LM386 1
单片机源程序如下:
- /**************************************************************
- 程序名称:模拟电子琴
- **************************************************************/
- #include<reg52.h> //定义头文件
- #define uchar unsigned char //宏定义
- #define led P0 //定义LED等位P0口
- #define sw_port P1 //中间变量。。。使按键和led对应
- sbit buzzer=P2^7; //扬声器管脚
- sbit key1=P3^2; //播放音乐与弹奏歌曲转换
- sbit key3=P3^4; //掉电存储按键
- sbit key4=P3^5; //播放掉电存储的歌曲
- sbit keybofang=P3^3; //播放刚才弹奏的歌曲
- sbit key7=P3^0; //音调键。。。 和 歌曲键
- sbit key8=P3^1; //音调键。。。 和 歌曲键
- sbit key6=P1^7;
- sbit key5=P1^6;
- sbit sda=P1^1; //24c02数据线
- sbit scl=P1^0; //24c02时钟线
- uchar keyd,i,keys,b; //定义变量
- uchar tone_H; //定义变量
- uchar tone_L; //定义变量
- void beat_125(unsigned char); //声明函数
- uchar code beat1[]={16,8,8,8,8,4,4,16,8,4,4,8,4,4,4, //歌曲1节拍
- 4,4,4,16,16,8,8,4,4,12,8,16,16,8,4,4,4,4,16};
- uchar code song1[]={6,5,3,5,7,6,5,6,3,5,6,5,3, //歌曲1简谱
- 2,1,6,5,3,2,2,3,5,5,6,3,2,1,5,3,2,1,6,1,1,15};
- uchar code beat2[]={7,7,7, 7,8,9, 1,2,3, 6,2,4, 4,4,4, 12, //歌曲二节拍
- 8,2,2, 4,4,4, 8,2,2, 4,4,4, 2,2,4,4, 12,};
- uchar code song2[]={1,2,8, 8,5,1, 3,3,3, 5,4,3, //歌曲二简谱
- 5,4,3, 2, 2,1,0, 1,2,3, 4,3,2, 3,4,5, 5,4,3, 2,1,15};
- uchar code beat4[]={4,4,4, 6,2,4, 4,4,4, 6,2,4, 4,4,4, 12,
- 8,2,2, 4,4,4, 8,2,2, 4,4,4, 2,2,4,4, 12,};
- uchar code song4[]={1,1,1, 3,2,1, 3,3,3, 5,4,3,
- 5,4,3, 2, 2,1,0, 1,2,3, 4,3,2, 3,4,5, 5,4,3, 2,1, 15};
- uchar code tone[]={115,102,91,86,77,68,61,57}; //歌曲音调
- unsigned int code tone1[]={1012,956,852,759,716,638,568,506,478,426,379,531,10}; //歌曲音调
- uchar song3[43]; //定义空数组
- void play(uchar*,uchar*); //演奏歌曲函数
- void delay8um(uchar); //第一8um延时函数
- void sound(uchar); //弹奏发声函数
- /*******************************************
- 函数功能:节拍的延时的基本单位,用于24c08简单延时
- ******************************************/
- void delay() //简单延时函数
- {;;}
- /*******************************************
- 函数功能:节拍的延时的基本单位,延时1ms
- ******************************************/
- void delay1ms(uchar x) //1um延时函数
- {
- uchar j;
- while(x--)
- for(j=120;j>0;j--);
- }
- /**************************************************************
- 函数功能:24c02驱动程序 用IIC总线进行传输
- **************************************************************/
- void init_c02() //24c02初始化
- {
- sda=1;
- delay();
- scl=1;
- delay();
- }
- void start_c02() //24c02的启动信号
- {
- scl=1;
- delay();
- sda=1;
- delay();
- sda=0;
- delay();
- }
- void stop_c02() //24c02停止信号
- {
- sda=0;
- delay();
- scl=1;
- delay();
- sda=1;
- delay();
- }
- void response_c02() //24c02的应答信号
- {
- uchar i;
- scl=1;
- delay();
- while((sda==1)&&(i<250))i++;
- scl=0;
- delay();
- }
- void write_c02byte(uchar date) //对24c02写一个字节
- {
- uchar i,temp;
- temp=date;
- for(i=0;i<8;i++)
- {
- temp=temp<<1;
- scl=0;
- delay();
- sda=CY;
- delay();
- scl=1;
- delay();
- }
- scl=0;
- delay();
- sda=1;
- delay();
- }
- uchar read_c02byte() //对24c02读一个字节
- {
- uchar i,k;
- scl=0;
- delay();
- sda=1;
- delay();
- for(i=0;i<8;i++)
- {
- scl=1;
- delay();
- k=(k<<1)|sda;
- scl=0;
- delay();
- }
- return k;
- }
- void write_addc02(uchar address,uchar date) //对24c02写一个数据
- {
- start_c02();
- write_c02byte(0xa0);
- response_c02();
- write_c02byte(address);
- response_c02();
- write_c02byte(date);
- response_c02();
- stop_c02();
- }
- uchar read_addc02(uchar address) //从24c02读一个数据
- {
- uchar date;
- start_c02();
- write_c02byte(0xa0);
- response_c02();
- write_c02byte(address);
- response_c02();
- start_c02();
- write_c02byte(0xa1);
- response_c02();
- date=read_c02byte();
- // response_c02;
- stop_c02();
- return date;
- }
- /**************************************************************
- 函数功能:主函数。。。。。。。。。。。。
- **************************************************************/
- void main() //主函数
- {
- uchar yd,temp,jj,tt; //定义变量
- uchar t1,i; //定义变量
- t1=0; //初始化 t1
- yd=0; //初始化t2
- buzzer=1; //初始化蜂鸣器
- EA=1; //打开定时总中断
- TMOD=0x01; //设置定时器模式 定时器0工作在方式1
- ET0=1; //打开定时器0中断
- while(1) //主循环
- {
- led=0x3c;
- sw_port=0xff;
- keys=~sw_port; //将led与按键结合起来
- switch(keys) //进入键盘选择
- {
- case 0x04:sound(0);temp=1;yd=0;break; //如果键盘1被按下发音do,同时设置标志temp,将数字计入yd
- case 0x08:sound(1);temp=1;yd=1;break; //如果键盘2被按下发音ruai,同时设置标志temp,将数字计入yd
- case 0x10:sound(2);temp=1;yd=2;break; //如果键盘3被按下发音mi,同时设置标志temp,将数字计入yd
- case 0x20:sound(3);temp=1;yd=3;break; //如果键盘4被按下发音fa,同时设置标志temp,将数字计入yd
- }
- if(key5==0) //如果键盘5被按下发音la,同时设置标志temp,将数字计入yd
- {
- while(!key5) // 松手检测
- sound(4);
- temp=1;yd=4;
- }
- if(key6==0) //如果键盘6被按下发音xi,同时设置标志temp,将数字计入yd
- {
- while(!key6) // 松手检测
- sound(5);
- temp=1;yd=5;
- }
- if(key7==0) //如果键盘7被按下发音xi,同时设置标志temp,将数字计入yd
- {
- while(!key7) // 松手检测
- sound(6);
- temp=1;yd=6;
- }
- if(key8==0) //如果键盘8被按下发音高音do,同时设置标志temp,将数字计入yd
- {
- while(!key8) //松手检测
- sound(7); //播放高音do。。
- temp=1;yd=7;
- }
- if(temp==1) //标志位,如果标志位为1,则说明有按键被按下
- {
-
- temp=0; //将标识位归零
- song3[t1++]=yd; //将数据存入song3[]数组
- }
- if(key3==0) //将数据存入24c02 ,掉电存储按键
- {
- delay1ms(10);
- if(key3==0) //检测是否key3被按下
- {
- P0=0; //如果被按下,将led打开
- while(!key3); //松手检测
- song3[t1++]=30;
- init_c02(); //初始化24c02
- for(i=0;i<40;) //进入循环
- {
- write_addc02(i,song3[i++]); //将数据依次写入24c02
- delay1ms(10); //延时
- }
- P0=1; //led关闭
- }
- }
- if(key4==0) //读取24c02中的数据,掉电播放
- {
- delay1ms(10);
- if(key4==0)
- { //检测是否有键被按下
-
- while(!key4); //松手检测
- init_c02(); //初始化
- P0=0; //将led打开
- tt=1; //将tt初值设为0
- while(read_addc02(tt)!=30) //进入while循环
- {
- jj=read_addc02(tt++);
- tone_H=(65536-tone1[jj])/256; //设定初值
- tone_L=(65536-tone1[jj])%256; //设定初值
- TH0=tone_H; //赋值TH0高八位
- TL0=tone_L; //赋值TL0低八位
- TR0=1; //打开定时器
- beat_125(3); //延时
- TR0=0;
- beat_125(4); //关闭定时器
- }
- P0=1; //关闭led
- }
- }
- if(keybofang==0)
- {
- while(!keybofang); //检测回放键是否被按下
- song3[t1++]=30;
- // t1=0;
- while(song3[i]!=30) //进入while循环。
- {
- tone_H=(65536-tone1[song3[i]])/256;
- tone_L=(65536-tone1[song3[i]])%256;
- TH0=tone_H;
- TL0=tone_L;
- TR0=1; //开启定时器
- beat_125(3);
- TR0=0; //关闭定时器
- i++;
- beat_125(4); //将i值加一
- }
- }
- if(key1==0)
- {
- delay1ms(10);
- if(key1==0) //检测key1是否被按下
- {
- while(!key1);
- P0=0; //关闭led
- while(key1) //进入循环
- {
- if(key7==0) //检测key7是否被按下
- {
- delay1ms(10);
- if(key7==0)
- {
- P0=0xaa; //设置led灯亮个数
- while(!key7); //等待释放
- play(song1,beat1); //演奏歌曲1
- P0=0xff; //关闭led
- }
- }
- if(key8==0) //检测是否key8键被按下
- {
- delay1ms(10);
- if(key8==0)
- {
- P0=0xaa; //设置led灯亮
- while(!key8); //松手检测
- play(song2,beat2); //播放歌曲2
- P0=0xff; //关闭led
- }
- }
- if(key6==0) //检测是否key6键被按下
- {
- delay1ms(10);
- if(key6==0)
- {
- P0=0xaa; //设置led灯亮
- while(!key6); //松手检测
- play(song4,beat4); //播放歌曲4
- P0=0xff; //关闭led
- }
- }
- }
- while(!key1); //检测key1是否被按下
- P0=1; //如果被按下。退出该函数。。并关闭led
-
- }
- }
-
- }
- }
- /**************************************************************
- 函数功能:从数组中播放歌曲
- **************************************************************/
- void play(uchar*song,uchar*beat) //播放歌曲函数
- {
- i=0; //设置初始值
- while(song[i]!=15) // 进入循环函数
- {
- tone_H=(65536-tone1[song[i]])/256; //定义初值
- tone_L=(65536-tone1[song[i]])%256; //定义初值
- TH0=tone_H; //赋值
- TL0=tone_L; //赋值
- TR0=1; //打开定时器0
- beat_125(beat[i]); //读取节拍函数
- i++; //自加
- TR0=0; //关闭led
- }
- }
- /**************************************************************
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码 附件内容包括:
整个电路设计原理图和PCB源文件,用AD软件打开;
源程序;
仿真电路,用proteus软件打开;
BOM表;
我这个目前目前问题还很多,研究了几天,也没有解决,仿真也没有效果,求大神帮帮忙看看我这电路和程序哪里错了?
错误文件:
基于51单片机8音键电子琴DIY制作(完整设计项目开源).zip
(114.57 KB, 下载次数: 479)
下面这位大神制作的是可以运行的,大家能参考这个帮我修改一下吗?
成功版:http://www.51hei.com/bbs/dpj-148020-1.html
|