當你按計算器部分時,自動切換到計算器,按字幕滾動方式時,自動切換到字幕滾動
程序中的部分來源于他人
附件中有程序與仿真,以及51單片機開發板的程序,方便實物操作
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
無標題111.png (376.77 KB, 下載次數: 31)
下載附件
2019-12-21 18:37 上傳
無標題.png (279.88 KB, 下載次數: 35)
下載附件
2019-12-21 18:37 上傳
單片機源程序如下:
- /*
- 接盤按鍵說明:
- --------------------------------------------------
- | 7 | 8 | 9 | / |
- - - - - - - - - - - - - -
- | 4 | 5 | 6 | * |
- - - - - - - - - - - - - -
- | 1 | 2 | 3 | - |
- - - - - - - - - - - - - -
- | C | 0 | = | + |
- --------------------------------------------------*/
- //操作簡介
- // 按第一個數,再按'+-*/',再按'='顯示出結果,然后按C清屏
- // 加最大9999+9999=19998
- // 減最大9999-0 =9999
- // 乘最大9999*9999=99980001
- // 除 1/9=0.1111 保留小數點后4位
- #include<reg51.h>
- #define uint unsigned int
- #define uchar unsigned char
- //--------LCD1602-------------------
- //P00-07==== D0-7
- sbit rs=P2^6; //指令or數據
- sbit wela=P2^5; //讀or寫
- sbit lcden=P2^7; //使能信號
- //--------LCD1602-------------------
- //--------KEY-----------------------
- //P1口
- //--------KEY-----------------------
- uchar code table[]= " ";
- long int data_a,data_b; //第一個數和第二個數
- long int data_c; //計算結果
- uchar a1[16]="I love huihui"; //顯示內容
- sbit stop=P3^2 ;
- sbit sp=P3^4;
- sbit czs=P3^3;
- uchar dispaly[10]; //顯示緩沖
- /***************延遲函數*************/
- void delay(uchar z)
- {
- uchar y;
- for(z;z>0;z--)
- for(y=0;y<110;y++);
- }
- //************************************************************************/
- // 描述: 延時t us函數
- //************************************************************************/
- void LCD_Delay_us(unsigned int t)
- {
- while(t--); //t=0,退出
- }
- //************************************************************************/
- // 描述: 延時t ms函數
- //************************************************************************/
- void LCD_Delay_ms(unsigned int t)
- {
- unsigned int i,j;
- for(i=0;i<t;i++) //執行t次循環
- for(j=0;j<113;j++) //執行113次循環
- ;
- }
- //************************************************************************/
- // 描述: 1602液晶寫指令
- //************************************************************************/
- void write_com(uchar com) //1602液晶寫指令
- {
- rs=0; //寫指令
- lcden=0; //使能1602
- P0=com; //寫入指令com
- LCD_Delay_ms(1); //延時1ms
- lcden=1; //使能1602
- LCD_Delay_ms(2); //延時2ms
- lcden=0; //使能1602
- }
- //************************************************************************/
- // 描述:1602液晶寫數據
- //************************************************************************/
- void write_date(uchar date) //1602液晶寫數據
- {
- rs=1; //寫數據
- lcden=0; //使能1602
- P0=date; //寫入數據date
- LCD_Delay_ms(1); //延時1ms
- lcden=1; //使能1602
- LCD_Delay_ms(2); //延時2ms
- lcden=0; //使能1602
- }
- //************************************************************************/
- // 描述:指定x,y寫入字符函數
- //************************************************************************/
- void W_lcd(unsigned char x,unsigned char y,unsigned char Data)
- {
- if (y == 0){write_com(0x80 + x);} //第一行
- else{write_com(0xc0 + x);} //第二行
- write_date( Data); //寫入數據
- }
- //指定x,y寫入字符串函數
- void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
- {
- if (y == 0){write_com(0x80 + x);} //第一行
- else{write_com(0xC0 + x);} //第二行
- while (*s) //
- {write_date( *s); s++;} //寫入數據
- }
- //************************************************************************/
- // 描述:初始化液晶,及畫面初始化
- //************************************************************************/
- void init_lcd(void) //初始化液晶,及畫面初始化
- {
- wela=0; //寫液晶
- lcden=0; //使能1602
- write_com(0x38); //8 位總線,雙行顯示,5X7 的點陣字符
- LCD_Delay_us(100); //延時100us
- write_com(0x0c); //開顯示,無光標,光標不閃爍
- write_com(0x06); //光標右移動
- write_com(0x01); //清屏
- write_com(0x80); //DDRAM 地址歸0
- }
- //************************************************************************/
- // 描述: 反轉法鍵盤掃描
- //************************************************************************/
- short keycheckdown() /* 反轉法鍵盤掃描 */
- {
- short temp1,temp2,temp,a=0xff;
- P1=0xf0; /* 輸入行值(或列值) */
- LCD_Delay_ms(20); /* 延時 */
- temp1=P1; /* 讀列值(或行值) */
- P1=0xff;
- LCD_Delay_ms(20); /* 延時 */
- P1=0x0f; /* 輸入列值(或行值) */
- LCD_Delay_ms(20); /* 延時 */
- temp2=P1; /* 讀行值(或列值) */
- P1=0xff;
- temp=(temp1&0xf0)|(temp2&0xf); /* 將兩次讀入數據組合 */
- switch(temp) /* 通過讀入數據組合判斷按鍵位置 */
- {
- case 0x77 :a=1;break;// 按鍵+a=0x0a
- case 0x7b :a=2; break;// 按鍵= a=0x0e
- case 0x7d :a=3; break;// 按鍵0a=0
- case 0x7e :a=0x0a; break;// 按鍵CEa=0x0f
- case 0xe7 :a=0x0f;break;// 按鍵/a=0x0d
- case 0xeb :a=0;break; // 按鍵9a=0x9
- case 0xed :a=0x0e;break; // 按鍵8a=0x8
- case 0xee :a=0x0b;break; // 按鍵7a=0x7
- case 0xd7 :a=0x7;break;// 按鍵*a=0x0c
- case 0xdb :a=0x8;break; // 按鍵6a=0x6
- case 0xdd :a=0x9;break; // 按鍵5a=0x5
- case 0xde :a=0x0c;break; // 按鍵4a=0x4
- case 0xb7 :a=0x4; break;// 按鍵-a=0x0b
- case 0xbb :a=0x5;break; // 按鍵3a=3
- case 0xbd :a=0x6;break; // 按鍵2a=2
- case 0xbe :a=0x0d;break; // 按鍵1a=1
- default :a=0xff;
- }
- return a; /* 返回按鍵值 */
- }
- void display_a() //顯示數據a
- {
- dispaly[3]=data_a%10000/1000; //千
- dispaly[2]=data_a%1000/100; //百
- dispaly[1]=data_a%100/10; //十
- dispaly[0]=data_a%10; //個
- write_com(0x80+0); //顯示數據a
- if(data_a>999){ write_date('0'+dispaly[3]);} //顯示千位
- if(data_a>99){ write_date('0'+dispaly[2]);} //顯示百位
- if(data_a>9){ write_date('0'+dispaly[1]);} //顯示十位
- write_date('0'+dispaly[0]); //顯示個位
- }
- void display_b() //顯示數據b
- {
- write_com(0x80+7); //第一行
- dispaly[3]=data_b%10000/1000; //千
- dispaly[2]=data_b%1000/100; //百
- dispaly[1]=data_b%100/10; //十
- dispaly[0]=data_b%10; //個
- if(data_b>999){ write_date('0'+dispaly[3]); } //顯示千位
- if(data_b>99) { write_date('0'+dispaly[2]); } //顯示百位
- if(data_b>9) { write_date('0'+dispaly[1]); } //顯示十位
- write_date('0'+dispaly[0]); //顯示個位
- }
- //計算結果
- void display_c(x)
- {
- if(data_c<100000000&&data_c>-1)//溢出時顯示錯誤
- {
- dispaly[8]=data_c%1000000000/100000000; //萬萬
- dispaly[7]=data_c%100000000/10000000; //千萬
- dispaly[6]=data_c%10000000/1000000; //百萬
- dispaly[5]=data_c%1000000/100000; //十萬
- dispaly[4]=data_c%100000/10000; //萬
- dispaly[3]=data_c%10000/1000; //千
- dispaly[2]=data_c%1000/100; //百
- dispaly[1]=data_c%100/10; //十
- dispaly[0]=data_c%10; //個
- write_com(0x80+6+0x40); //第一行
- if(x==4)
- {
- if(data_c>99999999) { write_date('0'+dispaly[8]);} //顯示萬萬
- if(data_c>9999999) { write_date('0'+dispaly[7]);} //千萬
- if(data_c>999999) { write_date('0'+dispaly[6]);} //百萬
- if(data_c>99999) { write_date('0'+dispaly[5]);} //十萬
- if(data_b!=0) {
- write_date('0'+dispaly[4]); //萬
- write_date('.');
- write_date('0'+dispaly[3]); //千
- write_date('0'+dispaly[2]); //百
- write_date('0'+dispaly[1]); //十
- write_date('0'+dispaly[0]); //個
- }
- }
- else{
- if(data_c>99999999) { write_date('0'+dispaly[8]);} //顯示萬萬
- if(data_c>9999999) { write_date('0'+dispaly[7]);} //千萬
- if(data_c>999999) { write_date('0'+dispaly[6]);} //百萬
- if(data_c>99999) { write_date('0'+dispaly[5]);} //十萬
- if(data_c>9999) { write_date('0'+dispaly[4]);} //萬
- if(data_c>999) { write_date('0'+dispaly[3]);} //千
- if(data_c>99) { write_date('0'+dispaly[2]);} //百
- if(data_c>9) { write_date('0'+dispaly[1]);} //十
- write_date('0'+dispaly[0]); //個
- }
- }
- // else //溢出時顯示錯誤
- // {
- // write_com(0x80+11+0x40); //第一行
- // write_date('E'); //顯示 E
- // write_date('r'); //顯示R
- // write_date('r'); //顯示R
- // write_date('o'); //顯示O
- // write_date('r'); //顯示E
- // }
- }
- void eql(uchar x)//加減乘除運算
- {
- switch(x) /*功能鍵選擇*/
- {
- case 1:data_c=data_a+data_b;break; //加 /* + S=1 */ /* 數值轉換函數 */
- case 2:if(data_a>=data_b){data_c=data_a-data_b;} /* - S=2 *///減
- else{data_c=data_b-data_a;W_lcd(5,1,'-');} //負數符號
- break;
- case 3:data_c=(data_a*data_b);break; /* * S=3 *///乘
- case 4:if(data_b==0){LCD_Write_String(0,1,"Error ! ");}else{data_c=(data_a*10000)/data_b;}break; /* / S=4 *///除//溢出時顯示錯誤
- case 0:break;
- }
- }
- void main()
- {
- uchar key=0xff; //鍵值初始化
- uchar n=0; //第1個數可以按1-4次
- uchar m=5; //第2個數可以按1-4次
- uchar x=0;
- data_a=0; //前一個數
- data_b=0; //后一個數
- data_c=0; //結果
- init_lcd(); //1602液晶初始化
- display_a();
- PX0=1; // 設置外部中斷 0 為高優先級
- IT0=1;//跳變沿出發方式(下降沿)
- IT1=1;//跳變沿出發方式(下降沿)
- EX0=1; // 允許外部中斷 0 打開
- EX1=1; // 允許外部中斷 1 打開
- EA=1; // 允許總中斷控制打開
- TMOD=0x66; // 設置定時 / 計數器中斷 0,擴展為外部中斷
- TH0=0xFF;
- TL0=0xFF;
- TCON=0x50;
- ET0=1;
- while(1)
- {
- key=keycheckdown(); //動態掃描鍵盤,返回按鍵對應值,賦給j key=0到f
- if(0xff!=key) //若返回值有效,進入內部處理程序
- {
- if(key<10)
- {
- if(key==0&&n==0) ;
- else
- {
- if(n<4){data_a=data_a*10+key;m=5;display_a();}n++; //首先輸入第一個數
- }
- if(key==0&&m==0) ;
- else
- {
- if(m<4){data_b=data_b*10+key;n=5;display_b();}m++; //必須按了+-才能輸入第二個數
- }
- }
- else
- { switch(key) /*功能鍵選擇*/
- {
- case 0xa:n=5;m=0;x=1;W_lcd(5,0,'+');break; //加 /* + S=1 */ /* 數值轉換函數 */
- case 0xb:n=5;m=0;x=2;W_lcd(5,0,'-');break; /* - S=2 *///減
- case 0xc:n=5;m=0;x=3;W_lcd(5,0,'*');break; /* * S=3 *///乘
- case 0xd:n=5;m=0;x=4;W_lcd(5,0,'/');break; /* / S=4 *///除
- case 0xe:n=5;m=5;eql(x);W_lcd(12,0,'=');display_c(x);break; /* = */
- case 0xf:n=0;x=0;m=5; data_a=0;data_b=0;data_c=0;LCD_Write_String(0,0,table);LCD_Write_String(0,1,table);W_lcd(0,0,'0');break; /* C*/
- }
- }
- do{P1=0xf0;}while(P1!=0xf0); /*等待按鍵松開*/
- }//(0xff!=key)
- }//while
- }//main
- void cshjs() //計算器初始化
- {
- uchar key=0xff; //鍵值初始化
- uchar n=0; //第1個數可以按1-4次
- uchar m=5; //第2個數可以按1-4次
- uchar x=0;
- data_a=0; //前一個數
- data_b=0; //后一個數
- data_c=0; //結果
- init_lcd(); //1602液晶初始化
- }
- /*lcd滾動字幕控制程序部分*/
- /***************字幕水平滾動*************/
- void sp1()
- {
- uint i,a;
- write_com(0x00+0x80);
- for(i=0;i<16;i++)
- {
- write_date(a1[i]);
- }
- while(1){write_com(0x1c);
- a=keycheckdown();
- if((czs==0)||(a!=0xff)){cshjs();break;}
- delay(200);}
- }
- /***************字幕垂直向上滾動*************/
- void cz()
- {
- uint i,a;
- write_com(0x01);
- write_com(0x80+0x00);
- for(i=0;i<16;i++)
- {
- write_date(a1[i]);
- a=keycheckdown();
- if((sp==0)||(a!=0xff)){cshjs();break;}
- }
- delay(8);
- write_com(0x01);
- write_com(0x80+0x40);
- for(i=0;i<16;i++)
- {
- write_date(a1[i]);
- a=keycheckdown();
- if((sp==0)||(a!=0xff)){cshjs();break;}
- }
- delay(8);
- }
- /***************外部中斷 0,實現暫停P3^2口*************/
- void int0()interrupt 0 // 外部中斷 0,實現暫停
- {
- EA=0; //關中斷
- delay(10);
- while(!stop);
- EA=1;//開中斷
- }
- /***************外部中斷 1,實現垂直移動P3^3口*************/
- void int1()interrupt 2
- {
- int a;
- init_lcd();
- while(1)
- {
- cz();
- a=keycheckdown();
- if((sp==0)||(a!=0xff)){cshjs();break;}
- }
- }
- /*************** 定時 / 計數器中斷擴展為外部中斷,實現水平移動P3^4口*************/
- void kt0()interrupt 1
- {
- init_lcd();
- sp1();
- }
復制代碼
所有資料51hei提供下載:
字幕滾動加計算器.zip
(293.38 KB, 下載次數: 50)
2019-12-21 18:38 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|