標題:
proteus 51單片機電子琴仿真圖加程序
[打印本頁]
作者:
lzh10620
時間:
2020-6-10 13:16
標題:
proteus 51單片機電子琴仿真圖加程序
24b44a1fcd68e46ede7248b72bddb28.png
(36.12 KB, 下載次數(shù): 76)
下載附件
2020-6-10 13:15 上傳
#include <reg52.h>
#define SONG 4 // 歌曲的數(shù)量
#define LED_PORT P3
#define uchar unsigned char // 以后unsigned char就可以用uchar代替
#define uint unsigned int // 以后unsigned int 就可以用uint 代替
#define ulong unsigned long // 以后unsigned long就可以用ulong代替
sbit Key1_P = P1^0; // 彈奏鍵1的管腳
sbit Key2_P = P1^1; // 彈奏鍵2的管腳
sbit Key3_P = P1^2; // 彈奏鍵3的管腳
sbit Key4_P = P1^3; // 彈奏鍵4的管腳
sbit Key5_P = P1^4; // 彈奏鍵5的管腳
sbit Key6_P = P1^5; // 彈奏鍵6的管腳
sbit Key7_P = P1^6; // 彈奏鍵7的管腳
//sbit Key8_P = P1^7; // 彈奏鍵8的管腳
sbit Key9_P = P2^0; // 播放內(nèi)置歌曲的按鍵管腳
sbit Key10_P = P2^1; // 開始/停止錄制
sbit Key11_P = P2^2; // 播放錄制的歌曲
sbit Beep_P = P2^4; // 揚聲器管腳
sbit Led_P = P2^7; // 錄歌指示燈
sbit Key_Set1 = P2^3; //設(shè)置音區(qū)按鍵1
sbit Key_Set2 = P2^5; //設(shè)置音區(qū)按鍵2
sbit Key_Set3 = P2^6; //設(shè)置音區(qū)按鍵3
uchar gTone=0; // gTone代表當前要播放的音調(diào)
uchar gPlayStatus; // gPlayStatus代表當前的播放狀態(tài),0是停止,1是播放
uchar gSong; // gSong代表當前播放到第幾首歌
uchar ledflag=0; //流水燈的標志位
uchar yinquflag=1; //音區(qū)選擇 1:第一組 2:第二組 3:第三組 默認第一組
/* 定時器初值 低1 低2 低3 低4 低5 低6 低7 中1 中2 中3 中4 中5 中6 中7 高1 高2 高3 高4 高5 高6 高7 */
uchar code ArrTL0[]={ 0X8B,0X5B,0X14,0X66,0X03,0X8F,0X0B,0X43,0XAB,0X08,0X33,0X81,0XC7,0X05,0X21,0X55,0X84,0X99,0XC0,0XE3,0X02};
uchar code ArrTH0[]={ 0XF8,0XF9,0XFA,0XFA,0XFB,0XFB,0XFC,0XFC,0XFC,0XFD,0XFD,0XFD,0XFD,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFE,0XFF};
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/* 數(shù)碼管的顯示值 1 2 3 4 5 6 7 */
uchar code ArrDig[]={ 0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8};
/* 《水手》的樂譜 */
uchar code Music1[]={
5,4, 9,2, 8,2, 9,4, 8,2, 9,2,
10,3, 11,1, 10,2, 8,2, 9,8, 9,1,
10,2, 10,1, 9,1, 8,2, 7,1, 7,1, 8,2, 7,1, 7,1, 8,2, 9,2,
7,2, 6,2, 5,2, 7,2, 6,8,
5,4, 9,2, 8,2, 9,4, 8,2, 9,2,
10,2, 10,1, 11,1, 9,2, 8,2, 9,8,
10,3, 9,1, 8,2, 7,2, 8,2, 8,1, 7,1, 8,2, 8,1, 9,1,
6,2, 6,2, 5,2, 4,2, 5,8,
8,3, 8,1, 8,2, 8,2, 10,2, 10,1, 9,1, 8,2, 7,1, 7,1,
9,3, 8,1, 7,2, 8,1, 7,1, 5,8,
8,3, 8,1, 8,2, 8,2, 8,2, 8,1, 8,1, 8,2, 7,1, 8,1,
9,2, 9,2, 9,1, 8,1, 7,1, 8,1, 9,8,
8,3, 8,1, 8,2, 8,2, 10,2, 9,2, 8,2, 8,2,
9,2, 8,2, 7,2, 8,1, 7,1, 5,7, 5,1,
8,3, 8,1, 8,2, 8,1, 8,1, 8,2, 8,2, 7,2, 8,2,
9,2, 9,2, 8,2, 7,2, 9,4, 9,2, 11,2,
12,4, 11,4, 9,4, 8,2, 7,2,
8,2, 9,1, 8,1, 7,2, 6,2, 5,4, 5,2, 6,2,
7,4, 7,2, 9,2, 8,4, 6,1, 5,1, 4,2,
5,3, 5,1, 7,2, 8,2, 9,4, 9,2, 11,2,
12,4, 11,4, 9,4, 8,2, 7,2,
8,2, 9,1, 8,1, 7,2, 6,2, 5,4, 5,2, 6,2,
7,4, 7,2, 9,2, 8,4, 7,2, 6,2, 5,12
};
/* 《揮著翅膀的女孩》的樂譜 */
uchar code Music2[]={
9,4, 9,2, 10,2, 11,4, 7,2, 8,2,
9,2, 9,2, 9,2, 10,2, 11,4, 8,2, 9,2,
10,4, 10,2, 9,2, 7,4, 10,2, 9,2,
10,4, 5,2, 7,2, 8,4, 7,2, 8,2,
9,4, 9,2, 10,2, 11,4, 12,2, 13,2,
14,2, 14,2, 9,2, 10,2, 11,4, 8,2, 9,2,
10,2, 9,2, 10,2, 14,2, 14,4, 8,2, 9,2,
10,2, 9,2, 10,2, 15,2, 15,4, 14,2, 13,2,
14,6, 15,2, 16,2, 15,2, 14,2, 13,2,
14,6, 14,2, 13,2, 11,2, 11,2, 7,2,
12,6, 12,2, 11,2, 7,2, 7,2, 9,2,
8,6, 9,1, 10,1, 10,2, 11,2, 14,2, 13,2,
14,6, 15,2, 16,2, 15,2, 14,2, 13,2,
14,6, 14,2, 13,2, 11,2, 11,2, 7,2,
12,6, 12,2, 11,2, 11,2, 14,2, 13,2,
14,16
};
/* 《茉莉花》的樂譜 */
uchar code Music3[]={
9,4, 9,2, 11,2, 12,2, 14,2, 14,2, 12,2,
11,4, 11,2, 12,2, 11,8,
9,4, 9,2, 11,2, 12,2, 14,2, 14,2, 12,2,
11,4, 11,2, 12,2, 11,8,
11,4, 11,4, 11,4, 9,2, 11,2,
12,4, 12,4, 11,8,
9,4, 8,2, 9,2, 11,4, 9,2, 8,2,
7,4, 7,2, 8,2, 7,8,
9,2, 8,2, 7,2, 9,2, 8,6, 9,2,
11,4, 12,2, 14,2, 11,8,
8,4, 9,2, 11,2, 8,2, 9,2, 7,2, 5,2,
4,8, 5,4, 7,4,
8,6, 9,2, 7,2, 8,2, 7,2, 5,2,
4,12
};
/* 《歡樂頌》的樂譜 */
uchar code Music4[]={
9,2, 9,2, 10,2, 11,2,
11,2, 10,2, 9,2, 8,2,
7,2, 7,2, 8,2, 9,2,
9,3, 8,1, 8,4,
9,2, 9,2, 10,2, 11,2,
11,2, 10,2, 9,2, 8,2,
7,2, 7,2, 8,2, 9,2,
8,3, 7,1, 7,4,
8,2, 8,2, 9,2, 7,2,
8,2, 9,1, 10,1, 9,2, 7,2,
8,2, 9,1, 10,1, 9,2, 8,2,
7,2, 8,2, 4,2, 9,2,
9,2, 9,2, 10,2, 11,2,
11,2, 10,2, 9,2, 10,1, 8,1,
7,2, 7,2, 8,2, 9,2,
8,3, 7,1, 7,4
} ;
/*********************************************************/
// 毫秒級的延時函數(shù),time是要延時的毫秒數(shù)
/*********************************************************/
void DelayMs(uint time)
{
uint i,j;
for(i=0;i<time;i++)
for(j=0;j<112;j++);
}
/*********************************************************/
// 發(fā)出指定音調(diào)及其節(jié)拍的聲音,tone代表音調(diào),beat代表節(jié)拍
/*********************************************************/
void PlayTone(uchar tone,float beat)
{
int i;
P0=ArrDig[tone%7]; // 數(shù)碼管顯示當前音調(diào)值
gTone=tone; // 將音調(diào)值賦給全局變量gTone
TH0 = ArrTH0[tone]; // 裝入定時器TH0的初值
TL0 = ArrTL0[tone]; // 裝入定時器TL0的初值
TR0=1; // 啟動定時器
for(i=0;i<beat;i++)
{
DelayMs(200);
}
TR0=0; // 停止定時器
P0=0xff; // 關(guān)閉數(shù)碼管顯示
Beep_P=1;
}
/*********************************************************/
// 播放內(nèi)置的音樂
// arr[]是要播放的樂譜數(shù)組,num是數(shù)組里面的元素個數(shù)
/*********************************************************/
void PlayMusic(uchar music[],uint num)
{
uint i=0;
while(i<num)
{
if(gPlayStatus==1) // 判斷播放狀態(tài)是否為播放還是暫停
{
PlayTone(music[i],music[i+1]); // 開始演奏一個節(jié)拍
i+=2; // 進入下一個節(jié)拍,因為每2個數(shù)為1組,所以每次要加2
if(i==num) // 判斷歌曲是否播放完了
{
gPlayStatus=0; // 播放完了的話,則把播放狀態(tài)改為暫停,否則會循環(huán)播放
}
}
if(Key9_P==0) // 下一曲
{
DelayMs(10); // 消除按鍵按下的抖動
while(!Key9_P); // 等待按鍵釋放
DelayMs(10); // 消除按鍵松開的抖動
gSong++; // 把當前播放到第幾首歌的變量gSong加1,即切到下一曲
if(gSong>SONG) // 如果gSong為SONG,說明到后面的盡頭了,則轉(zhuǎn)為第一首
gSong=1;
break;
}
}
}
/*********************************************************/
/*********************************************************************
: FlashLed1
*********************************************************************/
void FlashLed1(void)
{
LED_PORT = 0x55; //
DelayMs(200);
LED_PORT = 0xaa; //
DelayMs(200);
}
/*********************************************************************
: FlashLed2
*********************************************************************/
void FlashLed2(void)
{
unsigned char i = 0;
for (i=0; i<7; i++)
{
LED_PORT = (0xff & ~(1<<i));
DelayMs(200);
}
}
/*********************************************************************
: FlashLed3
*********************************************************************/
void FlashLed3(void)
{
LED_PORT = 0xff; //
DelayMs(200);
LED_PORT = 0x00; //
DelayMs(200);
}
/*********************************************************************
: FlashLed4
*********************************************************************/
void FlashLed4(void)
{
unsigned char i = 0;
for (i=0; i<7; i++)
{
LED_PORT =i;
DelayMs(200);
}
}
/*********************************************************************
: FlashLed5
*********************************************************************/
void FlashLed5(void)
{
unsigned char i = 0;
for (i=0; i<7; i++)
{
LED_PORT = (0xff & (1<<i));
DelayMs(200);
}
}
/*********************************************************************
: FlashLed6
*********************************************************************/
void FlashLed6(void)
{
unsigned char i = 0;
for (i=0; i<7; i++)
{
LED_PORT = (0xff & ~(1<<6-i));
DelayMs(200);
}
}
/*********************************************************************
: FlashLed7
*********************************************************************/
void FlashLed7(void)
{
LED_PORT = 0x0f; //
DelayMs(200);
LED_PORT = 0xf0; //
DelayMs(200);
}
void LED_PLAY(uchar num)
{
switch(num)
{
case(0x01):FlashLed1();break;
case(0x02):FlashLed2();break;
case(0x03):FlashLed3();break;
case(0x04):FlashLed4();break;
case(0x05):FlashLed5();break;
case(0x06):FlashLed6();break;
case(0x07):FlashLed7();break;
}
}
/*********************************************************/
// 定時器初始化函數(shù)
/*********************************************************/
void TimerInit()
{
TMOD=1; // 定時器0,工作方式1
TH0=0; // 裝定時器TH0的初值
TL0=0; // 裝定時器TL0的初值
ET0=1; // 開啟定時器0中斷
EA=1; // 開啟總中斷
}
/*********************************************************/
// 彈奏鍵掃描函數(shù)
/*********************************************************/
uchar KeyScanf()
{
if(Key_Set1==0) // 按鍵被按下 P2^3
yinquflag=1; //音區(qū)1
if(Key_Set2==0) // 按鍵被按下 P2^5
yinquflag=2; //音區(qū)2
if(Key_Set3==0) // 按鍵被按下 P2^6
yinquflag=3; //音區(qū)3
if(Key1_P==0) // 按鍵1被按下,返回1
return 1;
if(Key2_P==0) // 按鍵2被按下,返回2
return 2;
if(Key3_P==0) // 按鍵3被按下,返回3
return 3;
if(Key4_P==0) // 按鍵4被按下,返回4
return 4;
if(Key5_P==0) // 按鍵5被按下,返回5
return 5;
if(Key6_P==0) // 按鍵6被按下,返回6
return 6;
if(Key7_P==0) // 按鍵7被按下,返回7
return 7;
// if(Key8_P==0) // 按鍵8被按下,返回8
// return 8;
return 0; // 8個按鍵都沒被按下,返回0
}
/*********************************************************/
// 主函數(shù),程序從這里開始執(zhí)行
/*********************************************************/
void main()
{
uchar i; // 循環(huán)變量
uchar ret; // 用于保存音調(diào)鍵函數(shù)的返回值
uchar count; // 用于記錄當前錄制了多少個音調(diào)
uchar record[99]={0}; // 存儲錄制歌曲的數(shù)組
TimerInit();
gSong=0; // 上電默認第一首歌
gPlayStatus=0; // 上電默認是0停止狀態(tài)(1為播放狀態(tài))
while(1)
{
if(gPlayStatus==1) // 如果處于播放狀態(tài),則判斷是哪一首歌曲需要播放
{
switch(gSong)
{
case 1 : PlayMusic(Music1,sizeof(Music1)); break;
case 2 : PlayMusic(Music2,sizeof(Music2)); break;
case 3 : PlayMusic(Music3,sizeof(Music3)); break;
case 4 : PlayMusic(Music4,sizeof(Music4)); break;
default: break;
}
}
/*播放內(nèi)置的音樂*/
if(Key9_P==0) // 開始播放
{
DelayMs(10); // 消除按鍵按下的抖動
while(!Key9_P); // 等待按鍵釋放
DelayMs(10); // 消除按鍵松開的抖動
gSong++; // 把當前播放到第幾首歌的變量gSong加1,即切到下一曲
if(gSong>SONG) // 如果gSong為SONG,說明到后面的盡頭了,則轉(zhuǎn)為第一首
gSong=1;
gPlayStatus=1; // 播放狀態(tài)改為1,即播放
}
/*開始/停止 錄制按鍵的處理*/
if(Key10_P==0)
{
Led_P=~Led_P; // 錄歌指示燈狀態(tài)切換
if(Led_P==0) // 如果是切換為錄歌狀態(tài)
{
count=0; // 清零記錄按鍵值計數(shù),從新開始計數(shù)
}
DelayMs(10); // 消除按鍵按下的抖動
while(!Key10_P); // 等待按鍵釋放
DelayMs(10); // 消除按鍵松開的抖動
}
/*播放錄制的音樂*/
if(Key11_P==0)
{
for(i=0;i<count;i++)
{
PlayTone(record[i],2); // 播放該音調(diào)
DelayMs(50); // 每播放一個音調(diào),停頓50毫秒
}
DelayMs(10); // 消除按鍵按下的抖動
while(!Key11_P); // 等待按鍵釋放
DelayMs(10); // 消除按鍵松開的抖動
}
/* 8個彈奏按鍵的掃描 */
ret=KeyScanf(); // 獲取8個按鍵的掃描結(jié)果
if(ret!=0) // 如果有按鍵按下去了
{
ledflag=ret; //給流水燈賦值
P3=(0xff)^ledflag;
P0=ArrDig[(ret-1)%7]; // 數(shù)碼管顯示當前音調(diào)值
TH0 = ArrTH0[ret]; // 裝入定時器TH0的初值
TL0 = ArrTL0[ret]; // 裝入定時器TL0的初值
gTone=ret;
if(Led_P==0) // 如果是錄音狀態(tài),則把彈奏值記錄下來
{
record[count]=gTone; // 記錄當前彈奏的按鍵值
count++; // 準備記錄下一個
}
TR0=1; // 啟動定時器,播放彈奏的音符
DelayMs(20); // 去除按鍵按下的抖動
while(KeyScanf()); // 等待按鍵釋放
DelayMs(70); // 按鍵釋放之后,再播放70毫秒,達到余音的效果
TR0=0; // 停止定時器
P0=0xff; // 關(guān)閉數(shù)碼管顯示
P3=0xff; // 關(guān)閉led
Beep_P=1; // 關(guān)閉定時器,停止彈奏音符的播放
}
// LED_PLAY(ledflag);
}
}
/*********************************************************/
// 功能:定時器0中斷處理函數(shù)
/*********************************************************/
void time0() interrupt 1
{
Beep_P=!Beep_P; // 將控制揚聲器的管腳取反
if(yinquflag ==1)
{
TH0=ArrTH0[gTone]; // 重裝定時器TH0的初值
TL0=ArrTL0[gTone]; // 重裝定時器TL0的初值
}
else if(yinquflag ==2)
{
TH0=ArrTH0[gTone+5]; // 重裝定時器TH0的初值
TL0=ArrTL0[gTone+5]; // 重裝定時器TL0的初值
}
else if(yinquflag ==3)
{
TH0=ArrTH0[gTone+10]; // 重裝定時器TH0的初值
TL0=ArrTL0[gTone+10]; // 重裝定時器TL0的初值
}
}
復制代碼
全部資料51hei下載地址:
電子琴終結(jié)版.rar
(108.31 KB, 下載次數(shù): 72)
2020-6-10 13:16 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
歡迎光臨 (http://www.torrancerestoration.com/bbs/)
Powered by Discuz! X3.1