❶ 單片機簡易電子琴程序
22. 電子琴
1. 實驗任務
(1. 由4X4組成16個按鈕矩陣,設計成16個音。
(2. 可隨意彈奏想要表達的音樂。
2. 電路原理圖
圖4.22.1
3. 系統板硬體連線
(1. 把「單片機系統」區域中的P1.0埠用導線連接到「音頻放大模塊」區域中的SPK IN埠上;
(2. 把「單片機系統「區域中的P3.0-P3.7埠用8芯排線連接到「4X4行列式鍵盤」區域中的C1-C4 R1-R4埠上;
4. 相關程序內容
(1. 4X4行列式鍵盤識別;
(2. 音樂產生的方法;
一首音樂是許多不同的音階組成的,而每個音階對應著不同的頻率,這樣我們就可以利用不同的頻率的組合,即可構成我們所想要的音樂了,當然對於單片機來產生不同的頻率非常方便,我們可以利用單片機的定時/計數器T0來產生這樣方波頻率信號,因此,我們只要把一首歌曲的音階對應頻率關系弄正確即可。現在以單片機12MHZ晶振為例,例出高中低音符與單片機計數T0相關的計數值如下表所示
音符 頻率(HZ) 簡譜碼(T值) 音符 頻率(HZ) 簡譜碼(T值)
低1 DO 262 63628 # 4 FA# 740 64860
#1 DO# 277 63731 中 5 SO 784 64898
低2 RE 294 63835 # 5 SO# 831 64934
#2 RE# 311 63928 中 6 LA 880 64968
低 3 M 330 64021 # 6 932 64994
低 4 FA 349 64103 中 7 SI 988 65030
# 4 FA# 370 64185 高 1 DO 1046 65058
低 5 SO 392 64260 # 1 DO# 1109 65085
# 5 SO# 415 64331 高 2 RE 1175 65110
低 6 LA 440 64400 # 2 RE# 1245 65134
# 6 466 64463 高 3 M 1318 65157
低 7 SI 494 64524 高 4 FA 1397 65178
中 1 DO 523 64580 # 4 FA# 1480 65198
# 1 DO# 554 64633 高 5 SO 1568 65217
中 2 RE 587 64684 # 5 SO# 1661 65235
# 2 RE# 622 64732 高 6 LA 1760 65252
中 3 M 659 64777 # 6 1865 65268
中 4 FA 698 64820 高 7 SI 1967 65283
下面我們要為這個音符建立一個表格,有助於單片機通過查表的方式來獲得相應的數據
低音0-19之間,中音在20-39之間,高音在40-59之間
TABLE: DW 0,63628,63835,64021,64103,64260,64400,64524,0,0
DW 0,63731,63928,0,64185,64331,64463,0,0,0
DW 0,64580,64684,64777,64820,64898,64968,65030,0,0
DW 0,64633,64732,0,64860,64934,64994,0,0,0
DW 0,65058,65110,65157,65178,65217,65252,65283,0,0
DW 0,65085,65134,0,65198,65235,65268,0,0,0
DW 0
2、音樂的音拍,一個節拍為單位(C調)
曲調值 DELAY 曲調值 DELAY
調4/4 125ms 調4/4 62ms
調3/4 187ms 調3/4 94ms
調2/4 250ms 調2/4 125ms
對於不同的曲調我們也可以用單片機的另外一個定時/計數器來完成。
下面就用AT89S51單片機產生一首「生日快樂」歌曲來說明單片機如何產生的。
在這個程序中用到了兩個定時/計數器來完成的。其中T0用來產生音符頻率,T1用來產生音拍。
5. 程序框圖
貼不了.
7. C語言源程序
#include <AT89X51.H>
unsigned char code table[]={0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
unsigned char temp;
unsigned char key;
unsigned char i,j;
unsigned char STH0;
unsigned char STL0;
unsigned int code tab[]={64021,64103,64260,64400,
64524,64580,64684,64777,
64820,64898,64968,65030,
65058,65110,65157,65178};
void main(void)
{
TMOD=0x01;
ET0=1;
EA=1;
while(1)
{
P3=0xff;
P3_4=0;
temp=P3;
temp=temp & 0x0f;
if (temp!=0x0f)
{
for(i=50;i>0;i--)
for(j=200;j>0;j--);
temp=P3;
temp=temp & 0x0f;
if (temp!=0x0f)
{
temp=P3;
temp=temp & 0x0f;
switch(temp)
{
case 0x0e:
key=0;
break;
case 0x0d:
key=1;
break;
case 0x0b:
key=2;
break;
case 0x07:
key=3;
break;
}
temp=P3;
P1_0=~P1_0;
P0=table[key];
STH0=tab[key]/256;
STL0=tab[key]%256;
TR0=1;
temp=temp & 0x0f;
while(temp!=0x0f)
{
temp=P3;
temp=temp & 0x0f;
}
TR0=0;
}
}
P3=0xff;
P3_5=0;
temp=P3;
temp=temp & 0x0f;
if (temp!=0x0f)
{
for(i=50;i>0;i--)
for(j=200;j>0;j--);
temp=P3;
temp=temp & 0x0f;
if (temp!=0x0f)
{
temp=P3;
temp=temp & 0x0f;
switch(temp)
{
case 0x0e:
key=4;
break;
case 0x0d:
key=5;
break;
case 0x0b:
key=6;
break;
case 0x07:
key=7;
break;
}
temp=P3;
P1_0=~P1_0;
P0=table[key];
STH0=tab[key]/256;
STL0=tab[key]%256;
TR0=1;
temp=temp & 0x0f;
while(temp!=0x0f)
{
temp=P3;
temp=temp & 0x0f;
}
TR0=0;
}
}
P3=0xff;
P3_6=0;
temp=P3;
temp=temp & 0x0f;
if (temp!=0x0f)
{
for(i=50;i>0;i--)
for(j=200;j>0;j--);
temp=P3;
temp=temp & 0x0f;
if (temp!=0x0f)
{
temp=P3;
temp=temp & 0x0f;
switch(temp)
{
case 0x0e:
key=8;
break;
case 0x0d:
key=9;
break;
case 0x0b:
key=10;
break;
case 0x07:
key=11;
break;
}
temp=P3;
P1_0=~P1_0;
P0=table[key];
STH0=tab[key]/256;
STL0=tab[key]%256;
TR0=1;
temp=temp & 0x0f;
while(temp!=0x0f)
{
temp=P3;
temp=temp & 0x0f;
}
TR0=0;
}
}
P3=0xff;
P3_7=0;
temp=P3;
temp=temp & 0x0f;
if (temp!=0x0f)
{
for(i=50;i>0;i--)
for(j=200;j>0;j--);
temp=P3;
temp=temp & 0x0f;
if (temp!=0x0f)
{
temp=P3;
temp=temp & 0x0f;
switch(temp)
{
case 0x0e:
key=12;
break;
case 0x0d:
key=13;
break;
case 0x0b:
key=14;
break;
case 0x07:
key=15;
break;
}
temp=P3;
P1_0=~P1_0;
P0=table[key];
STH0=tab[key]/256;
STL0=tab[key]%256;
TR0=1;
temp=temp & 0x0f;
while(temp!=0x0f)
{
temp=P3;
temp=temp & 0x0f;
}
TR0=0;
}
}
}
}
void t0(void) interrupt 1 using 0
{
TH0=STH0;
TL0=STL0;
P1_0=~P1_0;
}
根據自己的情況稍微改改就好了
❷ 單片機簡易8鍵電子琴程序
#include<AT89X51.H>unsigned char table[]={0x3f,0x60,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};unsigned char temp;unsigned char key;unsigned char i,j;unsigned char STH0;unsigned char STL0;unsigned int code tab[]={64021,64103,64260,64400,64524,64580,64684,64777,64820,64898,64968,65030,65058,65110,65157,65178};
void main(void){ TMOD=0x01; ET0=1; EA=1; while(1) { P3=0xff; P3_4=0; temp=P3; temp=temp&0x0f; if(temp!=0x0f) { for(i=50;i>0;i--) for(j=200;j>0;j--); temp=P3; temp=temp&0x0f; if(temp!=0x0f) { temp=P3; temp=temp&0x0f; switch(temp) { case 0x0e: key=0; break; case 0x0d: key=1; break; case 0x0b: key=2; break; case 0x07: key=3; break; } temp=P3; P1_0=~P1_0; P0=table[key]; STH0=tab[key]/256; STL0=tab[key]%256; TR0=1; temp=temp&0x0f; while(temp!=0x0f) { temp=P3; temp=temp&0x0f; } TR0=0; } } P3=0xff; P3_5=0; temp=P3; temp=temp&0x0f; if(temp!=0x0f) { for(i=50;i>0;i--) for(j=200;j>0;j--) temp=P3; temp=temp&0x0f; if(temp!=0x0f) { temp=P3; temp=temp&0x0f; switch(temp) { case 0x0e: key=4; break; case 0x0d: key=5; break; case 0x0b: key=6; break; case 0x07: key=7; break; } temp=P3; P1_0=~P1_0; P0=table[key]; STH0=tab[key]/256; STL0=tab[key]%256; TR0=1; temp=temp&0x0f; while(temp!=0x0f) { temp=P3; temp=temp&0x0f; } TR0=0; } } P3=0xff; P3_6=0; temp=P3; temp=temp&0x0f; if(temp!=0x0f) { for(i=50;i>0;i--) for(j=200;j>0;j--); temp=P3; temp=temp&0x0f; if(temp!=0x0f) { temp=P3; temp=temp&0x0f; switch(temp) { case 0x0e: key=8; break; case 0x0d: key=9; break; case 0x0b: key=10; break; case 0x07: key=11; break; } temp=P3; P1_0=~P1_0; P0=table[key]; STH0=tab[key]/256; STL0=tab[key]%256; TR0=1; temp=temp&0x0f; while(temp!=0x0f) { temp=P3; temp=temp&0x0f; } TR0=0; } } P3=0xff; P3_7=0; temp=P3; temp=temp&0x0f; if(temp!=0x0f) { for(i=50;i>0;i--) for(j=200;j>0;j--); temp=P3; temp=temp&0x0f; if(temp!=0x0f) { temp=P3; temp=temp&0x0f; switch(temp) { case 0x0e: key=12; break; case 0x0d: key=13; break; case 0x0b: key=14; break; case 0x07: key=15; break; } temp=P3; P1_0=~P1_0; P0=table[key]; STH0=tab[key]/256; STL0=tab[key]%256; TR0=1; temp=temp&0x0f; while(temp!=0x0f) { temp=P3; temp=temp&0x0f; } TR0=0; } } }}
void t0(void) interrupt 1 using 0{ TH0=STH0; TL0=STL0; P1_0=~P1_0;}
❸ 單片機電子琴的工作原理
眾所周知,聲音是周圍空氣的震動,音調取決於震動的頻率,頻率越高音調越高。
電子琴按下不同的琴鍵就會發出不同音調的聲音,其實就是產生不同頻率的震動。
單片機電子琴說白了就是利用單片機產生不同頻率的電壓波形,推動揚聲器或蜂鳴器來發出不同音調的聲音。
假設電子琴有八個音階,就對應8個不同的頻率,頻率越高音調就越高。單片機很容易輸出方波信號,那麼只要讓它產生不同頻率的方波就可以了,然後用這個方波信號驅動揚聲器就可以了。單片機的按鍵可以模擬琴鍵,按下不同的按鍵就對應不同的頻率的方波,就能發出不同頻率的聲音了。
❹ 用單片機做電子琴,復音(合音)怎麼實現
解析MIDI電子琴的設計用單片機是如何實現的
摘要:用單片機控制通用MIDI音源模塊製作製作出的電子琴,結構簡單,可靠性高,並且價格低廉,具有實用的價值。這種電子琴能夠支持單音和復音彈奏,如果與高品質的音源晶元連接,音質更可與高檔電子琴相媲美。我們在實驗過程中,也曾採用手機中通用的音樂晶元構成音源模塊,效果不錯,價格更低廉,如韓國產的QS6400 等,這些晶元的驅動要復雜一些,需要對晶元進行初始化設置,詳細內容可參看國防工業出版社出版的《MIDI原理與開發應用》一書中的相關章節。
關鍵字:電子琴,單片機,音源板,MD2064
1、電子琴的硬體設計方案
本電子琴包含48個按鍵鍵盤,即具有4個8度的音域,單片機AT89C51通過對所彈按鍵的識別,產生相應的MIDI消息。它支持單音彈奏和最多16個復音彈奏。電子琴結構示意圖和電路原理圖分別如圖1和圖2所示。AT89C51作為主控晶元,它使得鍵盤矩陣模塊、通道和音色選擇以及串口發送等各功能模塊協調工作。48按鍵行列式鍵盤矩陣構成MIDI電子琴的鍵盤掃描輸入端,由於89C51的P0口內部沒有上拉電阻,故這里採用電阻R14——R21將列線拉至高電平,與六條行線組合完成48個琴鍵的掃描識別,在圖1中,單片機與鍵盤矩陣間的雙箭頭線表示單片機在掃描鍵盤矩陣時,P0口和P2口分別作為輸入/輸出口使用。人機介面電路則利用了單片機P1口的大部分口線,並通過或門向INT0發出中斷請求,該部分電路主要完成MIDI電子琴的通道設置和音色選擇等人機交互功能。鍵盤的彈奏信息以及通道、音色信息經CPU處理後,由串口將標準的MIDI數據發送給MIDI音源及放大器,推動揚聲器發聲。
圖1:MIDI電子琴結構示意圖
圖2:MIDI電子琴電路圖
音源模塊採用MD2064 套板,如圖3所示。它是一種模塊化的MIDI音源產品,由得理電子公司開發,具有標准MIDI介面,該板能接受標准GM MIDI命令進行音樂播放,自帶3D, REVERB, CHORUS等效果處理。由於該套板的MIDI 介面採用了光耦合器,電流驅動,故設計了由Q1、Q2等器件組成的驅動電路,使單片機串口數據得以正常傳輸。在模塊的耳機輸出端取得信號後,經小功率放大即可推動揚聲器發聲。
2、電子琴的軟體設計特點
該電子琴軟體採用模塊化設計方法,程序也較簡單。軟體中各功能模塊都由相應的子程序完成,主要包含通道選擇模塊,音色選擇模塊,48按鍵鍵盤掃描模塊,串口發送模塊等,其中為了及時完成用戶命令,音色選擇模塊採用了中斷服務子程序,可以在演奏中快速響應使用者的請求。
主程序在完成串口初始化、相關變數的初始化以及設置通道後,即進入鍵盤掃描、發送音符消息流程,為了使按鍵識別准確可靠,還設置了兩個緩沖區BUFF1和BUFF2保存鍵盤掃描值。主程序流程圖如圖3。
圖3:MIDI電子琴程序的流程圖
以下是部分功能模塊的程序設計介紹。
2.1 音色選擇模塊的設計
該模塊的功能是使MIDI電子琴能按要求快速改變音色,所以採用了中斷服務子程序。當某個音色選擇按鍵壓下時,通過或門向單片機的INT0發出中斷請求,CPU響應後進入該中斷服務子程序。MIDI技術規范規定,標准MIDI含有128種音色,它們的編號范圍是0~127,為了能夠快速找到所需音色,硬體中設置3個按鍵,其中2個用於音色編號的單步增加和減小,每次增加或減小1個音色編號,另外一個鍵用於音色快進,當快進鍵有效時,每次增加8個音色編號,選擇增加8個音色的原因是:標准MIDI的128種音色是按每8個音色一組編排的,共包含16個樂器組。電子琴開機時默認的音色編號是0,即大鋼琴音色。
單片機的P1.2口線連接著音色增加按鍵,P1.3則連接音色減小按鍵,P1.4連接音色快進鍵。低電平時按鍵有效,這三個按鍵通過與門連接外部中斷INT0,以便實時響應音色設置。該外部中斷0的中斷服務子程序流程圖見圖4,(圖中省去了按鍵延時去抖動部分):
圖4:音色改變子程序流程圖
在該子程序中,變數TAMBER中存放當前音色,其值可在0~127間循環,當TAMBER是最大值127時,加1後又變為0;而當TAMBER為0時,減1則變為127;在邊界范圍加8取模後,剛好為其對應的音色值。
2.2 串口發送模塊
串口發送模塊主要用於發送產生的MIDI消息,串口採用的模式1,發送的波特率是31.25KBPS。串口通過驅動電路連接MIDI音源,發送MIDI消息。通道號存放在變數CHANNEL中,通過與90H相與,所得值就是當前所設置的通道號。
2.3 鍵盤掃描模塊
本電子琴提供了48個MIDI按鍵,即4個8度音的音域范圍,當按下單個鍵時,產生一條MIDI消息,當按下多個鍵值時產生對應鍵值的多條MIDI音符開消息,當某個鍵值被釋放時,發送對應的音符關消息。這些MIDI消息通過串口發送給MIDI音源,產生MIDI音樂。音樂的時值由按鍵的時間長度控制,當按鍵被釋放,實時產生MIDI消息,關閉被釋放的鍵值音。
由P0口和P2口的P2.0~P2.5構成行列式鍵盤,也可繼續擴展鍵盤,例如改為常用的49鍵或64鍵。因為支持復音按鍵,鍵盤掃描程序必須掃描到行列式鍵盤的每個鍵值,掃描所得的鍵值存放在緩沖區BUFF1或BUFF2中。鍵盤掃描程序獲得的鍵盤編號范圍是0~47,還需將這個鍵盤編號值轉換為MIDI設備能夠識別的鋼琴鍵盤編號,這個功能由一個子程序來完成,限於篇幅本文不再詳述。鍵盤掃描子程序流程如圖5。
圖5:鍵盤掃描子程序
❺ 單片機簡單的電子琴程序(C語言的),需要用4*4按鍵控制,簡單點就行,不需要有音樂
#include<AT89X51.H>
unsignedchartemp;
unsignedcharkey;
unsignedchari,j;
unsignedcharSTH0;
unsignedcharSTL0;
unsignedintcodetab[]={64021,64103,64260,64400,
64524,64580,64684,64777,
64820,64898,64968,65030,
65058,65110,65157,65178};
voidmain(void)
{
TMOD=0x01;
ET0=1;
EA=1;
while(1)
{
P3=0xff;//將P3口取出
P3_4=0;//使P3_4為低電平,這樣可以判斷第一豎排有沒有鍵按下
temp=P3;
temp=temp&0x0f;
if(temp!=0x0f)//有鍵按下
{
for(i=50;i>0;i--)
for(j=200;j>0;j--);//延時
temp=P3;
temp=temp&0x0f;
if(temp!=0x0f)//再判斷是否有鍵按下
{
temp=P3;
temp=temp&0x0f;
switch(temp)//判斷是哪個鍵按下
{
case0x0e:
key=0;
break;
case0x0d:
key=1;
break;
case0x0b:
key=2;
break;
case0x07:
key=3;
break;
}
temp=P3;
P1_0=~P1_0;
P0=table[key];
STH0=tab[key]/256;//找出鍵對應的頻率的時間,作為定時器中斷初始值
STL0=tab[key]%256;
TR0=1;
temp=temp&0x0f;
while(temp!=0x0f)
{
temp=P3;
temp=temp&0x0f;
}
TR0=0;
}
}
P3=0xff;
P3_5=0;//跟上面差不多,現在是判斷第二排的按鍵
temp=P3;
temp=temp&0x0f;
if(temp!=0x0f)
{
for(i=50;i>0;i--)
for(j=200;j>0;j--);
temp=P3;
temp=temp&0x0f;
if(temp!=0x0f)
{
temp=P3;
temp=temp&0x0f;
switch(temp)
{
case0x0e:
key=4;
break;
case0x0d:
key=5;
break;
case0x0b:
key=6;
break;
case0x07:
key=7;
break;
}
temp=P3;
P1_0=~P1_0;
P0=table[key];
STH0=tab[key]/256;
STL0=tab[key]%256;
TR0=1;
temp=temp&0x0f;
while(temp!=0x0f)
{
temp=P3;
temp=temp&0x0f;
}
TR0=0;
}
}
P3=0xff;
P3_6=0;
temp=P3;
temp=temp&0x0f;
if(temp!=0x0f)
{
for(i=50;i>0;i--)
for(j=200;j>0;j--);
temp=P3;
temp=temp&0x0f;
if(temp!=0x0f)
{
temp=P3;
temp=temp&0x0f;
switch(temp)
{
case0x0e:
key=8;
break;
case0x0d:
key=9;
break;
case0x0b:
key=10;
break;
case0x07:
key=11;
break;
}
temp=P3;
P1_0=~P1_0;
P0=table[key];
STH0=tab[key]/256;
STL0=tab[key]%256;
TR0=1;
temp=temp&0x0f;
while(temp!=0x0f)
{
temp=P3;
temp=temp&0x0f;
}
TR0=0;
}
}
P3=0xff;
P3_7=0;
temp=P3;
temp=temp&0x0f;
if(temp!=0x0f)
{
for(i=50;i>0;i--)
for(j=200;j>0;j--);
temp=P3;
temp=temp&0x0f;
if(temp!=0x0f)
{
temp=P3;
temp=temp&0x0f;
switch(temp)
{
case0x0e:
key=12;
break;
case0x0d:
key=13;
break;
case0x0b:
key=14;
break;
case0x07:
key=15;
break;
}
temp=P3;
P1_0=~P1_0;
P0=table[key];
STH0=tab[key]/256;
STL0=tab[key]%256;
TR0=1;
temp=temp&0x0f;
while(temp!=0x0f)
{
temp=P3;
temp=temp&0x0f;
}
TR0=0;
}
}
}
}
voidt0(void)interrupt1using0
{
TH0=STH0;
TL0=STL0;
P1_0=~P1_0;
}
電路圖和原理我都有,剛好我也在做這個。你自己看下程序吧,我也不願意注釋。
這個是能發出16個音符聲音的,你寫的AD89S52,應該是AT89S52吧
❻ 單片機89c51電子琴怎麼控制節拍
節拍控制就是控制每個音符延時時間的問題,可以用定時器來實現。所以最好的做法是用兩個定時器來控制樂曲,一個定時器控制頻率(也就是音調),一個定時器控制節奏(也就是節拍)
❼ 單片機電子琴主要成果和特色
其實電子琴的原理就是蜂鳴器發聲的頻率不同能產生不同的聲音,當然使用其他更好的發聲設備產生的聲音更逼真。
那問題就剩下如何改變蜂鳴器的發聲頻率,
這個更簡單,單片機控制蜂鳴器的IO輸出高低電平能使蜂鳴器發聲,那麼只需要改變IO口高低電平的頻率了,
高電平---->延時----->低電平----->延時。延時時間的不同就能改變IO的高低電平頻率
❽ 設計一個簡易電子琴,由單片機控制蜂鳴器發聲,按下按鍵1-7,發出樂音1~7,實現一段樂曲的播放。
電子琴,是供人彈奏的。
電子琴,不會播放樂曲。
http://blog.163.com/asm_c/blog/static/2482031132014101711370141/
參考。
❾ 單片機電子琴
給一個8051的解決辦法:
單片機讀取鍵盤,得到音階,單片機控制一個定時器的中斷周期,使之在指定引腳電平變化,發出對應音階頻率的方波,驅動喇叭發聲,即可實現一個簡單的電子琴。