找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 8544|回复: 4
收起左侧

51单片机超级电子琴(C语言)

[复制链接]
ID:51707 发表于 2013-7-11 02:37 | 显示全部楼层 |阅读模式
/*说明:此程序是用矩阵按键和音乐实验组合而成的,先是写出矩阵键盘程序,得出键值。然后通过判断键值而分配各种音符,从而得到电子琴效果!硬件连接!
硬键连接:P1口接矩阵键盘,P3.5接蜂鸣器引脚*/
#include <reg52.h>//头文件
#define uint unsigned int//宏定义
#define uchar unsigned char//宏定义
void delay(uchar);//延时子函数声明
void bbtt (uchar);//声音处理子函数声明
void pan();//按键子函数声明
uint code table[]={
0xfd,0x12,0xfd,0x80, 0xfd,0xc6, 0xfe,0x07,0xfe,0x25,0xfe,0x57,
0xfe,0x84,0xfe,0x98,0xfe,0xc0,0xfe,0xe3,0xff,0x01, 0xff,0x10, 0xff,0x29,0xff,0x42
};/*音符代码 低音3,低音5,低音6,低音7,中音1,中音2,中音3,中音4,中音5,中音6,
中音7,高音1,高音2,高音3,基中一个音用两个数表示。*/
sbit bbt=P3^5;//定义蜂鸣器引脚为P3.5脚。
uchar num,lui,a,temp,num1,num2,numm,aa,bb;//定义行变量
void main()//主程序开始
{
TMOD=01;//设置定时器工作在方式0下
IE=0X82;//开总中断与中断允许
num=17;//定义初值,开机使它不亮
while(1)
{
pan();//按键识别子函数
TR0=0;//将定时器关掉
/
bbt=1;//将蜂鸣器关掉
//
/*将各按键得出键值码,也就是让每个键得到相应的音符*/

if(num!=17)//判断num是否不等于17,不等就执行以下语句,否则跳过
{
  switch(num)//执行开关语句
   {
    case 0://0x00与num值是否相等?
    {
    TR0=1;//打开定时器
    bbtt (0);//调用声音处理子函数,并赋值0
    num=17;// 将num值装回,使按键按下时只响一声
    }
    break;//返回开关语句
/////////////////////////////////////////////////////////////////
    case 1://0x01与num值是否相等?
    {
    TR0=1;//打开定时器
    bbtt (2);//调用声音处理子函数,并赋值2
    num=17;// 将num值装回,使按键按下时只响一声
    }
    break;//返回
//////////////////////////////////////////////////////////////////
    case 2://0x08与num值是否相等?
    {
    TR0=1;//打开定时器
    bbtt (4); //调用声音处理子函数,并赋值4
    num=17;// 将num值装回,使按键按下时只响一声
    }
    break;//返回
//////////////////////////////////////////////////////////////////
    case 3://0x00与num值是否相等?
    {
    TR0=1;//打开定时器
    bbtt (6);//调用声音处理子函数,并赋值6
    num=17;// 将num值装回,使按键按下时只响一声
    }
    break;//返回继续判断是否有键按下
/////////////////////////////////////////////////////////////////
    case 4://0x04与num值是否相等?
    {
    TR0=1;//打开定时器
    bbtt (8);//调用声音处理子函数,并赋值8
    num=17;// 将num值装回,使按键按下时只响一声
    }
    break;//返回
//////////////////////////////////////////////////////////////////
    case 5://0x08与num值是否相等?
    {
    TR0=1;//打开定时器
    bbtt (10);//调用声音处理子函数,并赋值10
    num=17;// 将num值装回,使按键按下时只响一声
    }
    break;//返回
    case 6://0x00与num值是否相等?
    {
    TR0=1;//打开定时器
    bbtt (12);//调用声音处理子函数,并赋值12
    num=17;// 将num值装回,使按键按下时只响一声
    }
    break;//返回继续判断是否有键按下
/////////////////////////////////////////////////////////////////
    case 7://0x04与num值是否相等?
    {
    TR0=1;//打开定时器
    bbtt (14);//调用声音处理子函数,并赋值14
    num=17;// 将num值装回,使按键按下时只响一声
    }
    break;//返回
    case 8://0x08与num值是否相等?
    {
    TR0=1;//打开定时器
    bbtt (16);//调用声音处理子函数,并赋值16
    num=17;// 将num值装回,使按键按下时只响一声
    }
    break;//返回
//////////////////////////////////////////////////////////////////
    case 9://0x00与num值是否相等?
    {
    TR0=1;//打开定时器
    bbtt (18);//调用声音处理子函数,并赋值18
    num=17;// 将num值装回,使按键按下时只响一声
    }
    break;//返回继续判断是否有键按下
/////////////////////////////////////////////////////////////////
    case 10://0x04与num值是否相等?
    {
    TR0=1;//打开定时器
    bbtt (20);//调用声音处理子函数,并赋值20
    num=17;// 将num值装回,使按键按下时只响一声
    }
    break;//返回
//////////////////////////////////////////////////////////////////
    case 11://0x08与num值是否相等?
    {
    TR0=1;//打开定时器
    bbtt (22);//调用声音处理子函数,并赋值22
    num=17;// 将num值装回,使按键按下时只响一声
    }
    break;//返回
    case 12://0x00与num值是否相等?
    {
    TR0=1;//打开定时器
    bbtt (24);//调用声音处理子函数,并赋值24
    num=17;// 将num值装回,使按键按下时只响一声
    }
    break;//返回继续判断是否有键按下
/////////////////////////////////////////////////////////////////
    case 13://0x04与num值是否相等?
    {
    TR0=1;//打开定时器
    bbtt (26); //调用声音处理子函数,并赋值26
    num=17; // 将num值装回,使按键按下时只响一声
    }
    break;//返回

   }
  }
}
}

