标题:
单片机电子贺卡源程序与Proteus仿真原理图
[打印本页]
作者:
sisisididfidi
时间:
2023-7-3 15:24
标题:
单片机电子贺卡源程序与Proteus仿真原理图
电子贺卡仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
51hei.gif
(127.53 KB, 下载次数: 25)
下载附件
2023-7-3 16:19 上传
单片机电子贺卡源程序如下:
#include<reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit SPEAK=P2^7; //定义蜂鸣器输出端口
sbit CS1=P2^4;
sbit CS2=P2^3;
sbit RS=P2^2;
sbit RW=P2^1;
sbit E=P2^0;
sbit L1=P1^0;
sbit L2=P1^1;
uchar code HZ0[]={
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
.................
...............
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
void delayus(uchar delay)
{
uchar i;
for(i=0;i<=delay;i++)
_nop_();
}
void check_busy()
{
uchar a=0;
for(a=0;a<200;a++); //此处为延时,一段时间后确保处于空闲状态
//此处为状态查询,查询忙状态,没有使用成功,以后再调试
/*RW=1;
RS=0;
E=1;
while(1)
{
E=1;
if(!(P0&0x80))
break;
a++;
if(a>10)
break;
}
E=1;*/
}
void write_cmd(uchar inst)
{
check_busy();
RS=0;
RW=0;
E=1;
P3=inst;
E=0;
_nop_();
}
void write_data(uchar dat)
{
check_busy();
RS=1;
RW=0;
E=1;
P3=dat;
E=0;
_nop_();
}
void LCD_Init()
{
write_cmd(0x30);//30H--基本指令操作?
delayus(4);
write_cmd(0x0c);//开显示,关光标,不闪烁。
delayus(10);
write_cmd(0x01);//清除显示
delayus(10);
write_cmd(0x06);//光标的移动方向左,DDRAM的地址计数器(AC)加1。
delayus(10);
}
void set_xy(uchar x,uchar y) //x为行,y为列
{
if(y>=64) //列地址大于等于64时右屏显示?
{
CS2=0; //低电平选择
CS1=1; //写右屏是左屏关闭,不然两边会同时显示
y=y-64;
}
else //列地址小于64时左屏显示
{
CS1=0; //同上
CS2=1;
}
write_cmd(0x40|y); //写列地址
_nop_();
write_cmd(0xb8|x); //写行地址?
}
//显示函数
void disp_hz(uchar *p)
{
uchar i;
for(i=0;i<128;i++)
{
set_xy(0,i);
write_data(p[i]);
set_xy(1,i);
write_data(p[i+128]);
set_xy(2,i);
write_data(p[i+256]);
set_xy(3,i);
write_data(p[i+384]);
set_xy(4,i);
write_data(p[i+512]);
set_xy(5,i);
write_data(p[i+640]);
set_xy(6,i);
write_data(p[i+768]);
set_xy(7,i);
write_data(p[i+896]);
set_xy(8,i);
write_data(p[i+1024]);
}
}
void disp_zf(uchar R,uchar L,uchar *p)
{
uchar i;
for(i=0;i<8;i++)
{
set_xy(2*R,8*L+i);
write_data(p[i]);
set_xy(2*R+1,8*L+i);
write_data(p[i+8]);
}
}
uchar beat,tl,th,key=0,k=0,temp; //定义节拍和T0初值变量
uchar code TABLE[]={ //音符对应的定时器初值表
0xfb,0x04,0xfb,0x90,0xfc,0x09,0xfc,0x44,
0xfc,0xac,0xfd,0x09,0xfd,0x34,0xfd,0x82,
0xfd,0xc8,0xfe,0x06,0xfe,0x22,0xfe,0x56,
0xfe,0x85,0xfe,0x9a,0xfe,0xc1};
uchar code GRACE[]={ //《奇异恩典》音符码表
0x14,0x48,0x62,0x42,0x68,0x54,0x48,0x24,0x18,
0x14,0x48,0x62,0x42,0x68,0x54,0x8c,0x88,
0x64,0x86,0x62,0x82,0x62,0x48,0x14,0x26,0x42,0x42,0x22,0x18,
0x14,0x48,0x62,0x42,0x68,0x54,0x4c,0x48,0x00};
uchar code JOY[]={ //《欢乐颂》音符码表
0x64,0x64,0x74,0x84,0x84,0x74,0x64,0x54,
0x44,0x44,0x54,0x64,0x66,0x52,0x58,0x64,
0x64,0x74,0x84,0x84,0x74,0x64,0x54,0x44,
0x44,0x54,0x64,0x56,0x42,0x48,0x54,0x54,
0x64,0x44,0x54,0x62,0x72,0x64,0x44,0x54,
0x62,0x72,0x64,0x54,0x44,0x54,0x18,0x64,
0x64,0x74,0x84,0x84,0x74,0x64,0x54,0x44,
0x44,0x54,0x64,0x56, 0x42,0x48,0x00};
uchar code HAPPY[]={ //《生日快乐》音符码表
0x82,0x01,0x81,0x94,0x84,0xB4,0xA4,0x04,
0x82,0x01,0x81,0x94,0x84,0xC4,0xB4,0x04,
0x82,0x01,0x81,0xF4,0xD4,0xB4,0xA4,0x94,
0xE2,0x01,0xE1,0xD4,0xB4,0xC4,0xB4,0x04,
0x82,0x01,0x81,0x94,0x84,0xB4,0xA4,0x04,
0x82,0x01,0x81,0x94,0x84,0xC4,0xB4,0x04,
0x82,0x01,0x81,0xF4,0xD4,0xB4,0xA4,0x94,
0xE2,0x01,0xE1,0xD4,0xB4,0xC4,0xB4,0x04,
0x00};
void Timer0_Initialize();
void delay_10ms();
void Delay(uchar);
void Key_Scan();
uint a[4]={0,1,2,3};
void main()
{
uchar m,m1; //定义临时变量
uchar *p[3];
uchar beat=0;
p[0]=GRACE;
p[1]=JOY;
p[2]=HAPPY;
Timer0_Initialize();
while(1)
{
Key_Scan();
if(key!=3)
TR0=1;
switch(key)
{
P1=0xff;
case 0:
disp_hz(HZ0 );
temp=key;
TR0=1;
while(*(p[key]+k)!=0) //判断取得的音符码是否为结束码
{
beat=*(p[key]+k)&0x0f; //取节拍码
m=_crol_(*(p[key]+k),4)&0x0f; //取音调码
if(beat!=0)
{ //判断取得的音调码是否为0 { //不是,根据取得的音调码计算T0初值
m1=--m*2+1;
m=m*2;
tl=TL0=TABLE[m1];
th=TH0=TABLE[m];
}
else
{ //取得的节拍码为0,则停止T0
TR0=0;
}
Delay(beat);
k++;
Key_Scan();
delay_10ms();
if(temp!=key)break;
}
TR0=0;
k=0;
break;
case 1:
disp_hz(HZ1 );
temp=key;
TR0=1;
while(*(p[key]+k)!=0) //判断取得的音符码是否为结束码
{
beat=*(p[key]+k)&0x0f; //取节拍码
m=_crol_(*(p[key]+k),4)&0x0f; //取音调码
if(beat!=0)
{ //判断取得的音调码是否为0 { //不是,根据取得的音调码计算T0初值
m1=--m*2+1;
m=m*2;
tl=TL0=TABLE[m1];
th=TH0=TABLE[m];
}
else
{ //取得的节拍码为0,则停止T0
TR0=0;
}
Delay(beat);
k++;
Key_Scan();
delay_10ms();
if(temp!=key)break;
}
TR0=0;
k=0;
break;
case 2:
disp_hz(HZ2 );
temp=key;
TR0=1;
while(*(p[key]+k)!=0) //判断取得的音符码是否为结束码
{
beat=*(p[key]+k)&0x0f; //取节拍码
m=_crol_(*(p[key]+k),4)&0x0f; //取音调码
if(beat!=0)
{ //判断取得的音调码是否为0 { //不是,根据取得的音调码计算T0初值
m1=--m*2+1;
m=m*2;
tl=TL0=TABLE[m1];
th=TH0=TABLE[m];
}
else
{ //取得的节拍码为0,则停止T0
TR0=0;
}
Delay(beat);
k++;
Key_Scan();
delay_10ms();
if(temp!=key)break;
}
TR0=0;
k=0;
break;
case 3:
TR0=0;break;
}
}
}
void Timer0_Initialize()
{
EA=1;
ET0=1;
TMOD=0x01;
TR0=1;
}
void timer0() interrupt 1 using 1
{
TL0=tl;
TH0=th; //重装定时初值
SPEAK=~SPEAK;
} //蜂鸣器控制端口电平取反 } /************************ 四分之一拍延时函数 ************************/
void Delay_Beat()
{
uint i;
for(i=0;i<20000;i++);
}
void Delay(uchar tt)
{
uchar i;
for(i=0;i<tt;i++)
Delay_Beat();
}
void delay_10ms()
{
int i;
for(i=0;i<200;i++);
}
void Key_Scan()
{
uchar i,temp1;
P1=0xfb;
for(i=0;i<=1;i++)
{
if(L1==0)
{
if(i==0)
key=a[i];
else
key=a[i+1];
}
if(L2==0)
{
if(i==0)
key=a[i+1];
else
key=a[i+2];
}
delay_10ms();
temp1=P1;
temp1=temp1|0x03;
temp1=temp1<<1;
temp1=temp1|0x03;
P1=temp1;
}
}
复制代码
Keil代码与Proteus仿真下载:
仿真和程序.7z
(108.6 KB, 下载次数: 22)
2023-7-3 16:20 上传
点击文件名下载附件
下载积分: 黑币 -5
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1