1、定時(shí)顯示
開辟一顯示緩沖區(qū),顯示中斷程序定時(shí)讀取緩沖區(qū)顯示各燈位,每燈位顯示2.5ms,顯示4只燈需要10ms,也就是顯示的刷新頻率是100Hz,亮度為25%。這樣既保證亮度又不閃爍,同時(shí)CPU還有足夠時(shí)間做其他事情。
2、鍵盤中斷掃描
利用鍵盤中斷掃描程序,讀出按鍵的鍵碼,存入鍵盤緩沖區(qū),供主程序讀區(qū)。
3、計(jì)算器的主程序讀取鍵盤緩沖區(qū)的鍵碼,驅(qū)動(dòng)計(jì)算器的運(yùn)行,計(jì)算器的運(yùn)行過程要清晰明了;
4、計(jì)算中需要十進(jìn)制與十六進(jìn)制(或二進(jìn)制)轉(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}; //當(dāng)前燈位、 顯示區(qū)
unsigned char key_buffer[2]={0,0xff}; //緩沖區(qū)滿標(biāo)志、鍵碼
void main()
{
Unsigned char temp[5];
unsigned char i;
unsigned char operator=0;
unsigned int tempa,tempb;
bit first=1;
TMOD=0x01; //置T0為方式1
TL0=0x0; //延時(shí)2.5mS的定時(shí)器初始值
TH0=0xf7; //賦初值
PT0=1; //定時(shí)中斷0優(yōu)先設(shè)置
TR0=1; //啟動(dòng)定時(shí)
ET0=1; //允許定時(shí)
IT1=0; //電平觸發(fā)低電平有效
EX1=1; //允許外中斷
PX1=1; // 外部中斷1優(yōu)先級(jí)設(shè)定
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ù),等待另一個(gè)數(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; //延時(shí)2.5mS的定時(shí)器初始值
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); //延時(shí)5-10ms,去抖動(dòng)
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) //延時(shí)k*1ms
{
unsigned int i,j;
for (j=0;j<=k;j++)
for(i=0;i<=1085;i++);
}

