#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit Beep = P2^4; // 蜂鸣器
sbit SegDig = P2^3; // 数码管位选
// 7个独立按键
sbit Key1 = P3^0;
sbit Key2 = P3^1;
sbit Key3 = P3^2;
sbit Key4 = P3^3;
sbit Key5 = P3^4;
sbit Key6 = P3^5;
sbit Key7 = P3^6;
// 共阴数码管段码(0无用,从1~8)
uchar code SEG_CODE[8] = {0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80};
// 8个音阶
uint code TONE_TABLE[8] = {0xF828,0xF959,0xFA13,0xFA68,0xFB04,0xFB90,0xFC0C,0xFC44};
// 歌曲数据
uchar code MUSIC1[] = {0x11,0x11,0x51,0x51,0x61,0x61,0x51,
0x41,0x41,0x31,0x31,0x21,0x21,0x11,
0x11,0x11,0x51,0x51,0x61,0x61,0x51,
0x41,0x41,0x31,0x31,0x21,0x21,0x11,
0x00};
uchar code MUSIC2[] = {0x52,0x32,0x12,0x32,0x52,0x82,0xA2,0x82,
0x52,0x32,0x12,0x32,0x52,0x82,0xA2,0x82,
0x62,0x72,0x82,0x72,0x62,0x52,0x42,0x32,
0x52,0x32,0x12,0x32,0x52,0x82,0xA2,0x82,
0x62,0x72,0x82,0x72,0x62,0x52,0x42,0x32,
0x52,0x32,0x12,0x32,0x52,0x82,0xA2,0x82,
0x00};
uchar cur_toneH=0, cur_toneL=0;
bit playing = 0;
// 定时器0中断
void Timer0_ISR(void) interrupt 1
{
TH0 = cur_toneH;
TL0 = cur_toneL;
Beep = ~Beep;
}
void Delay1ms(uint ms)
{
uint i,j;
for(i=0;i<ms;i++)
for(j=0;j<120;j++);
}
void Delay20ms() { Delay1ms(20); }
void Delay100ms() { Delay1ms(100); }
void Delay200ms() { Delay1ms(200); }
void Delay2s() { Delay1ms(2000); }
// 无按键检测
void WaitNoKey(void)
{
Delay20ms();
while((P3 & 0x7F) != 0x7F); // P3.0~P3.6都为高,表示无按下
}
// 按键扫描,返回键值(1~7),0表无键
uchar ScanKey(void)
{
if(!Key1) return 1;
if(!Key2) return 2;
if(!Key3) return 3;
if(!Key4) return 4;
if(!Key5) return 5;
if(!Key6) return 6;
if(!Key7) return 7;
return 0;
}
// 按键组扫描,返回键值,1~7为独立按键,8为高音DO,9为退出
uchar ScanKeyGroup(void)
{
if(!Key1) return 1;
if(!Key2) return 2;
if(!Key3) return 3;
if(!Key4) return 4;
if(!Key5) return 5;
if(!Key6) return 6;
if(!Key7) return 7;
// 可自定义组合键,如Key1+Key7为高音DO,Key6+Key7为退出等
// if(!Key1 && !Key7) return 8; // 高音DO
// if(!Key6 && !Key7) return 9; // 退出
return 0;
}
// 数码管显示1~8
void DisplaySeg(uchar num)
{
SegDig = 0;
P0 = SEG_CODE[num-1];
SegDig = 1;
}
// 发音
void PlayTone(uchar idx, uint ms)
{
cur_toneH = TONE_TABLE[idx] >> 8;
cur_toneL = TONE_TABLE[idx] & 0xFF;
TH0 = cur_toneH;
TL0 = cur_toneL;
playing = 1;
TR0 = 1;
Delay1ms(ms);
TR0 = 0;
playing = 0;
}
// 电子琴功能
void PianoMode()
{
P1 = 0xFF;
P1 &= ~0x01;
WaitNoKey();
while(1)
{
uchar key = ScanKeyGroup();
if(key==0) continue;
Delay20ms();
key = ScanKeyGroup();
if(key >= 1 && key <= 7)
{
DisplaySeg(key);
PlayTone(key-1,100);
}
// 可自定义退出、高音DO等功能
else if(key == 8) // 高音DO
{
DisplaySeg(8);
PlayTone(7,100);
}
else if(key == 9) // 退出
{
return;
}
WaitNoKey();
}
}
// 歌曲播放
void PlayMusic(const uchar* music)
{
uchar i=0;
uchar note, beat, tone;
while(1)
{
note = music[i];
if(note == 0x00) break;
beat = note & 0x0F;
tone = (note >> 4) - 1;
if(tone < 8)
PlayTone(tone, beat * 100);
else
Delay1ms(beat*100);
i++;
if(ScanKey()) {Delay2s(); if(ScanKey()) break;}
}
}
// 音乐选择/播放
void MusicMode()
{
P1 = 0xFF;
P1 &= ~0x02;
WaitNoKey();
while(1)
{
uchar k = 0;
while((k=ScanKey())==0);
Delay20ms();
k = ScanKey();
if(k==1) PlayMusic(MUSIC1);
else if(k==2) PlayMusic(MUSIC2);
else if(k==3) return; // 按键3退出
WaitNoKey();
}
}
// 主循环
void main()
{
TMOD = 0x01;
EA = 1;
ET0 = 1;
Beep = 1;
SegDig = 1;
P1 = 0xFF;
P0 = 0xFF;
while(1)
{
P1 = 0xFF;
Delay100ms();
P1 &= ~0x80;
if(!Key1) PianoMode();
else if(!Key2) MusicMode();
Delay100ms();
}
}这个代码实现了什么功能,我如果想用proteus仿真你能不能帮我生成一个可以匹配这个代码的仿真图
最新发布