3个IO口扫描16个按键


         

该电路在程序处理时,由处理器首先向I/O1~I/O3写高电平,然后读入。如果非全“1”,说明,K0~K6中有键按下,此时可根据读入的端口状态判断键的状态,如果读入的结果为全“1”,则I/O1~I/O3轮流输出低电平,再读入,这样就可根据另外两根I/O线的状态来判别是K7~K15中的哪一个键被按下。重复调用键盘处理子程序可将读取的键值与上次的值进行比较,甚至两次读数相同为止,这样即可消除按键抖动所造成的误读。该电路选用的单片机为AT89C2051,用C51语言编写的按键电路处理程序如下:
#include<c:eg51.h>
#define uchar unsigned char
uchar getkey(void);
uchar keyvol;
void main(void)
{
keyvol=getkey(); /*调用键处理函数,返回的数据等于16表示同有键按下,0至15对应k0至K15*/
}
以下为键盘处理子程序:
uchar getkey(void)
{
uchar x
P1=P1|0x07; /*I/O1至I/O3写“1”*/
x=P1&0x07; /*读入I/O1至I/O3并屏蔽其它位*/

if(x==0x07)   /*判断K0至K6是否按下并转换键值*/

{
P1=P1&0xfe;   /* I/O1写“0”*/
x=P1&0x07;
x=x/2+7;
if(x= =10)
{
P1=P1|0x07;
P1=P1&0xfd; /*I/O2写“0”*/
x=P1&0x07;
x=(x+1)/2+10; /*屏蔽I/O2并转换K10至K12的键值*/
if(x = =13)
{
P1=P1|0x07;
P1=P1&0xfb; /*I/O3写“0”*/
x=P1&0x07;
x=x+13; /*屏蔽I/O3并转换K13至K15的键值*/
}
}
}
return x;
}

利用该键盘电路并根据逻辑组合原理可推断开n条I/O线可组合的按键数N为:
N=(2n-1)+(2 n-1 -1)n


个人觉得自己写程序的时候有个地方需要注意:当IO口赋值011,按k0之后IO读数为000,按k13读数也为000,所以如果检测到到k0到k6,这几个都没按才可以继续检测k7到k15.

本文参考:廖向峰.节约单片机端口资源的键盘电路.《国外电子元器件》2001年第12期2001年12月

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,以下是一个基于ATmega328P单片机的扫描6个按键的程序,你可以根据自己的需要进行修改和扩展: ```c #include <avr/io.h> #include <util/delay.h> #define KEY_DDR DDRB // 按键使用的IO #define KEY_PORT PORTB #define KEY_PIN PINB #define KEY1 (1<<PB0) // 按键1对应的IO #define KEY2 (1<<PB1) // 按键2对应的IO #define KEY3 (1<<PB2) // 按键3对应的IO #define KEY4 (1<<PB3) // 按键4对应的IO #define KEY5 (1<<PB4) // 按键5对应的IO #define KEY6 (1<<PB5) // 按键6对应的IO int main(void) { uint8_t key_state = 0; // 记录按键状态 uint8_t key_press = 0; // 记录按键按下事件 uint8_t key_release = 0; // 记录按键释放事件 KEY_DDR = ~(KEY1 | KEY2 | KEY3 | KEY4 | KEY5 | KEY6); // 设置按键为输入 while (1) { _delay_ms(20); // 延时一段时间 uint8_t key_now = KEY_PIN; // 读取当前按键状态 for (uint8_t i = 0; i < 6; i++) // 遍历6个按键 { uint8_t mask = 1 << i; if ((key_now & mask) == 0) // 检测到按键按下 { if ((key_state & mask) == 0) // 如果之前没有按下 { key_state |= mask; // 更新按键状态为按下 key_press |= mask; // 更新按键按下事件 } } else // 没有检测到按键按下 { if ((key_state & mask) != 0) // 如果之前是按下状态 { key_state &= ~mask; // 更新按键状态为释放 key_release |= mask; // 更新按键释放事件 } } } // 处理按键事件 if (key_press & KEY1) { // TODO: 处理按键1按下事件 } if (key_release & KEY1) { // TODO: 处理按键1释放事件 } if (key_press & KEY2) { // TODO: 处理按键2按下事件 } if (key_release & KEY2) { // TODO: 处理按键2释放事件 } if (key_press & KEY3) { // TODO: 处理按键3按下事件 } if (key_release & KEY3) { // TODO: 处理按键3释放事件 } if (key_press & KEY4) { // TODO: 处理按键4按下事件 } if (key_release & KEY4) { // TODO: 处理按键4释放事件 } if (key_press & KEY5) { // TODO: 处理按键5按下事件 } if (key_release & KEY5) { // TODO: 处理按键5释放事件 } if (key_press & KEY6) { // TODO: 处理按键6按下事件 } if (key_release & KEY6) { // TODO: 处理按键6释放事件 } key_press = 0; // 清空按键按下事件 key_release = 0; // 清空按键释放事件 } } ``` 这个程序使用了轮询的方式来扫描6个按键,可以实现基本的按键检测和事件处理。你可以根据自己的需要,修改程序中的TODO部分来实现具体功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值