使用扫描按键和数码管实现连+和连-
本次程序有一点点复杂,但是基于我对本次程序的理解。主要使用函数完成按键的扫描,消抖,数码管的扫描,消影。程序主体部分就是按键驱动函数,通过调用按键驱动函数检测按键状态,然后将按键对应的映射表显示到数码管上,进而进行加法或减法运算。
#include<reg52.h>
sbit ADDR0 = P2^0;
sbit ADDR1 = P2^1;
sbit ADDR2 = P2^2;
sbit ENLED = P1^1;
sbit KEY_IN_1 = P2^0;
sbit KEY_IN_2 = P2^1;
sbit KEY_IN_3 = P2^2;
sbit KEY_IN_4 = P2^3;
sbit KEY_OUT_4= P2^4;
sbit KEY_OUT_3 = P2^5;
sbit KEY_OUT_2 = P2^6;
sbit KEY_OUT_1 = P2^7;
unsigned char code LedChar[] = {
0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, //数码管转换表
0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
};
unsigned char LedBuff[6] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF //用于数码管的消除鬼影
};
unsigned char code KeyCodeMap[4][4] = { //按键映射键盘表
{ 0x31, 0x32, 0x33, 0x26 },
{ 0x34, 0x35, 0x36, 0x25 },
{ 0x37, 0x38, 0x39, 0x28 },
{ 0x30, 0x1B, 0x0D, 0x27 }
};
unsigned char KeySta[4][4] = { //按键扫描当前值
{1,1,1,1}, {1,1,1,1}, {1,1,1,1}, {1,1,1,1}
};
void KeyDriver();
void main()
{
EA = 1;
ENLED = 0;
TMOD = 0x01;
TH0 = 0xF5;
TL0 = 0x55;
TR0 = 1;
ET0 = 1;
LedBuff[0] = LedChar[0];
while(1)
{
KeyDriver(); //主函数用于现实输入和输出
}
}
void ShowNumber(unsigned long num) //用于显示输入和输出数字,并且弥补了高位自动消除0.
{
signed char i;
unsigned char buf[6];
for(i=0;i<6;i++)
{
buf = num % 10;
num = num/10;
}
for(i=5;i>=1;i--)
{
if(buf == 0)
LedBuff = 0xFF;
else
break;
}
for(; i>=0;i--)
{
LedBuff = LedChar[buf];
}
}
void KeyAction(unsigned char keycode) //运算函数
{
static unsigned long result = 0;
static unsigned long addend = 0;
if((keycode>=0x30)&&(keycode<=0x39))
{
addend = (addend*10) + (keycode-0x30);
ShowNumber(addend);
}
else if(keycode == 0x26)
{
result += addend;
addend = 0;
ShowNumber(result);
}
else if(keycode == 0x0D)
{
result += addend;
addend = 0;
ShowNumber(result);
}
else if(keycode == 0x1B)
{
addend = 0;
result = 0;
ShowNumber(addend);
}
}
void KeyDriver()
{
unsigned char i,j;
static unsigned char backup[4][4] = { //按键扫描消抖函数,16ms扫描所有按键
{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1}
};
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
if(backup[j]!= KeySta[j])
{
if(backup[j]!= 0)
{
KeyAction(KeyCodeMap[j]);
}
backup[j] = KeySta[j];
}
}
}
}
void KeyScan()
{
unsigned char i;
static unsigned char keyout = 0;
static unsigned char keybuf[4][4] = {
{0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF},
{0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}
};
keybuf[keyout][0] = (keybuf[keyout][0] << 1) | KEY_IN_1;
keybuf[keyout][1] = (keybuf[keyout][1] << 1) | KEY_IN_2;
keybuf[keyout][2] = (keybuf[keyout][2] << 1) | KEY_IN_3;
keybuf[keyout][3] = (keybuf[keyout][3] << 1) | KEY_IN_4;
for (i=0; i<4; i++)
{
if ((keybuf[keyout] & 0x0F) == 0x00)
{
KeySta[keyout] = 0;
}
else if ((keybuf[keyout] & 0x0F) == 0x0F)
{
KeySta[keyout] = 1;
}
}
keyout++;
keyout = keyout & 0x03;
switch (keyout)
{
case 0: KEY_OUT_4 = 1; KEY_OUT_1 = 0; break;
case 1: KEY_OUT_1 = 1; KEY_OUT_2 = 0; break;
case 2: KEY_OUT_2 = 1; KEY_OUT_3 = 0; break;
case 3: KEY_OUT_3 = 1; KEY_OUT_4 = 0; break;
default: break;
}
}
void LedScan()
{
static unsigned char i = 0; //数码管消除鬼影和消除数码管显示错位现象
P0 = 0xFF;
switch (i)
{
case 0: ADDR2=0; ADDR1=0; ADDR0=0; i++; P0=LedBuff[5]; break;
case 1: ADDR2=0; ADDR1=0; ADDR0=1; i++; P0=LedBuff[4]; break;
case 2: ADDR2=0; ADDR1=1; ADDR0=0; i++; P0=LedBuff[3]; break;
case 3: ADDR2=0; ADDR1=1; ADDR0=1; i++; P0=LedBuff[2]; break;
case 4: ADDR2=1; ADDR1=0; ADDR0=0; i++; P0=LedBuff[1]; break;
case 5: ADDR2=1; ADDR1=0; ADDR0=1; i=0; P0=LedBuff[0]; break;
default: break;
}
}
void InterruptTimer0() interrupt 1
{
TH0 = 0xF5; 详细点击下方链接
TL0 = 0x55;
LedScan();
KeyScan(); 简易加法计算器_哔哩哔哩_bilibili www.bilibili.com/video/BV1za411q7WJ/
}
本次程序大概思路就是这样,但是有一个问题就是由于38译码器,数码管,LED灯,和矩阵按键的输入引脚是接在一起的,这就造成了,当对37译码器ADDR0,ADDR1,ADDR2,进行赋值的时候,就给按键输入一个错误的信息,并且当按键按下时,也会对LED和数码管造成影响,这个问题暂且我还没有解决。
|