/*矩阵键盘扫描程序*/

void pan()
{
///////////////////////////////////扫第一行
  P1=0xfe;//先扫第一行
  temp=P1;//将它值给temp
  temp=temp&0xf0;//与门比较
  if(temp!=0xf0)//如果它不等于0xf0,就执行括号语句
  {
   delay(100);//延时
   temp=P1;//再赋值
   temp=temp&0xf0;//再与门比较
   if(temp!=0xf0)//再判断是否为不等于0xf0?如果确实不等则说明有键按下
   {
    temp=P1;//将值重新给temp,以便下次再判断!否则找不到合适值
    switch(temp)//判断出了第一行有键按下了,还要判断具体哪个键
    {
     case 0xee:num=0;//0xee和temp比较,如果相等就将它编码定义为0
     break;//确定了就跳出switch语句
     case 0xde:num=1;//0xde和temp比较,如果相等就将它编码定义为1
     break;//确定了就跳出switch语句
     case 0xbe:num=2;//0xbe和temp比较,如果相等就将它编码定义为2
     break;//确定了就跳出switch语句
     case 0x7e:num=3;//0x7e和temp比较,如果相等就将它编码定义为3
     break;//确定了就跳出switch语句
    }
    if(temp!=0xf0)//按键识放判断,如果不等于0xf0就一直执行括号语句
    {
     temp=P1;//重新赋值
     temp=temp&0xf0;//重新与门
    }
   }
  }
///////////////////////////////////扫第二行
P1=0xfd;
  temp=P1;
  temp=temp&0xf0;
  if(temp!=0xf0)
  {
   delay(100);
   temp=P1;
   temp=temp&0xf0;
   if(temp!=0xf0)
   {
    temp=P1;
    switch(temp)
    {
     case 0xed:num=4;
     break;
     case 0xdd:num=5;
     break;
     case 0xbd:num=6;
     break;
     case 0x7d:num=7;
     break;
    }
    if(temp!=0xf0)
    {
     temp=P1;
     temp=temp&0xf0;
    }
   }
  }
/////////////////////////////////////扫第三行
P1=0xfb;
  temp=P1;
  temp=temp&0xf0;
  if(temp!=0xf0)
  {
   delay(100);
   temp=P1;
   temp=temp&0xf0;
   if(temp!=0xf0)
   {
    temp=P1;
    switch(temp)
    {
     case 0xeb:num=8;
     break;
     case 0xdb:num=9;
     break;
     case 0xbb:num=10;
     break;
     case 0x7b:num=11;
     break;
    }
    if(temp!=0xf0)
    {
     temp=P1;
     temp=temp&0xf0;
    }
   }
  }

////////////////////////////////////////扫第四行
  P1=0xf7;
  temp=P1;
  temp=temp&0xf0;
  if(temp!=0xf0)
  {
   delay(100);
   temp=P1;
   temp=temp&0xf0;
   if(temp!=0xf0)
   {
    temp=P1;
    switch(temp)
    {
     case 0xe7:num=12;
     break;
     case 0xd7:num=13;
     break;
     case 0xb7:num=14;
     break;
     case 0x77:num=15;
     break;
    }
    if(temp!=0xf0)
    {
     temp=P1;
     temp=temp&0xf0;
    }
   }
  }
}

void delay(uchar z)//延时函数
{
uchar x,y;
for(x=100;x>0;x--)
for(y=z;y>0;y--);
}

/*扫描得到音乐代码,赋值给定时器*/
void bbtt (uchar aa)
{
numm=table[aa];//得到音乐码高位
aa++;//将计数器加1,以便取下一个代码
num1=table[aa];//得到音乐码低位
TH0=numm;//将高位赋值
TL0=num1;//将低位赋值
}

/*中断服务子程序*/
void zhong() interrupt 1
{
TH0=numm;//将高位赋值
TL0=num1;//将低位赋值
bbt=~bbt;//将蜂鸣器取反发声
}
回复

使用道具 举报

ID:64089 发表于 2015-12-28 10:00 | 显示全部楼层
嗨,楼主这么好的帖子竟然没人顶,我支持一下。
回复

使用道具 举报

ID:79544 发表于 2015-12-28 13:20 | 显示全部楼层
不知道好用不好用先顶
回复

使用道具 举报

ID:121189 发表于 2016-5-16 15:56 | 显示全部楼层
为啥没电路图
回复

使用道具 举报

ID:69481 发表于 2016-12-13 10:31 | 显示全部楼层
不错,好东西
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表