16鍵計算器用c51實現(xiàn)
1、定時顯示
開辟一顯示緩沖區(qū),顯示中斷程序定時讀取緩沖區(qū)顯示各燈位,每燈位顯示2.5ms,顯示4只燈需要10ms,也就是顯示的刷新頻率是100Hz,亮度為25%。這樣既保證亮度又不閃爍,同時CPU還有足夠時間做其他事情。
2、鍵盤中斷掃描
利用鍵盤中斷掃描程序,讀出按鍵的鍵碼,存入鍵盤緩沖區(qū),供主程序讀區(qū)。
3、計算器的主程序讀取鍵盤緩沖區(qū)的鍵碼,驅(qū)動計算器的運行,計算器的運行過程要清晰明了;
4、計算中需要十進制與十六進制(或二進制)轉(zhuǎn)化。
#define LED_seg XBYTE[0x6000] //段碼地址#define LED_light XBYTE[0x8000] //燈位地址#include "reg51.h"#include "absacc.h"unsigned char read_key(unsigned char);unsigned char display(unsigned char,unsigned char);void delay(unsigned int);unsigned char light[4]={0xfe,0xfd,0xfb,0xf7}; //掃描值 燈位碼unsigned char seg[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //段碼unsigned char disp_buffer[5]={1,0,0,0,0}; //當前燈位、 顯示區(qū)unsigned char key_buffer[2]={0,0xff}; //緩沖區(qū)滿標志、鍵碼void main(){Unsigned char temp[5];unsigned char i;unsigned char operator=0;unsigned int tempa,tempb;bit first=1;TMOD=0x01; //置T0為方式1TL0=0x0; //延時2.5mS的定時器初始值TH0=0xf7; //賦初值PT0=1; //定時中斷0優(yōu)先設置TR0=1; //啟動定時ET0=1; //允許定時IT1=0; //電平觸發(fā)低電平有效EX1=1; //允許外中斷PX1=1; // 外部中斷1優(yōu)先級設定EA=1; //中斷總允許while(1){P1=0xf0; //掃描if (key_buffer[0]){switch(key_buffer[1]) //緩沖區(qū)滿{case 0:case 1:case 2:case 3:case 4:case 5:case 6:case 7:case 8:case 9: if (first) for(i=1;i=4;i++) //保存數(shù)據(jù),等待另一個數(shù)據(jù)輸入{temp[i]=disp_buffer[i];disp_buffer[i]=0; }first=0;for(i=1;i=3;i++) disp_buffer[i]=disp_buffer[i+1];disp_buffer[4]=key_buffer[1];break;case 10:case 11:case 12:case 13:case 14: first=1;
tempa=1000*disp_buffer[1]+100*disp_buffer[2]+10*disp_buffer[3]+disp_buffer[4];tempb=1000*temp[1]+100*temp[2]+10*temp[3]+temp[4];switch(operator){case 10:tempa+=tempb;break;case 11:tempa=tempb-tempa;break;case 12:tempa*=tempb;break;case 13:tempa=tempb/tempa;}tempa%=10000;disp_buffer[1]=tempa/1000;tempa%=1000;disp_buffer[2]=tempa/100;tempa%=100;disp_buffer[3]=tempa/10;disp_buffer[4]=tempa%10;operator=key_buffer[1];break;case 15: for(i=1;i=4;i++) disp_buffer[i]=temp[i]=0;first=1;operator=0;}key_buffer[0]=0; //緩沖區(qū)空} }}void disp_LED() interrupt 1{TL0=0x0; //延時2.5mS的定時器初始值TH0=0xf7;if (disp_buffer[0]==5) disp_buffer[0]=1;display(disp_buffer[disp_buffer[0]],disp_buffer[0]);disp_buffer[0]++;}void get_keypad_code() interrupt 2{unsigned char i,key;EA=0;for (i=0;i=3;i++){key=read_key(light[i]); //讀鍵碼if (key!=0xff) delay(10); //延時5-10ms,去抖動if (read_key(light[i])!=key) key=0xff; //讀鍵碼比較if (key!=0xff){key_buffer[0]=1; //緩沖區(qū)滿key_buffer[1]=key; //鍵碼} }EA=1;}unsigned char read_key(unsigned char scan){P1=scan; //掃描switch(P1) //返回掃描碼->鍵碼{case 0x77:return(0x7);case 0xb7:return(0x8);case 0xd7:return(0x9);case 0xe7:return(0xd);case 0x7b:return(0x4);case 0xbb:return(0x5);case 0xdb:return(0x6);case 0xeb:return(0xc);case 0x7d:return(0x1);case 0xbd:return(0x2);case 0xdd:return(0x3);case 0xed:return(0xb);case 0x7e:return(0xf);case 0xbe:return(0x0);case 0xde:return(0xe);case 0xee:return(0xa);default: return(0xff);}}unsigned char display(unsigned char disp_key,unsigned char n) //disp_key 顯示字符,n 燈位{if ((n=4)(n>=1)) LED_light=light[n-1];else LED_light=0xff;if ((disp_key>=0)(disp_key=16)) LED_seg=seg[disp_key];else LED_seg=0x00;return light[n-1];}void delay(unsigned int k) //延時k*1ms{unsigned int i,j;for (j=0;j=k;j++)for(i=0;i=1085;i++);}
評論