本設(shè)計僅供參考
基于51單片機的7鍵電子琴音樂播放器proteus(仿真+源碼+原理圖)
原理圖:Altium Designer
仿真圖proteus 7.8
程序編譯器:keil 4/keil 5
編程語言:C語言
編號C0036
設(shè)計介紹:
本次設(shè)計首先對單片機設(shè)計簡易電子琴仔細(xì)分析,接著制作硬件電路和編寫軟件的程序,最后進行軟硬件的調(diào)試運行。并且從原理圖,主要芯片,各模塊的原理和各個模塊的程序調(diào)試來闡述。利用單片機產(chǎn)生不同頻率來獲得我們要求的音階,實現(xiàn)高、中、低共21個音符的發(fā)音和顯示和音樂播放時的控制顯示,并且能自動播放程序中編排的音樂。
系統(tǒng)運行穩(wěn)定,其優(yōu)點是硬件電路簡單,軟件功能完善,控制系統(tǒng)可靠,性價比高等,具有一定的使用和參考價值。
設(shè)計思路:
用獨立式鍵盤的7個按鍵分別對應(yīng)相應(yīng)的音符,當(dāng)按下某一個按鍵時,產(chǎn)生一個相應(yīng)音符,操作者按一定的節(jié)奏、規(guī)律進行輸入時,信號經(jīng)過單片機處理,然后經(jīng)音頻放大后經(jīng)揚聲器輸出音頻信號,產(chǎn)生樂曲。本次設(shè)計有一個創(chuàng)新,就是預(yù)先存放一段音樂程序在芯片內(nèi),整個設(shè)計既可以作電子琴用又可以作音樂盒用,且?guī)э@示功能。
仿真圖(提供源文件):
原理圖:
硬件設(shè)計分析
電源的設(shè)計
系統(tǒng)電源使用直流5伏。
由電腦USB接口提供電源。
USB是通用串行總線(Universal Serial Bus)接口的簡稱。它是目前使用比較廣泛的電腦接口之一,主要版本有1.0、1.1和最新的2.0三種版本。根據(jù)USB總線的工業(yè)標(biāo)準(zhǔn),它可以提供額定功率為5V/500mA的電源供USB設(shè)備使用。
單片機最小系統(tǒng)
51單片機是對目前所有兼容intel 8031指令系統(tǒng)的單片機的統(tǒng)稱。該系列單片機的始祖是intel的8031單片機,后來隨著技術(shù)的發(fā)展,成為目前廣泛應(yīng)用的8為單片機之一。單片機是在一塊芯片內(nèi)集成了CPU、RAM、ROM、定時器/計數(shù)器和多功能I/O口等計算機所需要的基本功能部件的大規(guī)模集成電路,又稱為MCU。51系列單片機內(nèi)包含以下幾個部件:
一個8位CPU;一個片內(nèi)振蕩器及時鐘電路;
4KB的ROM程序存儲器;
一個128B的RAM數(shù)據(jù)存儲器;
尋址64KB外部數(shù)據(jù)存儲器和64KB外部程序存儲空間的控制電路;
32條可編程的I/O口線;
兩個16位定時/計數(shù)器;
一個可編程全雙工串行口;
5個中斷源、兩個優(yōu)先級嵌套中斷結(jié)構(gòu)。
顯示系統(tǒng)采用2位數(shù)碼管來顯示,LED顯示屏作為大型顯示設(shè)備的一種,具有亮度高、價格低、壽命長、維護簡便等優(yōu)點。LED數(shù)碼管的結(jié)構(gòu)簡單,分為七段和八段兩種形式,也有共陽和共陰之分。以八段共陽管為例,它有8個發(fā)光二極管(比七段多一個發(fā)光二極管,用來顯示sP,即點),每個發(fā)光二極管的陽極連在一起,如圖(圖3-3)所示。
這樣,一個LED數(shù)碼管就有I根位選線和8根段選線,要想顯示一個數(shù)值,就要分別對它們的高低電平來加以控制。為方便起見,本文主要討論共陰八段LED數(shù)碼顯示管,其他類形的顯示管與其類似。
LED 燈的顯示原理:通過同名管腳上所加電平的高低來控制發(fā)光二極管是否點亮而顯示不同的字形,如 H,G,F,E,D,C,B,A全亮顯示為8,采用共陰極連接驅(qū)動代碼,代碼表如下表(表2-2-2)所示。
程序:
#include<reg51.h>
#include<intrins.h>
typedef unsigned int uint;
typedef unsigned char uchar;
sbit SDA1=P0^2;//串行數(shù)據(jù)輸入,對應(yīng)595的14腳SER
sbit SCL1=P0^1;//移位寄存器時鐘輸入,對應(yīng)595的11腳SCK
sbit SCL2=P0^0;//存儲寄存器時鐘輸入,對應(yīng)595的12腳RCK
sbit W1=P0^3;
sbit W2=P0^4;
sbit k1=P1^0;
sbit k2=P1^1;
sbit k3=P1^2;
sbit k4=P1^3;
sbit k5=P1^4;
sbit k6=P1^5;
sbit k7=P1^6;
sbit D1=P2^6;//播放音樂模式
sbit D2=P2^7;//彈奏模式
sbit k8=P3^2;//功能切換鍵
sbit k9=P3^3;//低音
sbit k10=P3^4;//中音
sbit k11=P3^5;//高音
sbit beep=P2^2;//蜂鳴器接口
uchar code table1[]={
0x3F,/*0*/
0x06,/*1*/
0x5B,/*2*/
0x4F,/*3*/
0x66,/*4*/
0x6D,/*5*/
0x7D,/*6*/
0x07,/*7*/
0x7F,/*8*/
0x6F,/*9*/
0x37,/*N*///中音
0x38,/*L*///低音
0x76,/*H*///高音
0x79 /*E*/
};//共陰極數(shù)碼管
uchar code table2[]={
0xFC,0xFC,0xFD,0xFD,0xFD,0xFD,0xFE,//中音
0xF9,0xF9,0xFA,0xFA,0xFB,0xFB,0xFC,//低音的高8位
0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFF,
};//音階頻率表 低八位
uchar code table3[]={
0x8E,0xED,0x44,0x6B,0xB4,0xF4,0x2D,//中音
0x21,0xDB,0x87,0xD7,0x68,0xE8,0x5B,//低音的低8位
0x47,0x77,0xA2,0xB6,0xDA,0xFA,0x16,
};
uchar code table4[]={
1,2,3,1,
1,2,3,1,
3,4,5,
3,4,5,
5,6,5,4,3,1,
5,6,5,4,3,1,
1,12/*低音5*/,1,
1,12,1
};
uchar code table5[]={
4,4,4,4,
4,4,4,4,
4,4,8,
4,4,8,
2,1,2,1,4,4,
2,1,2,1,4,4,
4,4,6,
4,4,6
};
uchar i;
uchar key,aa=0;
uchar bb,cc;
bit flag=0;
//延時子函數(shù)
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=340;y>0;y--);
}
void in(uchar Data)
{
uchar i;
for(i=0;i<8;i++) //循環(huán)8次,剛好移完8位
{
Data<<=1;
SCL1=CY;
SDA1=1; //先將移位寄存器控制引腳置為低
_nop_();
_nop_();
SDA1=0;
}
}
void out()
{
SCL2=0; //先將存儲寄存器引腳置為低
_nop_();
SCL2=1; //再置為高,產(chǎn)生移位時鐘上升沿,上升沿時移位寄存器的數(shù)據(jù)進入數(shù)據(jù)存儲寄存器,更新顯示數(shù)據(jù)。
_nop_();
SCL2=0;
}
//初始化子函數(shù)
void init()
{
beep=0;
D1=1;
D2=0;
EA=1;//開總中斷
TCON=0x01;//外部中斷0設(shè)置為邊沿觸發(fā)
EX0=1;//開外部中斷0
ET0=1;
ET1=1;
TMOD=0x11;//定時器0,1工作在定時狀態(tài),均為方式1
}
//數(shù)碼管顯示子函數(shù)
void display1()
{
in(table1[aa]); //再傳段碼
out();
W1=0;;
delay(1); //延遲時間2ms以內(nèi)
W1=1;
in(table1[cc+1]); //再傳段碼
out();
W2=0;
delay(1); //延遲時間2ms以內(nèi)
W2=1;
}
//高低音選擇子函數(shù)
void yinjie()
{
if(k10==0)
{
delay(5);
if(k10==0)
{
aa=10;
bb=0;//返回10為seg[10]顯示C
}
}
if(k9==0)
{
delay(5);
if(k9==0)
{
aa=11;
bb=1;//返回11為seg[11]顯示L
}
}
if(k11==0)
{
delay(5);
if(k11==0)
{
aa=12;
bb=2;//返回12為seg[12]顯示H
}
}
if(aa==0)
{
aa=13;
}
}
//播放音樂子函數(shù)
void display_music()
{
TH0=table2[table4[i]-1];
TL0=table3[table4[i]-1];
while(flag==0)
{
if(i<32)
{
TR0=1;
delay(57*table5[i]);
i++;
}
if(i==32)
{
i=0;
}
}
}
//演奏模式子函數(shù)
void display_play()
{
TR0=0;
TR1=0;
yinjie();
in(table1[aa]); //再傳段碼
out();
W1=0;;
delay(1); //延遲時間2ms以內(nèi)
W1=1;
if(aa!=13&&flag==1)
{
if(k1==0)
{
TH1=table2[7*bb+cc];
TL1=table3[7*bb+cc];
TR1=1;
while(k1==0)
{
cc=0;
display1();
}
}
if(k2==0)
{
TH1=table2[7*bb+cc];
TL1=table3[7*bb+cc];
TR1=1;
while(k2==0)
{
cc=1;
display1();
}
}
if(k3==0)
{
TH1=table2[7*bb+cc];
TL1=table3[7*bb+cc];
TR1=1;
while(k3==0)
{
cc=2;
display1();
}
}
if(k4==0)
{
TH1=table2[7*bb+cc];
TL1=table3[7*bb+cc];
TR1=1;
while(k4==0)
{
cc=3;
display1();
}
}
if(k5==0)
{
TH1=table2[7*bb+cc];
TL1=table3[7*bb+cc];
TR1=1;
while(k5==0)
{
cc=4;
display1();
}
}
if(k6==0)
{
TH1=table2[7*bb+cc];
TL1=table3[7*bb+cc];
TR1=1;
while(k6==0)
{
cc=5;
display1();
}
}
if(k7==0)
{
TH1=table2[7*bb+cc];
TL1=table3[7*bb+cc];
TR1=1;
while(k7==0)
{
cc=6;
display1();
}
}
}
}
//主函數(shù)
void main()
{
init();
while(1)
{
if(flag==0)
display_music();
else
display_play();
}
}
//外部0中斷子函數(shù)
void wb0() interrupt 0
{
if(k8==0)
{
delay(5);
while(k8==0);
flag=~flag;
D1=~D1;
D2=~D2;
}
}