51单片机实现简易升降调电子琴
立即下载
资源介绍:
51单片机实现简易升降调电子琴
//=========================================================
// 电子琴,4x4矩阵按键
//=========================================================
#include "reg52.h"
#include
#define uchar unsigned char
#define uint unsigned int
#define KEY_PORT P1 //矩阵键盘端口
sbit LSA=P2^2; //138译码器引脚
sbit LSB=P2^3;
sbit LSC=P2^4;
sbit buzz=P2^5; //蜂鸣器
uchar key; //键值
uchar tone=0; //音符
uchar scale=2; //音阶
uchar index; //序号
uchar code tab[]={ //共阴数码管段码表
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
uint code table[]={ //这个数组里存放的是1-7的音调的初始值
// 1 2 3 4 5 6 7 //音符
0xf88c,0xf95c,0xfa14,0xfa6c,0xfb04,0xfb90,0xfc0c,
0xfc44,0xfcab,0xfd09,0xfd34,0xfd82,0xfdc8,0xfe06,
0xfe22,0xfe56,0xfe8c,0xfe9a,0xfec1,0xfee4,0xff03
};
//=========================函数声明========================
void delayms(uint t); //延时函数
void Timer_Init(); //定时器初始化函数
void display(); //数码管显示函数
void keyscan(); //矩阵按键扫描函数
//==========================主函数=========================
void main(void)
{
LSA=LSB=LSC=0;
Timer_Init(); //定时器初始化
while(1) //主循环
{
keyscan(); //矩阵按键扫描
}
}
//=======================延时函数===========================
void delayms(uint t)
{
uchar i;
while(t--)for(i=0;i<120;i++);
}
//===================定时器初始化函数======================
void Timer_Init()
{
TMOD=0x11; //定时器T0和T1都是工作方式1
TH0=0xf8; //定时器T0初值
TL0=0xcd; //11.0592MHz,2ms定时
EA=1; //允许总中断
ET0=1; //允许定时器T0中断
TR0=1; //启动定时器T0
TH1=TL1=0; //定时器T1初值
ET1=1; //允许定时器T1中断
TR1=0; //暂不启动定时器T1
}
//===================定时器T0中断函数=====================
void T0_ISR() interrupt 1
{
TH0=0xf8; //重装初值
TL0=0xcd; //2ms定时
display(); //数码管扫描
}
//===================定时器T1中断函数=====================
void T1_ISR() interrupt 3
{
TH1=table[index]>>8; //按当前音符装载定时器数据,高8位
TL1=table[index]; //低8位
buzz=~buzz; //蜂鸣器取反以驱动无源蜂鸣器发声
}
//======================数码管显示函数=====================
void display()
{
static uchar t=0;
P0=0;
LSC=t;
if(t==0)P0=tab[tone]; //显示音符
else P0=tab[scale]; //显示音阶
t=(t+1)%2; //切换下一位
}
//====================矩阵按键扫描函数====================
void keyscan()
{
uchar key=0;
KEY_PORT=0x0f;
if(KEY_PORT!=0x0f)
{
delayms(10); //延时消抖
if(KEY_PORT!=0x0f)
{
//列扫描
KEY_PORT=0x0f;
switch(KEY_PORT)
{
case(0x07): key=1;break;
case(0x0b): key=2;break;
case(0x0d): key=3;break;
case(0x0e): key=4;break;
}
//行扫描
KEY_PORT=0xf0;
switch(KEY_PORT)
{
case(0x70): key=key;break;
case(0xb0): key=key+4;break;
case(0xd0): key=key+8;break;
case(0xe0): key=key+12;break;
}
if(key>=1 && key<=7)
{
tone=key; //记录音符
index=(scale-1)*7+key-1; //按当前音阶和音符取频率值的序号
TH1=table[index]>>8; //定时器赋初值取音符对应的数据高字节
TL1=table[index]; //取低字节
TR1=1; //启动定时器T1发音
}
else if(key==13) //降调
{
if(scale>1)scale--;
}
else if(key==14) //升调
{
if(scale<3)scale++;
}
while(KEY_PORT!=0xf0); //等待按键松开
TR1=0; //停止定时器T1
buzz=1; //关闭蜂鸣器
}
}
}