#include "reg51.h"
sbit DO_KEY = P1^0; // 音符按键
sbit RE_KEY = P1^1;
sbit MI_KEY = P1^2;
sbit FA_KEY = P1^3;
sbit SO_KEY = P1^4;
sbit LA_KEY = P1^5;
sbit XI_KEY = P1^6;
sbit BEEP = P3^3; // 蜂鸣器
sbit PLAY_KEY = P2^0; // 播放键
sbit LED = P2^1; // 通电指示LED灯
// 数码管段码(0-7对应do-si)
unsigned char code SEG_CODE[] = {0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x88};
// 音符频率参数
unsigned int code NOTE_TIMER[] = {64580,64684,64777,64820,64898,64968,65030,64260};//523HZ-1047HZ
// 《晴天》旋律数据
unsigned char code MUSIC[] =
{
2,4,1,4,3,4,2,4, 0,4,4,4,6,4,6,4,6,4,4,4,0,4, // 刮风这天我试过握着你手
0,4,5,4,5,4, 5,4,4,4,4,4, 4,4,3,4,2,4,1,4,2,4,3,4,2,4, // 但偏偏雨渐渐大到我看你不见
2,4,3,4,4,4,2,4, 3,4,4,4,5,4,6,4,6,4,6,4,6,4, // 还要多久我才能在你身边
6,4,6,4,4,4,4,4,5,4,4,4,3,4, // 等到放晴的那天
1,4,2,4,3,4,4,4,5,4,0,4,5,4,6,4,6,4, // 也许我会比较好一点
2,4,1,4,3,4,2,4, 0,4,4,4,6,4,6,4,5,4,4,4,0,4, // 从前从前有个人爱你很久
0,4,5,4,5,4, 5,4,4,4,4,4, 4,4,3,4,2,4,1,4,2,4,3,4,2,4, // 但偏偏雨渐渐把距离吹得好远
2,4,3,4,4,4,2,4, 3,4,4,4,6,4,6,4,6,4,6,4,6,4, // 好不容易又能在多爱一天
6,4,6,4,4,4,4,4,5,4,4,4, // 但故事的最后
3,4,5,4,6,4,7,4,1,4,2,4,1,4,2,4,0,8, // 你好像还是说了拜拜
0xFF
};
unsigned char music_idx = 0;
bit is_playing = 0;
unsigned char curr_note = 8;
void delay_ms(unsigned int ms)
{
unsigned int i, j;
for(i = 0; i < ms; i++)
for(j = 0; j < 123; j++);
}
// LED指示灯控制函数
void led_control(bit state)
{
LED = state; // 控制LED亮灭,0=亮,1=灭(共阳接法)
}
void beep_set_note(unsigned char note)
{
curr_note = note;
if(note >= 8)
{
TR1 = 0;
BEEP = 1;
P0 = 0xFF;
return;
}
TR1 = 0;
TH1 = NOTE_TIMER[note] >> 8;
TL1 = NOTE_TIMER[note] & 0xFF;
TR1 = 1;
P0 = SEG_CODE[note];
}
void play_music()
{
unsigned char note, dur;//音符和时长变量
if(MUSIC[music_idx] == 0xFF)
{
music_idx = 0;
beep_set_note(8);
delay_ms(2000);
return;
}
note = MUSIC[music_idx++];
dur = MUSIC[music_idx++];
beep_set_note(note);
switch(dur)
{
case 2: delay_ms(300); break;
case 4: delay_ms(600); break;
case 8: delay_ms(1200); break;
default: delay_ms(600); break;
}
beep_set_note(8);
delay_ms(dur == 2 ? 20 : 40);
}
void check_keys()
{
unsigned char i;
if(PLAY_KEY == 0)
{
delay_ms(20);
if(PLAY_KEY == 0)
{
is_playing = 1;
music_idx = 0;
// 播放时LED闪烁提示
led_control(0); // LED亮
while(PLAY_KEY == 0);
}
}
// 简化音符按键检测
for(i = 0; i < 7; i++)
{
if(!(P1 & (1 << i)))
{
is_playing = 0;
beep_set_note(i);
// 弹奏时LED闪烁
led_control(0); // LED亮
while(!(P1 & (1 << i)));
beep_set_note(8);
led_control(1); // LED灭
break;
}
}
}
void main()
{
unsigned char i;
// 初始化
TMOD = 0x10;
EA = 1;
ET1 = 1;
beep_set_note(8);
// 通电指示:LED闪烁3次
led_control(1); // 初始状态LED灭
delay_ms(500);
for(i = 0; i < 3; i++)
{
led_control(0); // LED亮
delay_ms(200);
led_control(1); // LED灭
delay_ms(200);
}
// 通电完成,LED常亮
led_control(0);
while(1)
{
check_keys();
if(is_playing)
{
play_music();
// 音乐播放结束后LED恢复常亮
if(music_idx == 0)
{
led_control(0);
}
}
}
}
void timer1_isr() interrupt 3
{
TH1 = NOTE_TIMER[curr_note] >> 8;
TL1 = NOTE_TIMER[curr_note] & 0xFF;
BEEP = ~BEEP;
}保持数据优化代码
最新发布