标题:
51单片机实现音阶(可调高低音)Proteus仿真代码
[打印本页]
作者:
Cf13655859831
时间:
2021-4-11 21:13
标题:
51单片机实现音阶(可调高低音)Proteus仿真代码
51单片机实现音阶,可放歌曲
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
51hei.png
(30.98 KB, 下载次数: 56)
下载附件
2021-4-11 21:19 上传
单片机源程序如下:
#include<reg52.h>
#include<intrins.h>
#define keyport P1
#define out P0
#define uchar unsigned char
#define uint unsigned int
uchar high,low; //定时器预装值的高8位和低8位
sbit S1 =P1^0; // 按键
uchar keyvalue; // 键值
uchar code name[] ="Chen xin chen";//显示名字
uchar code stu_num[] =" 1111120028";//显示学号
sbit RS = P2^0; // 数据或指令控制线
sbit RW = P2^1; // 读写控制线
sbit E = P2^2; //使能控制线
/*********************
延时函数
*********************/
void delay(uint j)
{
uchar i = 250;
for(;j>0;j--)
{
while (--i);
i= 249;
while(--i);
i=250;
}
}
/*********************
检查忙函数,检查LCD是否处于忙状态
如果处于忙则持续检查
*********************/
void check_busy(void)
{
uchar temp;
do{
temp =0xff; //
E = 0;
RS= 0; //
RW = 1;
E =1;
temp = out; //
}while(temp&0x80); // 如果 BF =1 则持续检查
E = 0;
}
/*********************
写命令函数
*********************/
void write_command(uchar com)
{
check_busy();// 首先检查忙
E= 0;//预置0
RS =0;
RW =0; //按LCD写命令控制信号设置
out = com;
E =1; // 正脉冲
_nop_();//
E = 0; // 还原E
delay(1);
}
/********************
写数据函数
********************/
void write_data(uchar com)
{
check_busy();
E=0; //预置0
RS= 1;
RW =0;//按LCD写数据控制信号设置
out = com;
E=1;// 正脉冲
_nop_();
E =0;
delay(1);
}
/********************
LCD初始化函数
********************/
void lcd_initial(void) //
{
write_command(0x38); // 八位数据,双列显示,5X7阵
_nop_();
write_command(0x0c); //开显示屏,关光标,光标不显示
_nop_();
write_command(0x06); //字符不移动,每次字符地址加1
_nop_();
write_command(0x01); //清屏
_nop_();
delay(100);
}
/********************
//字符串显函数
********************/
void string(uchar add, uchar *s) reentrant
{
write_command(add);//显示地址
while(*s != '\0')
{
write_data(*s++);
}
}
void interrupt_int(void)
{
EA =1;//总中断允许
EX0 =1;//外部中断打开
EX1 =1;//
IT0=1;//负跳变
IT1 =1;//
IP =0;//同一优先级
}
void key_1(void) interrupt 0
{
EX0 =0;
lcd_initial();
string(0x83,name); //第一行第四个开始显示学号
string(0xc2,stu_num);//第二行第三个开始显示姓名
EX0 =1;//开启中断
}
sbit speak=P3^0;
sbit gao=P3^5;
sbit di=P3^6;
sbit zdbf=P3^7;
uchar yinjie=1;
uchar time;
uchar n=0;
uchar bo=0;
uchar code fre[][2]= { 0x8c,0xf8,0x5b,0xf9,0x15,0xfa,0x67,0xfa,0x90,0xfb,0xae,0xfb,0x0c,0xfc, //低音
0x44,0xfc,0xac,0xfc,0x09,0xfd,0x34,0xfd,0x82,0xfd,0xc2,0xfd,0x06,0xfe, //中音
0x22,0xfe,0x56,0xfe,0x85,0xfe,0x9a,0xfe,0xc1,0xfe,0xe4,0xfe,0x03,0xff, //高音
};
void delay(uint );
void ITimer0(void);//定时器初始化
void key(void);
void dtxs(int,int);
void song()
{
TH0=high;
TL0=low;
TR0=1;
delay(time*240);
}
void yinyue()//小星星歌曲
{
uchar code hls[]={ 1,2,2, 1,2,3, 5,2,2, 5,2,3, 6,2,2, 6,2,3, 5,2,4, 4,2,2, 4,2,3, 3,2,2 ,3,2,3 ,2,2,2, 2,2,3, 1,2,4, 5,2,2, 5,2,3, 4,2,2, 4,2,3, 3,2,2, 3,2,3, 2,2,4, 5,2,2, 5,2,3, 4,2,2, 4,2,3, 3,2,2, 3,2,3, 2,2,4};
uchar m;
n=0;
while(n<174)
{
m=hls[n]+7*(hls[n+1]-1)-1;
high=fre[m][1];
low=fre[m][0];
time=hls[n+2];
n=n+3;
song();
}
}
void main (void)
{
uchar num;
ITimer0();
speak=0;
interrupt_int();
while(1)
{
key();
switch(keyport)
{
case 0xfe:num=1;break;
case 0xfd:num=2;break;
case 0xfb:num= 3;break;
case 0xf7:num= 4;break;
case 0xef:num= 5;break;
case 0xdf:num= 6;break;
case 0xbf:num= 7;break;
case 0x7f:num= 8;break;
default:num= 0;break;
}
if(num==0)
{
TR0=0;
speak=0;
}
else
{
high=fre[7*yinjie+num-1][1];
low=fre[7*yinjie+num-1][0];
TR0=1;
}
dtxs(yinjie,num);
}
}
void ITimer0(void)
{
TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
EA=1; //总中断打开
ET0=1; //定时器中断打开
TR0=1; //定时器开关打开
}
void Timer0_isr(void) interrupt 1
{
TH0=high;
TL0=low;
speak=!speak;
if(zdbf==0)
{
delay(100);
if(zdbf==0)
{
bo++;
if(bo/2==1)
{ delay(100);
if(n<174)n=500; //n赋值大于174,跳出while,停止音乐
else n=0;
dtxs(3,0);
}
if(bo%2==0)
{ delay(100);
n=500; //n赋值大于174,跳出while,停止音乐
}
}
}/**/
}
void key()//按键
{
if(zdbf==0)
{delay(100);
if(zdbf==0)
yinyue();
}
if(gao==0)
{
delay(100);
if(gao==0)
{
delay(100);
if(yinjie==2)
yinjie=1;
else yinjie=2;
}
}
if(di==0)
{
delay(100);
if(di==0)
{
delay(100);
if(yinjie==0)
yinjie=1;
else yinjie=0;
}
}
}
void dtxs(k,l)//k是按键号,l是工作方式
{
char seg[14]={ 0x3F,/*0*/
0x06,/*1*/
0x5B,/*2*/
0x4F,/*3*/
0x66,/*4*/
0x6D,/*5*/
0x7D,/*6*/
0x07,/*7*/
0x7F,/*8*/
0x6F,/*9*/
0x37,/*N*/
0x38,/*L*/
0x76,/*H*/
0x79
};
P2=0x01;//选择第一个数码管
P0=seg[l];//显示按键号
delay(4);
P2=0x02;//选择第二个数码管
P0=seg[k+10];//显示工作方式
delay(4);
}
复制代码
所有资料51hei提供下载:
仿真.7z
(100.06 KB, 下载次数: 23)
2021-4-11 22:45 上传
点击文件名下载附件
下载积分: 黑币 -5
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1