電子賀卡仿真原理圖如下(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
|