单片机 键盘编程

花了几天时间整了下单片机的键盘.我用的单片机板子是用的P2的8个IO端口对16个键达到控制的目的.
那怎样来使用8个端口控制16个键呢?其实很简单,先必须要掌握她的原理图,
[img]/upload/attachment/89572/8ed2c5c8-088a-3ed2-84f2-75aa84fac52e.bmp[/img]
附件中作者上传了一张,仅供参考.原理图看了之后,我们就可以正式开始编写程序了.
先将KEY0置低电平,其余的置高电平,当我们按下第一列的按键时,P2的高四位肯定会有所变化,而我们就是用的这种变化达到分辨不同按键的目的.同理,我们可以将KEY1置低电平,再去检测P2的高四位,也得出了第二列按的哪个键.依次类推,我们即可检测单片机的16个按键了.
下面有一个单片机键盘的完整示例程序,本程序已在89C52单片机上成功运行,产生的效果是,按下单片机上不同的键时,数码管将显示不同的值与之对应.

#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int

sbit sda = P1^0;
sbit clk = P1^1;
sbit dig1 = P1^2;
sbit dig2 = P1^3;
sbit dig3 = P1^4;
sbit dig4 = P1^5;
uchar code table[]={0x7e,0x0c,0xb6,0x9e,
0xcc,0xda,0xfa,0x0e,
0xfe,0xde,0xef,0xf9,
0x72,0xb8,0xf2,0xe2};
uchar key = 255;
uchar diskey = 255;
void init();
void delay(uchar);
void write(uchar);
void display(uchar);
uchar scankey();

