|
/*加法器
一1先取鍵值(去抖動在中斷,數(shù)碼管顯示在中斷(讀取緩存器))
二鍵值的處理在主函數(shù)
三處理的結(jié)果十六進(jìn)制轉(zhuǎn)十進(jìn)制,并存入緩存器*/
#include <reg52.h>
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
sbit keyin1 = P2^4;
sbit keyin2 = P2^5;
sbit keyin3 = P2^6;
sbit keyin4 = P2^7;
sbit keyout1 = P2^3;
sbit keyout2 = P2^2;
sbit keyout3 = P2^1;
sbit keyout4 = P2^0;
unsigned char code ledchar[]={0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E};
unsigned char ledbuf[6]={0xff,0xff,0xff,0xff,0xff,0xff}; //16進(jìn)制轉(zhuǎn)10金之后的計算后的結(jié)果送入這個緩存器 P0直接讀取這個用于顯示
/*矩陣按鍵到標(biāo)準(zhǔn)鍵盤的映射變 ASCLL表查詢可知*/
unsigned char code keycodemap[4][4]={
{0x31,0x32,0x33,0x26}, //1 2 3 向上
{0x34,0x35,0x36,0x25}, //4 5 6 向左
{0x37,0x38,0x39,0x28}, //7 8 9 向下
{0x30,0x1B,0x0D,0x27}, //0 ESC 回車 向右
};
unsigned char keystate[4][4]={{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}}; //16個按鍵的當(dāng)前鍵值 1代表的是這個按鍵是按下還是松開 最好用BIT 但是數(shù)組不允許
void keydrive();
void keyaction(unsigned char keycode);
void shownumber(unsigned long number);
void keydrive();
void ledscan(); //數(shù)碼管顯示函數(shù)
void keyscan(); //按鍵掃描函數(shù)
void main()
{
TMOD=0x01; //用定時器T0模式1
TH0=0XFC; //定時以為時間12/11059200,需要定時0.001S 需要
TL0=0X66;
EA=1;
ET0=1;
TR0=1;
ADDR3=1;
ENLED=0;
ledbuf[0]=ledchar[0];
/*按鍵當(dāng)前狀態(tài)刷出來后 取鍵值 */
while(1)
{
keydrive();
}
}
void shownumber(unsigned long num)
{
signed char i; /這里為什么不能用 unsigned char
unsigned char buf[6]; //待顯示的數(shù)字
for(i=0;i<6;i++) //將數(shù)取出來放入數(shù)組
{
buf[i]=num%10;
num=num/10;
}
for(i=5;i>=1;i--)
{
if(buf[i]==0x00) //從最高位起,遇到0轉(zhuǎn)換為空格,遇到非0則退出循環(huán)
{
ledbuf[i]=0xff;
}
else
{
break;
}
} //剩余低位都如實轉(zhuǎn)換為數(shù)碼管顯示字符
for(;i>=0;i--)
{
ledbuf[i]=ledchar[buf[i]];
}
}
void keyaction(unsigned char keycode)
{
static unsigned long addend=0; //中間值
static unsigned long result=0; //結(jié)果值
if((keycode>=0x30)&&(keycode<=0x39)) {addend=((addend*10)+(keycode-0x30));shownumber(addend);}
else if(keycode == 0x26) {result=(addend+result);addend=0; shownumber(result);} // +
else if(keycode == 0x0D) {result=(addend+result);addend=0; shownumber(result);} //回車
else if(keycode == 0x1B) {result=0;addend=0; shownumber(addend);} //ESC
}
/*將按鍵(根據(jù)位置)取出來的值,根據(jù)映射表提取值,并且進(jìn)行運算*/
void keydrive()
{
unsigned char i,j;
static unsigned char backup[4][4]={{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}}; //16個按鍵的上一個狀態(tài)
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
if( keystate[i][j]!=backup[i][j]) //按鍵有動作
{
if(backup[i][j]!=0) //按鍵處于松開狀態(tài)
{
keyaction(keycodemap[i][j]);
}
backup[i][j]=keystate[i][j];
}
}
}
}
void ledscan() //數(shù)碼管掃描函數(shù)
{
static unsigned char i=0;
/*下面用處數(shù)碼管的顯示,讀取緩存ledbuf的值*/
P0=0xff; //消影
switch(i) //進(jìn)一次中斷刷新一位
{
case 0: ADDR0=0; ADDR1=0; ADDR2=0; P0=ledbuf[0];i++;break;
case 1: ADDR0=1; ADDR1=0; ADDR2=0; P0=ledbuf[1];i++;break;
case 2: ADDR0=0; ADDR1=1; ADDR2=0; P0=ledbuf[2];i++;break;
case 3: ADDR0=1; ADDR1=1; ADDR2=0; P0=ledbuf[3];i++;break;
case 4: ADDR0=0; ADDR1=0; ADDR2=1; P0=ledbuf[4];i++;break;
case 5: ADDR0=1; ADDR1=0; ADDR2=1; P0=ledbuf[5];i=0;break;
default: break;
}
}
void keyscan() //按鍵掃描函數(shù)
{
unsigned char i;
static unsigned char keyout=0 ; //行索引
static unsigned char keytemp[4][4]={{0xff,0xff,0xff,0xff},{0xff,0xff,0xff,0xff},{0xff,0xff,0xff,0xff},{0xff,0xff,0xff,0xff}};
keytemp[keyout][0]=(keytemp[keyout][0]<<1)|keyin1; //掃完16個按鍵的第一位需要4MS 掃完8位需要32MS
keytemp[keyout][1]=(keytemp[keyout][1]<<1)|keyin2; //一個按鍵每隔4MS掃一次
keytemp[keyout][2]=(keytemp[keyout][2]<<1)|keyin3; // 8個狀態(tài)是32MS之間的穩(wěn)態(tài)值
keytemp[keyout][3]=(keytemp[keyout][3]<<1)|keyin4; //每進(jìn)中斷一次(1MS)掃描一行
for(i=0;i<4;i++)
{
if(( keytemp[keyout][i]&0x0f) == 0x00 ) {keystate[keyout][i]=0;}
else if( ( keytemp[keyout][i]&0x0f) == 0x0f ) {keystate[keyout][i]=1;} //掃描結(jié)果的賦值
}
keyout++; //下一次掃描下一行
keyout=keyout&0x03; //逢三復(fù)位
/*讀取列值 行首先要置位0 為什么把置位放在后面 ? 1如果放在中斷掃描前
馬上就能掃描 而行的置位是需要一定時間的,就會導(dǎo)致列值不準(zhǔn)確 2 如果放在后面
其實是給下一次行掃描的置位,經(jīng)過了主程序的延遲 ,置位完成,程序才足夠強壯*/
switch(keyout)
{
case 0: keyout4=1; keyout1=0; break;
case 1: keyout1=1; keyout2=0; break;
case 2: keyout2=1; keyout3=0; break;
case 3: keyout3=1; keyout4=0; break;
default: break;
}
}
void time0() interrupt 1 //中斷中 行要置位0
{
TH0=0XFC; //定時以為時間12/11059200,需要定時0.001S 需要
TL0=0X66;
ledscan();
keyscan();
}
|
|