电路图:
代码:
#include <reg51.h>
#define uint unsigned int
#define uchar unsigned char
// 要展示的数据 0-F 共阴极 和tab[]一一对应
uchar code dp[] = {
0x3f, 0x06, 0x5b, 0x4f,
0x66, 0x6d, 0x7d, 0x07,
0x7f, 0x6f, 0x77, 0x7c,
0x39, 0x5e, 0x79, 0x71};
// 用于后续判断哪个按钮按下
uchar code tab[] = {
0xee, 0xde, 0xbe, 0x7e,
0xed, 0xdd, 0xbd, 0x7d,
0xeb, 0xdb, 0xbb, 0x7b,
0xe7, 0xd7, 0xb7, 0x77
};
// 延迟函数
void delay(uint xms) {
uint i, j;
for (i = xms; i > 0; i--)
for (j = 110; j > 0; j--);
}
void main() {
uint row, col, key, i;
// 初始状态不亮
P2 = 0x00;
while (1) {
P3 = 0x0F;
if (P3 != 0x0F) {
delay(10);
if (P3 != 0x0F) {
row = P3;
P3 = 0xF0;
col = P3;
key = row + col;
for (i = 0; i < 16; i++) {
if (key == tab[i])
P2 = dp[i];
}
while (!P3);
}
}
}
}
对代码的解释:
进入while循环我们先把P3 = 0x0F,这样一来所有的列将会被选中(也可以将P3初始化为0xF0)
这时候P3是等于0x0F不会进入执行if,当有键按下时(后续以左上角btn1按下为例)延迟10ms然后再次判断会确定按键按下,确定以后现在P3口成了 0000 1110 (从高到低)
此时执行 row = P3 得到 0000 1110 就知道了按下的按钮在第一行(前四位即第几列由于都是0不能确定)
然后将P3置为0xF0,由于btn1按下,将P3置为0xF0后还要看按钮由于btn1是按下的状态,他会带动btn1所在的这列即c1,也会是低电平所以在执行col = P3 时 P3的值实际是 1110 0000
由此得到col为 1110 0000 即按下的按钮在第一列,这样一来就能确定按下按钮的位置
将行和列相加得到按下的开关的16进制在和tab[]数组的值进行比较然后将对应的值赋值给P2
然后我们!P3来实现防抖(即按键改变时)