5个IO口最多能扫描多少个按键
用最少的IO口扫最多的按键
用最少的IO口扫最多的按键竟然可以这样在做项目(工程)的时候,我们经常要用到比较多的按键,而且IO资源紧张,于是我们就想方设法地在别的模块中节省IO口,好不容易挤出一两个IO口,却发现仍然不够用,实在没办法了就添加一个IC来扫键。
一个IC虽然价格不高,但对于大批量生产而且产品利润低的厂家来说,这是一笔不菲的开支!那,我们能不能想到比较好的扫键方法:用最少的IO口,扫最多的键?可以吗?举个例:给出5个IO口,能扫多少键?有人说是2*3=6个,如图一:图一对,大部分技术参考书都这么做,我们也经常这样做:用3个IO口作行扫描,2个IO作列检测(为方便描述,我们约定:设置某一IO口输出为“0”――称其为“扫某IO口”)。
用行线输出扫键码,列线检测是否有按键的查询方法进行扫键。
扫键流程:在行线依次输出011,101,110扫键值,行线每输出一个扫键值,列线检测一次。
当列线检测到有按键时,结合输出的扫键值可以判断相应的按键。
但是,5个IO真的只能扫6个键吗?有人说可以扫9个,很聪明!利用行IO与地衍生3个键(要注意上拉电阻),如图二:图二扫键流程:先检测3个行IO口,对K1’,K2’,K3’进行扫键,之后如上述2*3扫键流程。
5个IO口能扫9个键,够厉害吧,足足比6个键多了1/2!动动脑,还能不能再多扫几个?就几个?一个也行!好,再想一下,硬是被逼出来了!如图三:图三不多不少,正好10个键!这种扫键方式比较少见吧!漂亮!扫键流程:设IO1输出为“0”,检测IO2…IO5,若判断有相应健按下,则可知有健;若无键,则继续扫键:设IO2输出为“0”,检测IO3,IO4,IO5,判断有无键按下,如此类推。
这里应注意:当扫某一IO口(输出为“0”)时,不要去检测已经扫过的IO口。
如:此时设置IO2输出为“0”,依次检测IO3,IO4,IO5,但不要去检测IO1,否则会出错(为什么,请思考)。
感觉怎么样?不错吧!让我们再看看图三,好有成就感!看着,看着……又看到了什么?快!见图四:图四真强!被您看出20个键!多了一个对称的三角形。
AIP650 LED驱动控制 键盘扫描专用集成电路 产品说明书
表733-11-I 编号:AIP650-AX-BJ-78AIP650LED驱动控制/键盘扫描专用集成电路产品说明书说明书发行履历:版本发行时间新制/修订内容2010-01-A 2010-01 更换新模板2012-01-B1 2012-01 增加说明书编号及发行履历第 1 页共 12 页版本:2012-01-B11、概 述AIP650是一种带键盘扫描电路接口的LED 驱动控制专用电路。
内部集成有MCU 输入输出控制数字接口、数据锁存器、LED 驱动、键盘扫描、辉度调节等电路。
本芯片性能稳定、质量可靠、抗干扰能力强,可适应于24小时长期连续工作的应用场合。
其主要特点如下: ● 显示模式:8段×4位● 段驱动电流不小于25mA ,字驱动电流不小于150mA. ● 提供8级亮度控制 ● 键盘扫描:7×4bit ● 高速两线式串行接口 ● 内置时钟振荡电路 ● 内置上电复位电路 ● 支持3V -5.5V 电源电压● 使用时VCC 端建议加104电容,且电容尽量靠近AIP650的VCC 端口(小于2cm ) ● 封装形式:DIP16/SOP162、引脚排列图及引脚说明2.1、引脚排列图第 2 页 共 12 页版本:2012-01-B1DP/KP G/KI7F/KI6E/KI5D/KI4C/KI3VCC B/KI21211DIG1CLK DAT GND DIG2DIG3DIG4A/KI11615141312345678910第 3 页 共 12 页版本:2012-01-B12.2、引脚说明 引脚符 号引 脚 名 称功 能1 DIG1 位/键扫描输出 LED 位驱动输出,低电平有效,及作为键盘扫描输出,高电平有效。
2 CLK 时钟输入 2线串行接口的数据时钟输入,内置上拉电阻。
3 DAT 数据输入/输出 2线串行接口的数据输入输出,为内置上拉开漏模式。
4 GND接地端 接地5 DIG2位/键扫描输出 LED 位驱动输出,低电平有效,及作为键盘扫描输出,高电平有效。
用一条IO口实现两个按键功能
用一条IO口实现两个按键功能发布时间:2011-02-27 14:11:36 年前去到一个朋友那里,提到现在客户对成本要求非常之高,尤其是玩具行业,已经是一分一厘的去计算产品成本。
朋友感慨为了省成本,方案商是绞尽脑汁地去想各种实现方法,说遇到过为了节省成本,硬是用单片机一条IO实现了两个按键的功能,让他颇为诧异,好久都没想明白原理。
一条IO实现两个按键,听上去确实挺新奇,既然别人能够实现,我想我也应该可以做到,看来得找找实现的方法。
我有一个习惯,遇到某些问题的时候,会在睡觉前想解决方法,想着想着就会睡着了,问题的答案有没有找到则不一定。
我知道有用一条IO实现多个按键的方法,这样的方法大多是选用的IO支持ADC功能,用电阻分压后通过读电压判断键值。
如果IO不支持ADC功能,也不是不行,可以用电容充放电的方法实现ADC,从而用普通IO间接进行测量。
(参见我之前关于键盘扫描的文章)这样用一条IO实现两个按键给我的第一感觉是可能需要利用到电容充放电原理,于是在半梦半醒之中找到了实现的方法。
先看上图左边部分,如果MCU_IO1为双向IO口,假设单片机程序按以下流程处理,看看会得到什么样的结果?1.MCU_IO1设定为输出,输出高电平一段时间,此时电容C1会充电,最后C1上的电压接近电源电压。
2.MCU_IO1设定为输入,如果J1、J2均不按下,此时MCU_IO1可以理解成一个阻值很大的电阻接地,电容C1上的电荷会通过这个电阻逐渐释放掉,这样C1上的电压会逐渐降低到零。
因为C1上的电压下降需要一个过程,当MCU_IO1设为输入后马上读一下MCU_IO1的状态,此时会读到什么结果?显然是高电平状态1。
3.再将MCU_IO1设定为输出,输出低电平一段时间,显然不管电容C1处于什么状态,只要MCU_IO1输出低电平时间足够长,最后C1上的电压应该接近零。
4.再将MCU_IO1设定为输入,如果J1、J2同样不按下,MCU_IO1读到的是低电平状态0。
五键电容式触摸感应按键芯片TCH05B
TCH05B五键电容式触摸感应按键芯片 概述:触摸感应检测按键可以穿透绝缘材料外壳来检测人体手指带来的电荷移动,从而 不需要传统按键的机械触点而判断出有效按键动作。
感应检测按键做出来的产品可靠耐 用,美观时尚,材料用料少,便于生产安装以及维护,逐步将取代传统直接按钮键。
TCH05B是一款高性价比的触摸感应检测IC,能提供最多5个感应键。
特点:工作电压2.0V— 5.5V 电路非常简单,无须任何其他外围元件 工作电流在3V时68uA, 最大值100uA 可以选择4级灵敏度 快速上电,1S内按键即可以工作 提供直接输出低电平有效 稳定的电容检测算法 环境温度湿度变化自动适应 10S异常输出自动重适应 同TCH0x系列共用内核 SSOP-16超小型封装,包含引脚总面积5mmX6mm应用:数码产品MP3,MP4,LCD-TV等 家用电器 取代传统按钮键Page 1 of 7TCH05B封装脚位:管脚描述:管脚号 管脚名称1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 OSL I4 I3 I2 I1 I0 OSC1 VDD Q0 Q1 Q2 Q3 Q4 VSS SL1 SL2I/O 类型I/O I I I I I I/O I/O I/O I/O I/O I/O I I管脚描述内部振荡,一般悬空 感应按键 4 信号输入口 感应按键 3 信号输入口 感应按键 2 信号输入口 感应按键 1 信号输入口 感应按键 0 信号输入口 内部测试用,请悬空 电源电压正极,2.0-5.5V Q0 为直接模式下的输出管脚 Q1 为直接模式下的输出管脚 Q2 为直接模式下的输出管脚 Q3 为直接模式下的输出管脚 Q4 为直接模式下的输出管脚 电源电压负极 选择灵敏度的选项管脚,调节级别 1 选择灵敏度的选项管脚,调节级别 2Page 2 of 7TCH05B功能描述:1、输出方式: TCH05A输出模式则为直接模式, 输入输出对应关系见下表: 无按键信号 I0按键信号有效 I1按键信号有效 I2按键信号有效 I3按键信号有效 I4按键信号有效 Q0-Q4 为高电平 Q0 输出低电平 Q1 输出低电平 Q2 输出低电平 Q3 输出低电平 Q4 输出低电平2、灵敏度调节: TCH05 电容式触摸按键是通过检测触盘对地电容的变化来实现触摸识别的, 因此灵敏度 与电容的变化量有直接的关系。
按键扫描方法
说到键盘扫描,相信大多数人第一反应就是行列矩阵扫描,这样我们可以用相对有限的IO口得到尽可能多的按键。
键盘扫描是单片机技术的一种基本处理方法,学校的单片机课程都会有相应章节进行阐述,只要按照课本上讲述的方法,一般都能设计出比较可靠的键盘扫描电路与程序。
课本上的键盘扫描方法(见下图接法二)不能说是尽善尽美,从易懂性、成本、程序难易程度等方面综合看应该是不错的方法,给人感觉是已经没有太多的改善空间,至少我是这么认为的。
然而前段时间一位台湾朋友画给我的键盘扫描矩阵电路(见下图接法二),让我又一次看到到自己的思维还有许多地方被自己的所谓“经验”束缚着。
单纯的从硬件接法看,两种接法并没有明显区别,接法一甚至要复杂一些,但如果结合到键盘扫描的程序来看,就会发现接法一确实更好。
两种接法我都没有把上拉电阻包含进来,来让我们看一下两种接法到底有什么不同:接法二:我们熟悉的传统扫键处理电路,假定键盘行列IO口标号分别为H1/H2/H3和V1/V2/V3,扫键流程通常如下。
2.1. H1设置为输出,H2/H3和V1/V2/V3设置为输入2.2. H1分别输出1和0,读V1/V2/V3状态,如果Vy状态与H1一致,则认为H1与Vy交叉位置的键按下2.3. H2设置为输出,H1/H3和V1/V2/V3设置为输入2.4. H2分别输出1和0,读V1/V2/V3状态,如果Vy状态与H2一致,则认为H2与Vy交叉位置的键按下2.5. H3设置为输出,H1/H2和V1/V2/V3设置为输入2.6. H3分别输出1和0,读V1/V2/V3状态,如果Vy状态与H3一致,则认为H3与Vy交叉位置的键按下接法一:新扫键处理电路,假定键盘行列IO口标号分别为H1/H2/H3和V1/V2/V3,扫键流程通常如下。
1.1. H1/H2/H3和V1/V2/V3都设置为输入1.2. 读H1/H2/H3和V1/V2/V3状态,如果Hx和Vy读到的状态均为0,则认为Hx与Vy交叉位置的键按下从上面流程可以看出接法一的程序代码要简单不少,既能减少扫键的代码量,又能加快扫键处理的时间,站在软件的角度看确实要比接法二要好。
第七章 IO接口_AD_DA技术
C口上半部分(PC7~PC4)随A口称为A组,
C口下半部分(PC3~PC0)随B口称为B组。
其中A口可工作于方式0、1、和2,而B口只能工作在 方式0和1。 例如:写入工作方式控制字95H
可将8255A编程为:A口方式0输入,B口方式1输出, C口的上半部分(PC7~ PC4)输出,C口的下半部分 (PC3~PC0)输入。
第9章 MCS-51扩展I/O接口的设计 9.1 I/O接口扩展概述
I/O (输入/输出)接口是MCS-51与外设交换数字信 息的桥梁。
I/O扩展也属于系统扩展的一部分。
真正用作I/O口线的只有P1口的8位I/O线和P3口的某些 位线。 在多数应用系统中,MCS-51单片机都需要外扩I/O接 口电路。
数据总线为三态 非法状态 数据总线为三态
0
0 1 1 × 1 ×
0
1 0 1 × 1 ×
1
1 1 1 × 0 1
0
0 0 0 × 1 1
0
0 0 0 1 0 0
9.2.2 工作方式选择控制字及C口置位/复位控制字
8255A有三种工作方式:
(1) 方式0:基本输入输出; (2) 方式1:选通输入输出; (3) 方式2:双向传送(仅A口有)。
各端口的工作状态与控制信号的关系如表9-1所示。
表9-1
A1 A0
8255A端口工作状态选择
RD* WR* CS* 工作状态
0
0 1
0
1 0
0
0 0
1
1 1
0
0 0
读端口A:A口数据→数据总线 读端口B:B口数据→数据总线 读端口C:C口数据→数据总线 写端口A:总线数据→A口 写端口B:总线数据→B口 写端口C:总线数据→C口 写控制字:总线数据→控制字寄存 器
第4节:“鸿哥三宝”之74HC165(按键扫描篇)
}
else if(key_lock4==0)
{
++ delay_cnt4;
if(delay_cnt4> cnt_delay_cnt1) //延时计数去抖动
hc165_pl_dr=0;
asm("nop");
asm("nop");
hc165_pl_dr=1;
asm("nop");
asm("nop");
for(j=0;j<16;j++)
{
hc165_cp_dr=0;
beep_dr=0; //关蜂鸣器,上电初始化IO
while(1) { Nhomakorabea CLRWDT(); //喂看门狗,大家不用过度关注此行
key_service(); //按键服务
asm("nop");
asm("nop");
} //以上一小段代码是通过驱动2个74HC165来获取16个按键的电平状态
//key_status
//以下代码通过解析每一位电平状态来确定哪个按键被触发
if((key_status &0x0001)==0x0001)
(4)源码适合的单片机:PIC18f4520,晶振为22.1184MHz
(5)源代码讲解如下:
#include<pic18.h> //包含芯片相关头文件
//补充说明:吴坚鸿程序风格是这样的,凡是输出IO后缀都是_dr,凡是输入的//IO后缀都//是_sr
LE5010 LinkedBlock Solo 使用手册说明书
凌思微电子(厦门)有限公司LINKEDSEMILE5010 LinkedBlock Solo使用手册修订记录目录第1章LE5010 Solo开发板硬件设计 (4)1. 1开发板硬件资源 (4)1. 2开发板IO口分配 (5)1. 2. 1板上外设 (5)1. 2. 2数字IO (5)1. 2. 3模拟IO (6)1. 2. 4IO配置注意事项 (6)1. 3开发板电源开关说明 (7)1. 3. 15V供电.................................................................................... 错误!未定义书签。
1. 3. 2 3.3V供电 (8)第2章LE5010 Solo开发板系统框图 (9)第3章LE5010 Solo开发板产品特性 (11)第4章开发板使用说明 (12)4. 1烧录与调试 (12)4. 2串口驱动安装 (12)4. 3软件调试注意事项 (12)第5章LE5010开发示例 (13)5. 1GPIO示例 (13)5. 2UART示例 (13)5. 3BLE串口透传示例 (13)第6章LE5010 Solo技术支持 (14)附录1例程路径:SCH&PCB&BOM (15)第1章LE5010 Solo开发板硬件设计1. 1 开发板硬件资源图1 LE5010 Solo Board 实物图图1 LE5010 Solo Board为凌思微LE5010 QFN48封装的开发学习板板宽为25.4*53.09mm,兼容面包板,板载天线保持黑漆倒角, PCB沉金工艺,丝印清晰,外观简洁美观。
25个外接IO(包括数字和模拟IO)TYPE-C口供电(5V),外部电源供电(3.3V)一个RGB灯, 不影响功耗测试具有USB-UART转换芯片(Type-C口兼容UART通信烧录)J-link(SWD模式)四线烧入调试口具有TX/RX 串口状态灯和PWR电源指示灯具有一个复位按键和唤醒按键(低电平有效)1. 2 开发板IO 口分配LE5010 Solo Board 开发板采用LE5010_QFN48封装IC 芯片,扣除电源、晶振、RF 管脚,共有34个IO 口(包括复位、BOOT 、烧录以及UART 口),这里将这34个IO 口分为3类,分别为学习板上外设、数字IO 口、模拟IO 口,具体如下表格。
用一条IO口实现两个按键功能
我知道有用一条IO实现多个按键的方法,这样的方法大多是选用的IO支持ADC功能,用电阻分压后通过读电压判断键值。
如果IO不支持ADC功能,也不是不行,可以用电容充放电的方法实现ADC,从而用普通IO间接进行测量。
这样用一条IO实现两个按键给我的第一感觉是可能需要利用到电容充放电原理,于是在半梦半醒之中找到了实现的方法。
先看上图左边部分,如果MCU_IO1为双向IO口,假设单片机程序按以下流程处理,看看会得到什么样的结果?1.MCU_IO1设定为输出,输出高电平一段时间,此时电容C1会充电,最后C1上的电压接近电源电压。
2.MCU_IO1设定为输入,如果J1、J2均不按下,此时MCU_IO1可以理解成一个阻值很大的电阻接地,电容C1上的电荷会通过这个电阻逐渐释放掉,这样C1上的电压会逐渐降低到零。
因为C1上的电压下降需要一个过程,当MCU_IO1设为输入后马上读一下MCU_IO1的状态,此时会读到什么结果?显然是高电平状态1。
3.再将MCU_IO1设定为输出,输出低电平一段时间,显然不管电容C1处于什么状态,只要MCU_IO1输出低电平时间足够长,最后C1上的电压应该接近零。
4.再将MCU_IO1设定为输入,如果J1、J2同样不按下,MCU_IO1读到的是低电平状态0。
如果J1按下,再来看看这四步,此时电容C1已经被强制接到电源上,MCU_IO1对其的充放电已经不起作用,在步骤2中MCU_IO1读到的状态依然是1,但在步骤4中MCU_IO1读到的状态就不再是0,而是变为1。
如果J2按下,同样看这四步,此时电容C1被强制接到地,MCU_IO1对其充放电也失去作用,在步骤2中MCU_IO1读到的状态变为0,但在步骤4中MCU_IO1读到的状态保持为0。
到这里我想大家应该已经明白了实现方法,根据此四步中读到的MCU_IO1状态,就可以判断出J1、J2是否按下。
既然已经找到方法,是不是就万事大吉了呢?不然,我们还得回过头去看看此方法是不是足够可靠。
5个IO最多可以接出多少个按键
5个IO最多可以接出多少个按键在做项目(工程)的时候,我们经常要用到比较多的按键,而且IO资源紧张,于是我们就想方设法地在别的模块中节省IO口,好不容易挤出一两个IO口,却发现仍然不够用,实在没办法了就添加一个IC来扫键。
一个IC虽然价格不高,但对于大批量生产而且产品利润低的厂家来说,这是一笔不菲的开支!那,我们能不能想到比较好的扫键方法:用最少的IO口,扫最多的键?可以吗?举个例:给出5个IO 口,能扫多少键?有人说是2*3=6个,如图一:图一对,大部分技术参考书都这么做,我们也经常这样做:用3个IO口作行扫描,2个IO作列检测(为方便描述,我们约定:设置某一IO口输出为“0”――称其为“扫某IO 口”)。
用行线输出扫键码,列线检测是否有按键的查询方法进行扫键。
扫键流程:在行线依次输出011,101,110扫键值,行线每输出一个扫键值,列线检测一次。
当列线检测到有按键时,结合输出的扫键值可以判断相应的按键。
但是,5个IO真的只能扫6个键吗?有人说可以扫9个,很聪明!利用行IO与地衍生3个键(要注意上拉电阻),如图二:图二扫键流程:先检测3个行IO口,对K1’,K2’,K3’进行扫键,之后如上述2*3扫键流程。
5个IO口能扫9个键,够厉害吧,足足比6个键多了1/2!动动脑,还能不能再多扫几个?就几个?一个也行!好,再想一下,硬是被逼出来了!如图三:图三不多不少,正好10个键!这种扫键方式比较少见吧!漂亮!扫键流程:设IO1输出为“0”,检测IO2…IO5,若判断有相应健按下,则可知有健;若无键,则继续扫键:设IO2输出为“0”,检测IO3,IO4,IO5,判断有无键按下,如此类推。
这里应注意:当扫某一IO口(输出为“0”)时,不要去检测已经扫过的IO口。
如:此时设置IO2输出为“0”,依次检测IO3,IO4,IO5,但不要去检测IO1,否则会出错(为什么,请思考)。
感觉怎么样?不错吧!让我们再看看图三,好有成就感!看着,看着……又看到了什么?快!见图四:图四真强!被您看出20个键!多了一个对称的三角形。
两个IO口检测六个按键
两个I/O口实现六个按键的电路(无附加集成块)及配套C程序摘要:思路非常巧妙,仅用2个IO就可区分出无键和6个单独按键共7种状态... 原理图:程序:1.//6keyfor2io.c2.//思路非常巧妙,仅用2个IO就可区分出无键和6个单独按键共7种状态,3.//如有疑问也可发送邮件至:****************讨论4.#include <REG52.H>5.#define uchar unsigned char6.7.sbit IO1=P1^6;8.sbit IO2=P1^7;9.uchar keybuf,keydat;10.bit bkeyok;11.12.void delay_us(unsigned int n)13.{14.while(--n);15.}16.17.void delay_ms(unsigned int n)18.{19.do20. {21. delay_us(1000);22. }23.while(--n);24.}25.26.bit scan_key(void)27.{28. uchar tempkey;29. IO1=1;IO2=1;30.if(!IO1)31. {32.if (!IO2)33. tempkey=3; // IO1 = 0,IO2 = 0;34.else35. tempkey=2; // IO1 = 0,IO2 = 1;36. }37.else38. {39.if (!IO2)40. tempkey=1; // IO1 = 1,IO2 = 0;41.else // 两个口都等于142. {43. IO1=0; // IO1输出044.if (!IO2) // IO2 = 0?45. {46. IO1=1;IO2=0; // IO1先输出147.if (!IO1)48. tempkey=4; // IO2输出0,检测IO1是否为049.else50. tempkey=6; // IO1 = 1,51. }52.else // IO2 = 1?53. {54. IO1=1;IO2=0;55.if (!IO1)56. tempkey=5;57.else58. tempkey=0;59. }60.61. }62. }63. IO1=1;IO2=1;64.if((keybuf !=0) && (keybuf == tempkey))65. {66. bkeyok=1;67. keydat=tempkey;68. }69. keybuf=tempkey;70.return(bkeyok);71.}72.73.uchar read_key(void)74.{75. bkeyok=0;76.return(keydat);77.}78.79.void doanything(uchar key)80.{81.//----------按键处理只有有按键并正确消抖时才会进入,功能自己随便写82. ;83.}84.85.void main(void)86.{87.while(1)88. {89.if(scan_key())90. doanything(read_key());91. delay_ms(10);92. }93.}。
TM1650 LED驱动控制专用电路说明书
一、概述TM1650是一种带键盘扫描接口的LED(发光二极管显示器)驱动控制专用IC,内部集成有MCU 数字接口、数据锁存器、LED驱动、键盘扫描等电路。
本产品质量可靠、稳定性好、抗干扰能力强。
主要适用于机顶盒、家电设备(智能热水器、微波炉、洗衣机、空调、电磁炉)、电子称、智能电表等数码管,可适用于24小时长期连续工作的应用场合。
二、特性说明•两种显示模式(8段×4 位和 7 段×4 位)•支持单个按键7x4bit(28个按键)和组合按键(4个)• 8••高速2••••支持••三、四、管脚功能定义:1结束信号:保持CLK为“1”电平,DAT从“0”跳“1”,认为是结束信号,如(图1)E段;2、ACK信号如果本次通讯正常,芯片在串行通讯的第8个时钟下降沿后,TM1650主动把DAT拉低。
直到检测到CLK来了上升沿,DAT释放为输入状态(对芯片而言),如(图1)D段。
3、写“1”和写“0”写“1”:保持DAT为“1”电平,CLK从“0”跳到“1”,再从“1”跳到“0”,则认为是写入“1”如(图1)B段。
写“0”:保持DAT为“0”电平,CLK从“0”跳到“1”,再从“1”跳到“0”,则认为是写入“0”如(图1) C段。
4、 一个字节(8位)数据传输格式12345678B7B6B5B4B3B2B1B0DATCLK图2一个字节数据的传输格式如图2,数据发送时MSB 在前,LSB 在后,即高位先进。
微处理器的数据通过2线串行接口和TM1650通信,当CLK 是高电平时,DAT 上的信号必须保持不变;只有CLK 上的时钟信号为低电平时,DAT 上的信号才能改变。
数据输入的开始条件是CLK 为高电平时,DAT 由高变低;结束条件是CLK 为高时,DAT 由低电平变为高电平。
5、 写显示操作6SCL 7图5 读按键时序command :读按键命令4FH ;key_data :读按键数据(一个字节)。
5个IO口扫描25个按键
5个IO口你能扫描多少按键?25个!看看这个吧5个IO口扫描25个按键的解决方法来源:互联网简介:在做项目(工程)的时候,我们经常要用到比较多的按键,而且IO资源紧张,于是我们就想方设法地在别的模块中节省IO口,好不容易挤出一两个IO口,却发现仍然不够用,实在没办法了就添加一个IC来扫键。
一个IC虽然价格不高,但对于大批量生产而且产品利润低的厂家来说,这是一笔不菲的开支!那,我们能不能想到比较好的扫键方法:用最少的IO口,扫最多的键?可以吗?举个例:给出5个IO口,能扫多少键?有人说是2*3=6个,如图一:图一对,大部分技术参考书都这么做,我们也经常这样做:用3个IO口作行扫描,2个IO 作列检测(为方便描述,我们约定:设置某一IO口输出为“0”――称其为“扫某IO口”)。
用行线输出扫键码,列线检测是否有按键的查询方法进行扫键。
扫键流程:在行线依次输出011,101,110扫键值,行线每输出一个扫键值,列线检测一次。
当列线检测到有按键时,结合输出的扫键值可以判断相应的按键。
但是,5个IO真的只能扫6个键吗?有人说可以扫9个,很聪明!利用行IO与地衍生3个键(要注意上拉电阻),如图二:图二扫键流程:先检测3个行IO口,对K1’,K2’,K3’进行扫键,之后如上述2*3扫键流程。
5个IO口能扫9个键,够厉害吧,足足比6个键多了1/2!动动脑,还能不能再多扫几个?就几个?一个也行!好,再想一下,硬是被逼出来了!如图三:图三不多不少,正好10个键!这种扫键方式比较少见吧!漂亮!扫键流程:设IO1输出为“0”,检测IO2…IO5,若判断有相应健按下,则可知有健;若无键,则继续扫键:设IO2输出为“0”,检测IO3,IO4,IO5,判断有无键按下,如此类推。
这里应注意:当扫某一IO口(输出为“0”)时,不要去检测已经扫过的IO口。
如:此时设置IO2输出为“0”,依次检测IO3,IO4,IO5,但不要去检测IO1,否则会出错(为什么,请思考)。
5个IO口25个按键
UINT8 Key_Scan_New(void){UINT8 chTempKeyCode = KEY_NULL; //为按键的编码设初值//先对21-25按钮进行扫描DDRC &= ~(BIT(1) | BIT(2) | BIT(3) |BIT(4) | BIT(5)); //把端口pc1-pc5都置为输入PORTC |= BIT(1) | BIT(2) | BIT(3) |BIT(4) | BIT(5); //全部端口拉高NOP();NOP();if (!(PINC & (BIT(1)))) //读取pc1端口,如果返回值是0则表明按键被按下, //则返回按键的值{chTempKeyCode = 21;return chTempKeyCode;}else if (!(PINC & (BIT(2)))) //读取pc2端口,如果返回值是0则表明按键被按下, //则返回按键的值,下面以此类推。
{chTempKeyCode = 22;return chTempKeyCode;}else if (!(PINC & (BIT(3)))){chTempKeyCode = 23;return chTempKeyCode;}else if (!(PINC & (BIT(4)))){chTempKeyCode = 24;return chTempKeyCode;}else if (!(PINC & (BIT(5)))){chTempKeyCode = 25;return chTempKeyCode;}////////////////////////////////////////////////////////////////对1-4按钮进行扫描DDRC &= ~(BIT(2) | BIT(3) |BIT(4) | BIT(5)); //把端口pc2-pc5设置为输入DDRC |= BIT(1); //把pc1端口设为输出PORTC |= BIT(1) | BIT(2) | BIT(3) |BIT(4) | BIT(5);PORTC &=~ BIT(1); //把pc1端口拉低NOP();NOP();if (!(PINC & (BIT(2)))) //读取pc2端口,如果返回值是0则表明按键被按下,//则返回按键的值//以下依次对pc3、pc4、pc5逐个读取值,如果返回值为0 //则返回相应按键值{chTempKeyCode = 1;return chTempKeyCode;}else if (!(PINC & (BIT(3)))){chTempKeyCode = 2;return chTempKeyCode;}else if (!(PINC & (BIT(4)))){chTempKeyCode = 3;return chTempKeyCode;}else if (!(PINC & (BIT(5)))){chTempKeyCode = 4;return chTempKeyCode;}////////////////////////////////////////////////////////////////对6-7按钮进行扫描DDRC &= ~(BIT(1) | BIT(3) |BIT(4) | BIT(5));//把端口pc1,pc3-pc5设置为输入DDRC |= BIT(2);//把pc2端口设为输出PORTC |= BIT(1) | BIT(2) | BIT(3) |BIT(4) | BIT(5);PORTC &= ~BIT(2); //把pc2端口拉低NOP();NOP();if (!(PINC & (BIT(3)))) //读取pc3端口,如果返回值是0则表明按键被按下,//则返回按键的值//以下依次对pc4、pc5逐个读取值,如果返回值为0 //则返回相应按键值{chTempKeyCode = 6;return chTempKeyCode;}else if (!(PINC & (BIT(4)))){chTempKeyCode = 7;return chTempKeyCode;}else if (!(PINC & (BIT(5)))){chTempKeyCode = 8;return chTempKeyCode;}////////////////////////////////////////////////////////////////对11-12按钮进行扫描DDRC &= ~(BIT(2) | BIT(1) |BIT(4) | BIT(5));//把端口pc1-pc2,pc4-pc5设置为输入DDRC |= BIT(3);//把pc3端口设为输出PORTC |= BIT(1) | BIT(2) | BIT(3) |BIT(4) | BIT(5);PORTC &= ~BIT(3);//把pc2端口拉低NOP();NOP();if (!(PINC & (BIT(4)))) //读取pc4端口,如果返回值是0则表明按键被按下, //则返回按键的值{chTempKeyCode = 11;return chTempKeyCode;}else if (!(PINC & (BIT(5))))//读取pc5端口,如果返回值是0则表明按键被按下, //则返回按键的值{chTempKeyCode = 12;return chTempKeyCode;}//////////////////////////////////////////////////////////////////对16按钮进行扫描DDRC &= ~(BIT(2) | BIT(1) |BIT(3) | BIT(5));//把端口pc1-pc3、pc5设置为输入DDRC |= BIT(4); //把pc4端口设为输出PORTC |= BIT(1) | BIT(2) | BIT(3) |BIT(4) | BIT(5);PORTC &=~ BIT(4); //把pc4端口拉低NOP();NOP();if (!(PINC & (BIT(5)))){chTempKeyCode = 16;return chTempKeyCode; //读取pc5端口,如果返回值是0则表明按键被按下, //则返回按键的值}////////////////////////////////////////////////////////////////对20-17按钮进行扫描DDRC &= ~(BIT(2) | BIT(3) |BIT(4) | BIT(1)); //把端口pc1-pc4设置为输入DDRC |= BIT(5); //把pc5端口设为输出PORTC |= BIT(1) | BIT(2) | BIT(3) |BIT(4) | BIT(5);PORTC &= ~BIT(5); //把pc5端口拉低NOP();NOP();if (!(PINC & (BIT(4)))) //读取pc4端口,如果返回值是0则表明按键被按下,//则返回按键的值//以下依次对pc3-pc1逐个读取值,如果返回值为0 //则返回相应按键值{chTempKeyCode = 20;return chTempKeyCode;}else if (!(PINC & (BIT(3)))){chTempKeyCode = 19;return chTempKeyCode;}else if (!(PINC & (BIT(2)))){chTempKeyCode = 18;return chTempKeyCode;}else if (!(PINC & (BIT(1)))){chTempKeyCode = 17;return chTempKeyCode;}////////////////////////////////////////////////////////////////对15-13按钮进行扫描DDRC &= ~(BIT(1) | BIT(3) |BIT(2) | BIT(5)); //把端口pc1-pc3、pc5设置为输入DDRC |= BIT(4); //把pc4端口设为输出PORTC |= BIT(1) | BIT(2) | BIT(3) |BIT(4) | BIT(5);PORTC &= ~BIT(4); //把pc4端口拉低NOP();NOP();if (!(PINC & (BIT(3)))) //读取pc3端口,如果返回值是0则表明按键被按下,//则返回按键的值//以下依次对pc2-pc1逐个读取值,如果返回值为0 //则返回相应按键值{chTempKeyCode = 15;return chTempKeyCode;}else if (!(PINC & (BIT(2)))){chTempKeyCode = 14;return chTempKeyCode;}else if (!(PINC & (BIT(1)))){chTempKeyCode = 13;return chTempKeyCode;}////////////////////////////////////////////////////////////////对10-9按钮进行扫描DDRC &= ~(BIT(2) | BIT(1) |BIT(4) | BIT(5)); //把端口pc1-pc2、pc4-pc5设置为输入DDRC |= BIT(3); //把pc3端口设为输出PORTC |= BIT(1) | BIT(2) |BIT(3) | BIT(4) | BIT(5);PORTC &= ~BIT(3); //把pc3端口拉低NOP();NOP();if (!(PINC & (BIT(2)))) //读取pc2端口,如果返回值是0则表明按键被按下,//则返回按键的值{chTempKeyCode = 10;return chTempKeyCode;}else if (!(PINC & (BIT(1)))) //读取pc1端口,如果返回值是0则表明按键被按下, //则返回按键的值{chTempKeyCode = 9;return chTempKeyCode;}////////////////////////////////////////////////////////对5按钮进行扫描DDRC &= ~(BIT(4) | BIT(1) |BIT(3) | BIT(5)); //把端口pc1、pc3-pc4设置为输入DDRC |= BIT(2); //把pc2端口设为输出PORTC |= BIT(1) | BIT(2) | BIT(3) |BIT(4) | BIT(5);PORTC &= ~BIT(2); //把pc2端口拉低NOP();NOP();if (!(PINC & (BIT(1)))) //读取pc1端口,如果返回值是0则表明按键被按下, //则返回按键的值{chTempKeyCode = 5;return chTempKeyCode;}return chTempKeyCode; //返回按键值}UINT8 Get_Code (UINT8 chi){UINT8 chj;UINT8 Table[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};switch(chi){case 1: chj = Table[1];break; case 2: chj = Table[2];break; case 3: chj = Table[3];break; case 4: chj = Table[4];break; case 5: chj = Table[5];break; case 6: chj = Table[6];break; case 7: chj = Table[7];break; case 8: chj = Table[8];break; case 9: chj = Table[9];break; case 10: chj = Table[0];break; case 11: chj = Table[1];break; case 12: chj = Table[2];break; case 13: chj = Table[3];break; case 14: chj = Table[4];break; case 15: chj = Table[5];break; case 16: chj = Table[6];break; case 17: chj = Table[7];break; case 18: chj = Table[8];break; case 19: chj = Table[9];break; case 20: chj = Table[0];break; case 21: chj = Table[1];break; case 22: chj = Table[2];break; case 23: chj = Table[3];break; case 24: chj = Table[4];break; case 25: chj = Table[5];break; default: chj = 0xFF;}return chj;}。
按键功能实验报告总结(3篇)
第1篇一、实验背景按键作为电子设备中常见的输入装置,其功能丰富,应用广泛。
本实验旨在通过设计和实现一系列按键功能,加深对按键工作原理的理解,并提高电子设计实践能力。
二、实验目的1. 掌握按键的基本原理和电路设计方法。
2. 熟悉按键在不同应用场景下的功能实现。
3. 培养电子设计实践能力,提高问题解决能力。
三、实验内容1. 实验器材:51单片机最小核心电路、按键、LED灯、电阻、电容、面包板等。
2. 实验内容:(1)单按键控制LED灯闪烁(2)按键控制LED灯点亮与熄灭(3)按键控制LED灯亮度调节(4)按键实现数字时钟调整(5)按键实现多功能计数器(6)按键实现密码输入与验证四、实验步骤1. 根据实验要求,设计电路图,并选择合适的元器件。
2. 使用面包板搭建实验电路,包括单片机、按键、LED灯、电阻、电容等。
3. 编写程序,实现按键功能。
4. 对程序进行调试,确保按键功能正常。
5. 实验完成后,撰写实验报告。
五、实验结果与分析1. 单按键控制LED灯闪烁实验结果:按下按键,LED灯闪烁;松开按键,LED灯停止闪烁。
分析:本实验通过单片机定时器实现LED灯的闪烁。
当按键按下时,定时器开始计时;当定时器达到设定时间后,LED灯点亮;定时器继续计时,当达到设定时间后,LED灯熄灭。
如此循环,实现LED灯的闪烁。
2. 按键控制LED灯点亮与熄灭实验结果:按下按键,LED灯点亮;再次按下按键,LED灯熄灭。
分析:本实验通过单片机的I/O口控制LED灯的点亮与熄灭。
当按键按下时,单片机将I/O口置为高电平,LED灯点亮;当按键再次按下时,单片机将I/O口置为低电平,LED灯熄灭。
3. 按键控制LED灯亮度调节实验结果:按下按键,LED灯亮度逐渐增加;松开按键,LED灯亮度保持不变。
分析:本实验通过单片机的PWM(脉宽调制)功能实现LED灯亮度的调节。
当按键按下时,单片机调整PWM占空比,使LED灯亮度逐渐增加;松开按键后,PWM占空比保持不变,LED灯亮度保持不变。
相当经典的IO口扫描法
在做项目(工程)的时候,我们经常要用到比较多的按键,而且IO资源紧张,于是我们就想方设法地在别的模块中节省IO口,好不容易挤出一两个IO 口,却发现仍然不够用,实在没办法了就添加一个IC来扫键。
一个IC虽然价格不高,但对于大批量生产而且产品利润低的厂家来说,这是一笔不菲的开支! 那,我们能不能想到比较好的扫键方法:用最少的IO口,扫最多的键?可以吗?举个例:给出5个IO口,能扫多少键?有人说是2*3=6个,如图一:图一对,大部分技术参考书都这么做,我们也经常这样做:用3个IO口作行扫描,2个IO作列检测(为方便描述,我们约定:设置某一IO口输出为“0”――称其为“扫某IO口”)。
用行线输出扫键码,列线检测是否有按键的查询方法进行扫键。
扫键流程:在行线依次输出011,101,110扫键值,行线每输出一个扫键值,列线检测一次。
当列线检测到有按键时,结合输出的扫键值可以判断相应的按键。
但是,5个IO真的只能扫6个键吗?有人说可以扫9个,很聪明!利用行IO 与地衍生3个键(要注意上拉电阻),如图二:图二扫键流程:先检测3个行IO口,对K1’,K2’,K3’进行扫键,之后如上述2*3扫键流程。
5个IO口能扫9个键,够厉害吧,足足比6个键多了1/2!动动脑,还能不能再多扫几个?就几个?一个也行!好,再想一下,硬是被逼出来了!如图三:图三不多不少,正好10个键!这种扫键方式比较少见吧!漂亮!扫键流程:设IO1输出为“0”,检测IO2…IO5,若判断有相应健按下,则可知有健;若无键,则继续扫键:设IO2输出为“0”,检测IO3,IO4,IO5,判断有无键按下,如此类推。
这里应注意:当扫某一IO口(输出为“0”)时,不要去检测已经扫过的IO 口。
如:此时设置IO2输出为“0”,依次检测IO3,IO4,IO5,但不要去检测IO1,否则会出错(为什么,请思考)。
感觉怎么样?不错吧!让我们再看看图三,好有成就感!看着,看着……又看到了什么?快!见图四:图四真强!被您看出20个键!多了一个对称的三角形。
单片机课程设计—8个按键控制8个LED自动设定控制流水灯
-1-江苏安全技术学院实习总结报告实习单位江苏安全技术职业学院实习起止时间 2019 年 11 月 17 日至 2019 年 12 月 11 日指导教师所在院(系) 电气工程系班 级 电梯技术 2 班学生姓名 艾孜提艾力·阿迪力·玉苏甫江学号20183102932019 年 12 月 16 日江苏安全技术职业学院-1-目录第 1 章 按键控制流水灯设计.................................................................................... 1 1.1 实习目的 ................................................................... 错误!未定义书签。
1.2 实习要求 ................................................................... 错误!未定义书签。
第 2 章 电路工作原理................................................................................................ 2 2.1 STC89C52 单片机工作原理 ....................................................................... 2 2.2 LED 工作原理.............................................................................................. 3 2.3 按键工作原理 .............................................................................................. 3 2.4 整体电路图 .................................................................................................. 5 2.5 本章小结 ..................................................................................................... 6第 3 章 C 程序设计.................................................................................................... 7 3.1 程序设计流程图 ......................................................................................... 7 3.2 实验结果 ...................................................................................................... 8 3.3 本章小结 ..................................................................................................... 9总结及体会................................................................................................................ 10 参考文献.................................................................................................................... 11 附录............................................................................................................................ 12-1--2-第1章 按键控制流水灯设计1.1 实习目的本次实习以 STC89C52 单片机为控制核心。
AD按键扫描与蜂鸣器
AD按键扫描与蜂鸣器第三节:AD按键扫描与蜂鸣器(1)开场白:AD按键可以实现一个IO口驱动几个按键的目的,以鸿哥的经验,一个IO口控制的按键数量最好不要超过3个。
从实际应用来考虑,独立按键的方式最好,其次是行列按键,最次是AD按键。
(2)功能需求:每按一个按键,蜂鸣器就响一次。
(3)硬件原理:(a)用4个电阻竖着串联起来,最上端接5V,最下端接地。
从上往下,最上端接5V的算第一个节点,最下端接地算最后一个节点,共5个节点。
用一个带AD的IO口连接到第2个节点上,此节点上连接第一个按键,按键的另一端接地。
以此方式,第二个按键连接到第3个节点,第三个按键连接到第4个节点。
这4个电阻的目的主要是用来分压,靠不同的电压来识别不同的按键。
(b)用1个IO经过8050三极管来驱动有源蜂鸣器,有源蜂鸣器通电就一直响,断电就停止。
(4)源码适合的单片机:PIC16f73,晶振为4MHz(5)源代码讲解如下:#include //包含芯片相关头文件//补充说明:吴坚鸿程序风格是这样的,凡是输出IO后缀都是_dr,凡是输入的//IO后缀都//是_sr#define beep_dr RB0 //蜂鸣器输出//补充说明:吴坚鸿程序风格是这样的,凡是做延时计数阀值的常量//前缀都用cnt_表示。
凡是延时常量,都应该根据上机实际情况来调整出最佳的数值#define cnt_delay_cnt1 40 //按键去抖动延时阀值#define cnt_voice_time 75 //蜂鸣器响的声音长短的延时阀值#define cnt_key_nc 185 //没有按键按下时电压对应的AD数值#define cnt_key1_up 185 //1号按键按下时电压对应的AD数值上限#define cnt_key2_down 117 //2号按键按下时电压对应的AD 数值下限#define cnt_key2_up 137 //2号按键按下时电压对应的AD数值上限#define cnt_key3_down 160 //3号按键按下时电压对应的AD 数值下限#define cnt_key3_up 175 //3号按键按下时电压对应的AD数值上限//补充说明:吴坚鸿程序风格是这样的,凡是按键扫描函数都放在定时中//断里,凡是按键服务程序都是放在main函数循环里。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
5个IO口最多能扫描多少个按键?简介:在做项目(工程)的时候,我们经常要用到比较多的按键,而且IO资源紧张,于是我们就想方设法地在别的模块中节省IO口,好不容易挤出一两个IO口,却发现仍然不够用,实在没办法了就添加一个IC来扫键。
一个IC虽然价 ...在做项目(工程)的时候,我们经常要用到比较多的按键,而且IO资源紧张,于是我们就想方设法地在别的模块中节省IO口,好不容易挤出一两个IO口,却发现仍然不够用,实在没办法了就添加一个IC来扫键。
一个IC虽然价格不高,但对于大批量生产而且产品利润低的厂家来说,这是一笔不菲的开支!那,我们能不能想到比较好的扫键方法:用最少的IO口,扫最多的键?可以吗?举个例:给出5个IO口,能扫多少键?有人说是2*3=6个,如图一:图一对,大部分技术参考书都这么做,我们也经常这样做:用3个IO口作行扫描,2个IO作列检测(为方便描述,我们约定:设置某一IO口输出为“0”――称其为“扫某IO口”)。
用行线输出扫键码,列线检测是否有按键的查询方法进行扫键。
扫键流程:在行线依次输出011,101,110扫键值,行线每输出一个扫键值,列线检测一次。
当列线检测到有按键时,结合输出的扫键值可以判断相应的按键。
但是,5个IO真的只能扫6个键吗?有人说可以扫9个,很聪明!利用行IO与地衍生3个键(要注意上拉电阻),如图二:图二扫键流程:先检测3个行IO口,对K1’,K2’,K3’进行扫键,之后如上述2*3扫键流程。
5个IO口能扫9个键,够厉害吧,足足比6个键多了1/2!动动脑,还能不能再多扫几个?就几个?一个也行!好,再想一下,硬是被逼出来了!如图三:图三不多不少,正好10个键!这种扫键方式比较少见吧!漂亮!扫键流程:设IO1输出为“0”,检测IO2…IO5,若判断有相应健按下,则可知有健;若无键,则继续扫键:设IO2输出为“0”,检测IO3,IO4,IO5,判断有无键按下,如此类推。
这里应注意:当扫某一IO口(输出为“0”)时,不要去检测已经扫过的IO口。
如:此时设置IO2输出为“0”,依次检测IO3,IO4,IO5,但不要去检测IO1,否则会出错(为什么,请思考)。
感觉怎么样?不错吧!让我们再看看图三,好有成就感!看着,看着……又看到了什么?快!见图四:图四真强!被您看出20个键!多了一个对称的三角形。
可是,像这样的排列能正确扫20个键吗?回答是肯定的:不能!上下三角形相互对称,其对称扫出的键无法区别。
有没有注意到分析图三时提到的注意点?(à“当扫某IO口时,不要去检测已经扫过的IO口,否则会出错”)我们分析一下图四:当IO1输出“0”时,按下K11或K11’键都能被IO2检测到,但IO2检测却无法区别K11和K11’键!同理,不管扫哪个IO口,都有两个对称的键不能区分。
我们假想,如果能把对称键区分开来,我们就能正常地去判断按键。
我们在思考:有没有单向导通性器件?有!见图五!图五很巧妙的思路!利用二极管的单向导通性,区别两个对称键。
扫键思路:对逐个IO口扫键,其他四个IO口可以分别检测其所在的四个按键。
这样,就不会有分析图三时提到的注意点。
够酷吧!等等,大家先别满足现状,我们再看一下图二,是不是有点启发?对,我们再分析一下“用5个IO口对地衍生的5个键”。
看图六:图六25个键!5个IO口扫出25个键!先别激动,我们再分析一下它的可行性,分析通得过才能真正使用。
假设扫键流程:先扫对地的5个键,再如图五扫键。
先扫对地5个键,判断没有按键,接着对逐一对IO口进行扫键。
但当对某一IO口扫键时,如果有对地的键按下,这时有可能会误判按键,因为对地键比其他键有更高的响应优先级。
例如:扫IO1,IO1输出“0”,恰好此时K62按下,IO2检测到有按键,那就不能判断是K11还是K62。
我们可以在程序上避免这种按键误判:若IO2检测到有按键,那下一步就去判断是否有对地键按下,如果没有,那就可以正确地判断是K11了。
我们小结扫键个数S:S = (N-1)*N + N ――启用二极管S = (N-1)*N /2 + N ――省掉二极管经典吗?太经典了!!告诉大家一个小道消息:第一个设计出此电路的人是一个美国大佬,他(她?)还为此申请了专利!示例代码如下(出自孩儿们之手哈):硬件描述:键盘连接说明;IO2 PC2IO3 PC3IO4 PC4IO5 PC5核心函数:/************************************************************ 函数说明:五个端口扫描25个键盘的函数** 输入:无** 输出:键盘编号** 调用函数:无************************************************************/UINT8 _25Key_Scan(void){UINT8 i = 0,Key_Num = 0;//扫描最下面一行开关DDRC |= BIT(PC1)|BIT(PC2)|BIT(PC3)|BIT(PC4)|BIT(PC5); PORTC |= BIT(PC1)|BIT(PC2)|BIT(PC3)|BIT(PC4)|BIT(PC5);NOP();NOP();for(i = 1; i <= 5; i++){if(!(PINC & BIT(i))) //PCi=0{Key_Num = i+20;return Key_Num;}}//扫描第一行开关DDRC |= BIT(PC1); //PC1 输出PORTC &= ~BIT(PC1); //PC1=0DDRC &= ~(BIT(PC2)|BIT(PC3)|BIT(PC4)|BIT(PC5)); //PC2-PC5 输入PORTC |= BIT(PC2)|BIT(PC3)|BIT(PC4)|BIT(PC5); //PC2~PC5=1NOP();for(i = 2; i <=5; i++){if(!((PINC & BIT(i)))){Key_Num = i-1;return Key_Num;}}//扫描第二行开关DDRC |= BIT(PC2); //PC2 输出PORTC &= ~BIT(PC2); //PC2=0DDRC &= ~(BIT(PC1)|BIT(PC3)|BIT(PC4)|BIT(PC5)); //PC1、PC3-PC5 输入PORTC |= BIT(PC1)|BIT(PC3)|BIT(PC4)|BIT(PC5); //PC1、PC3~PC5=1if(!(PINC & BIT(1))){Key_Num = 5;return Key_Num;}else{for(i = 3; i <= 5; i++){if(!(PINC & BIT(i))){Key_Num = i+3;return Key_Num;}}}//扫描第三行开关DDRC |= BIT(PC3); //PC3 输出PORTC &= ~BIT(PC3); //PC2=0DDRC &= ~(BIT(PC1)|BIT(PC2)|BIT(PC4)|BIT(PC5)); //PC1、PC2、PC4、PC5 输入PORTC |= BIT(PC1)|BIT(PC2)|BIT(PC4)|BIT(PC5); //PC1、PC2、PC4、PC5=1if(!(PINC & BIT(1))){Key_Num = 9;return Key_Num;}else if(!(PINC & BIT(2))){Key_Num = 10;return Key_Num;}else if(!(PINC & BIT(4))){Key_Num = 11;return Key_Num;}else if(!(PINC & BIT(5))){Key_Num = 12;return Key_Num;}//扫描第四行开关DDRC |= BIT(PC4); //PC4 输出PORTC &= ~BIT(PC4); //PC4=0DDRC &= ~(BIT(PC1)|BIT(PC2)|BIT(PC3)|BIT(PC5)); //PC1~PC3、PC5 输入PORTC |= BIT(PC1)|BIT(PC2)|BIT(PC3)|BIT(PC5); //PC1~PC3、PC5=1for(i = 1; i <= 3; i++){if(!(PINC & BIT(i))){Key_Num = i+12;return Key_Num;}}if(!(PINC & BIT(5))){Key_Num = 16;return Key_Num;}//扫描第五行开关DDRC |= BIT(PC5); //PC5 输出PORTC &= ~BIT(PC5); //PC5=0DDRC &= ~(BIT(PC1)|BIT(PC2)|BIT(PC3)|BIT(PC4)); //PC1-PC4 输入PORTC |= BIT(PC1)|BIT(PC2)|BIT(PC3)|BIT(PC4); //PC1~PC4=1for(i = 1; i <= 4; i++){if(!(PINC & BIT(i))){Key_Num = i+16;return Key_Num;}}return Key_Num;//循环的方法实现使用的是PORTD口/*uint8 i = 0, j =0;DDRD = 0;PORTD = 0xff;for(i = 0; i< 5; i++){if(!(PIND&BIT(i))){return i+1;}}for(i = 0; i < 5; i++){DDRD = BIT(i);PORTD = ~BIT(i);for(j = 0; j < 5; j++){if((!(PIND&BIT(j)))&&(j != i)){if(j>=i)return i*4+j+5;return i*4+j+6;}}}return 0;*/}根据最新成果,如果只考虑单个按键被按下的情况,键盘已经可以扩展为25 + 5 * (4 * 3 / 2)= 25 + 30 = 55个按键了……实现这种方法的原理其实很简单。
假设,我们考虑如何解决K11和K12同时被按下的解决方案,此时,只需要:1、将IO1设置为输入并开启上蜡电阻2、将IO2设置为输出高电平,将其余IO设置为输出低电平3、检测IO1的电平来判断K11是否被按下4、将IO3设置为输出高电平,将其余IO设置为输出低电平5、检测IO1的电平来判断K12是否被按下这样就可以单独区别K11和K12了。