1602显示原理及应用(课件) - 图文 联系客服

发布时间 : 星期六 文章1602显示原理及应用(课件) - 图文更新完毕开始阅读5f49e3a450e2524de5187ed0

位,并将相关消抖动的和连击时间的宏定义改小即可。然后在主程序类似下面这样写即可 if( KeyTime ) //定时扫描时间到 {

KeyValue = u8_ReadKey_f() ; }

具体的工作就交给您去完成啦。

看看效果: 按键单击

连发时候的截图

至此,关于单个按键的学习就告一段落了,您是否已经明白了。如果您还不明白,那么把这个程序好好的看看,并画下流程图,分析分析。估计您就会恍然大悟。关键是思路要转换过来。 下面我们来看看多个按键的情况吧

一般情况下,如果多个按键每个都直接接在单片机的I/O上的话会占用很多的I/O资源。比较合理的一种

做法是,按照行列接成矩阵的形式。按键接在每一个的行列的相交处。这样对于m行n列的矩阵,可以接的按键总数是m*n。这里我们以常见的4*4矩阵键盘来讲解矩阵键盘的编程。

上图就是矩阵键盘的一般接法。

这里我们要介绍一种快速的键盘扫描法:线反转法(或者称为行列翻转法)。具体流程如下。首先,让单片机的行全部输出0,列全部输出1,读取列的值(假设行接P3口的高四位,列接低四位)。即P3= 0x0f ; 此时读列的值,如果有键按下,则相应的列读回来的值应该为低。譬如此时读回来的值为 0x0e ; 即按键列的位置已经确定。这时反过来,把行作为输入,列作为输出,即P0 = 0xf0 ;此时再读行的值,如果按键仍然被按下,则相应的行的值应该为低,如果此时读回来的值为0xe0,则确定了行的位置 。说到这里,您应该笑了,知道了一个按键被按下的行和列的位置,那么就可以肯定确定它的位置了。我们把读回来的行值和列值进行或运算。即 0xe0 | 0x 0e 即 0xee。那么0xee就是我们按下的按键的键值了。怎么样。只需几步就可以判断所有的键值,简单吧。下面再结合一个例子具体看看。 /****************************************** * 此模块所需相关支持库 *

******************************************/ #include\

#define uint8 unsigned char #define uint16 unsigned int

/**************************************** * 与硬件连接相关的定义及宏定义和操作宏 *

*****************************************/

#define KEYBOARD P3 //键盘连接到单片机上的端口位置

#define READ_ROW_ENLABLE KEYBOARD = 0x0f ; //读端口之前先把相应口置位(由基本51单片机特性决定的)

#define READ_COL_ENLABLE KEYBOARD = 0xf0 ; // 根据实际硬件连接情况修改

/***************************************** * 模块内相关的宏定义及常数宏 *

******************************************/ #define NOKEY 0xff //定义无键按下时的返回值 #define DELAY_COUNT 2 //消抖时间常数

/***************************************** * 此模块所需的全局或者外部变量 *

*****************************************/ bit bdata StartScan = 0 ;//此变量需放在定时中断中置位

/***************************************** * 按键扫描函数,按下去后经去抖,确定按下 * * 则返回键值0~15;无键按下则返回0xff ; * * 此函数需要定时器的支持(去抖....) *

*****************************************/ uint8 u8_KeyBoardScan_f() {

static uint8 DelayCount = 0 ; uint8 KeyValueRow = 0 ; uint8 KeyValueCol = 0 ; uint8 KeyValue = 0 ;

if( StartScan ) //开始扫描,StartScan在定时中断中置位 {

StartScan = 0 ; //清除开始扫描标志位,避免多次重复执行扫描程序 //读入按键状态前先向相应端口写1(由基本51单片机硬件结构决定) READ_ROW_ENLABLE

if( ( KEYBOARD & 0x0f ) != 0x0f ) //判断是否有键按下 {

DelayCount++;

if( DelayCount <= DELAY_COUNT ) //有键按下则判断延时去抖的时间是否达到

{

return NOKEY ; }

else //消除了抖动 {

if( ( KEYBOARD & 0x0f ) != 0x0f ) //再次判断是否按键真的按下 {

DelayCount = 0 ; //确定按下后,延时去抖计时器清0 KeyValueRow = KEYBOARD & 0x0f ; //取得行码

//准备读列,先向相应端口写1(由基本51单片机硬件结构决定)

READ_COL_ENLABLE

if ( (KEYBOARD & 0xf0) != 0xf0 ) //反转,读列码 {

KeyValueCol = KEYBOARD & 0xf0 ; //取得列码

//合并取得的行码和列码,即是相应按键的键值 switch( KeyValueCol | KeyValueRow) {

case 0x77 : KeyValue = 0 ; break ; case 0xb7 : KeyValue = 1 ; break ; case 0xd7 : KeyValue = 2 ; break ; case 0xe7 : KeyValue = 3 ; break ; case 0x7b : KeyValue = 4 ; break ; case 0xbb : KeyValue = 5 ; break ; case 0xdb : KeyValue = 6 ; break ; case 0xeb : KeyValue = 7 ; break ; case 0x7d : KeyValue = 8 ; break ; case 0xbd : KeyValue = 9 ; break ; case 0xdd : KeyValue = 10 ;break ; case 0xed : KeyValue = 11 ;break ; case 0x7e : KeyValue = 12 ;break ; case 0xbe : KeyValue = 13 ;break ; case 0xde : KeyValue = 14 ;break ; case 0xee : KeyValue = 15 ;break ; default : return NOKEY ; }

return KeyValue ;