void main()
{
init();
while(1)
{
diskey = scankey();
display(diskey);
//scankey();
delay(10);
}
}
/** 键盘扫描 **/
uchar scankey()
{
uchar temp;
/* 检查第一列是否有按键按下 */
P2 = 0xfe;
temp = P2;
temp = temp&0xf0;
if(temp!=0xf0)
{
delay(5);
if(temp!=0xf0)
{
switch (temp)
{
case 0xe0 : key = 0;
break;
case 0xd0 : key = 1;
break;
case 0xb0 : key = 2;
break;
case 0x70 : key = 3;
break;
}
}
//display(key);//显示按的键
}

/* 检查第二列是否有按键按下 */
P2 = 0xfd;
temp = P2;
temp = temp&0xf0;
if(temp!=0xf0)
{
delay(5);
if(temp!=0xf0)
{
switch (temp)
{
case 0xe0 : key = 4;
break;
case 0xd0 : key = 5;
break;
case 0xb0 : key = 6;
break;
case 0x70 : key = 7;
break;
}
}
//display(key);//显示按的键
}
/* 检查第三列是否有按键按下 */
P2 = 0xfb;
temp = P2;
temp = temp&0xf0;
if(temp!=0xf0)
{
delay(5);
if(temp!=0xf0)
{
switch (temp)
{
case 0xe0 : key = 8;
break;
case 0xd0 : key = 9;
break;
case 0xb0 : key = 10;
break;
case 0x70 : key = 11;
break;
}
}
//display(key);//显示按的键
}
/* 检查第四列是否有按键按下 */
P2 = 0xf7;
temp = P2;
temp = temp&0xf0;
if(temp!=0xf0)
{
delay(5);
if(temp!=0xf0)
{
switch (temp)
{
case 0xe0 : key = 12;
break;
case 0xd0 : key = 13;
break;
case 0xb0 : key = 14;
break;
case 0x70 : key = 15;
break;
}
}
//display(key);//显示按的键
}
return key;
}
/** 显示一个3位的整数 **/
void display(uchar num)
{
uchar bai,shi,ge;
bai = num/100;
shi = num%100/10;
ge = num%10;
/* 显示个位 */
dig4 = 0;
write(table[ge]);
delay(10);
dig4 = 1;
/* 显示十位 */
dig3 = 0;
write(table[shi]);
delay(10);
dig3 = 1;
/* 显示百位 */
if(bai!=0)
{
dig2 = 0;
write(table[bai]);
delay(10);
[img]/upload/attachment/89564/a2582c87-2c23-3974-bf9c-f935ad8c6c92.bmp[/img]
[img]/upload/attachment/89564/a2582c87-2c23-3974-bf9c-f935ad8c6c92.bmp[/img]


dig2 = 1;
}
}
/** 程序初始化函数 **/
void init()
{
P2 = 0xfe;
//dig1 = 1;
//dig2 = 1;
//dig3 = 1;
//dig4 = 0;
}
/** 向数据码管写入一个字节数据 **/
void write(uchar u)
{
uchar i;
for(i=0;i<8;i++)
{
clk = 1;
sda = u&0x80;
clk = 0;
u = u<<1;
}
}
/** 延迟函数 **/
void delay(uchar t)
{
uchar x,y;
for(x=t;x>0;x--)
for(y=101;y>0;y--);
}
c语言实现单片机键盘程序 #include "SST89x5x4.H" #include #define uchar unsigned char #define uint unsigned int #define _Nop() _nop_() unsigned char code Key_Value_Table[16]={0xff,0x00,0x01,0xff,0x02,0xff,0xff,0xff, 0x03,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; void Key_Init(void); unsigned char GetScanKey(void); unsigned char GetKey(void); void LCD_Init(void); void LCD_Init2(void); //void WriteW(uint a); void CheckBF(void); unsigned char Key_ASC2(unsigned char); void WritD(unsigned char); void Delay_ns(int i); void Delay_ms(int ms); unsigned char key; unsigned char key_asc2; unsigned char bKeyUp_Flag; uchar xdata *ptr; //函数功能描述:键盘初始化,将标志位置1; void Key_Init(void) { bKeyUp_Flag=1;//标志(全局变量)位置1 } //函数功能描述:键盘扫描函数,得到键的行列位置; unsigned char GetScanKey(void) { unsigned char key, i, temp; unsigned char xdata * ptr; key=0xff; for (i=1; i<0x10; i<<=1) //i的低4位为行数位,行依次检测 循环4次 { ptr=0x8fff; //数码管位选地址 * ptr =i; temp = * ptr; //取键盘IO口的值 temp &= 0x0f; //屏蔽高四位 if (temp!=0x00) //是否有有效键值 { key = i<<4; //取行数位的值并将其放入返回值高4位 key|=temp; //列数位的值放入返回值低4位 break; } } return key; //返回行位(高四)和列位(低四) } /*函数功能描述:取键值,长按无效; unsigned char code Key_Value_Table[16]={0xff,0x00,0x01,0xff,0x02,0xff,0xff,0xff, 0x03,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; 说明:计算因子,定义在函数外部。此数组在计算键值的中间过程起作用。比如右下方键按下(行列值为0x88),通过查找数组得到行对应的中间值0x03,列对应的中间值0x03。 */ unsigned char GetKey(void) { unsigned char key, temp; if (!bKeyUp_Flag) //判断标志,是0执行 /*按键程序执行一次后会将bKeyUp_Flag标志位清零,执行此段程序,长按键无效返回无效值,直至按键无效返回无效按键值,置"1"标志位。按键输入恢复有效。屏蔽这部分则长按键有效*/ { key=GetScanKey(); if (key==0xff) //没有按键,置标志位 bKeyUp_Flag=1; else //保持按键 return 0xff; //因为0xff大于15,故为无效键值,实现长按键无效 } key=GetScanKey(); if (key==0xff) //没有按键 return key; else //有按键有效 temp=key; //取键值 Delay_ms(20); //延时20ms 消抖 key=GetScanKey(); //键盘扫描 if(key!=temp) //判断两次键值是否相同,排除干扰信号影响 确认有效信号 { key=0xff; return key; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值