本專案實現一款基於AT89S51單片機的簡易電子琴,採用4×4矩陣鍵盤輸入,可演奏16個不同音調。系統利用單片機定時器T0產生方波頻率信號駅動蜂鳴器發聲,定時器T1控制音拍節奏,並透過數碼管顯示當前按鍵對應的音符編碼。
採用12MHz晶振,定時器T0工作於模式1(16位定時器)。機器週期1μs,溢出率計算公式:
TH0 = (65536 - 頻率計數值) / 256 TL0 = (65536 - 頻率計數值) % 256
常用音符計數值表(部分):
| 音符 | 頻率(Hz) | 計數值 |
|---|---|---|
| 中音DO (C4) | 523 | 64580 |
| 中音RE (D4) | 587 | 64684 |
| 中音MI (E4) | 659 | 64777 |
| 中音FA (F4) | 698 | 64820 |
| 中音SO (G4) | 784 | 64898 |
| 中音LA (A4) | 880 | 64968 |
| 中音SI (B4) | 988 | 65030 |
| 高音DO (C5) | 1046 | 65058 |
採用行列反轉掃描法:依次將P3.4–P3.7置低,讀取P3.0–P3.3狀態。雙重延時消抖(50×200循環),確認按鍵穩定後查表獲取對應音符索引。
#include <AT89X51.H>
unsigned char code seg_table[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
unsigned int code freq_table[] = {64021,64103,64260,64400,64524,64580,64684,64777,
64820,64898,64968,65030,65058,65110,65157,65178};
unsigned char temp, key, i, j;
unsigned char STH0, STL0;
void main(void) {
TMOD = 0x01; // T0模式1
ET0 = 1; EA = 1;
while(1) {
// 掃描第1行 (P3.4)
P3 = 0xFF; P3_4 = 0;
temp = P3 & 0x0F;
if(temp != 0x0F) {
for(i=50;i>0;i--) for(j=200;j>0;j--);
temp = P3 & 0x0F;
if(temp != 0x0F) {
switch(temp) {
case 0x0E: key=0; break;
case 0x0D: key=1; break;
case 0x0B: key=2; break;
case 0x07: key=3; break;
}
P0 = seg_table[key];
STH0 = freq_table[key] / 256;
STL0 = freq_table[key] % 256;
TR0 = 1;
while((P3 & 0x0F) != 0x0F);
TR0 = 0;
}
}
// 第2-4行掃描邏輯同理 (P3.5-P3.7 對應 key 4-15)
// ... 此處省略重複代碼 ...
}
}
void t0_isr(void) interrupt 1 using 0 {
TH0 = STH0; TL0 = STL0;
P1_0 = ~P1_0; // 翻轉輸出產生方波
}
T0中斷以預載值重裝計數器,並翻轉P1.0輸出腳位,產生50%佔空比方波。頻率精度取決於晶振穩定性與計數值準確度。