这个例程也是开发板上面的一个经典例程,我对程序的框架进行了修改,更适合以后的调用。具体的4*4键盘扫描原理较为基础这里不再赘述,这里我认为比较重要的是要养成一个良好的写程序的习惯,想4*4键盘扫描这样的函数可以写成一个固定的C或者H文件,便于以后调用。先看看主程序:
/***********************************************
程序功能:扫描4X4键盘并将键值在数码管上显示
------------------------------------------------
测试说明:按动K1~K16按键,观察数码管显示
************************************************/
#include #include "Keypad.C" //数码管7位段码:0--f unsigned char scandata[16] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8, 0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e}; //记录显示位数的全局变量 unsigned char cnt = 0; //显示缓存 unsigned char Dispbuf[2]; //引用外部变量的声明 extern unsigned char key_Pressed; extern unsigned char key_val; extern unsigned char key_Flag; /********************主函数********************/ void main(void) { /*下面六行程序关闭所有的IO口*/ P1DIR = 0XFF;P1OUT = 0XFF; P2DIR = 0XFF;P2OUT = 0XFF; P3DIR = 0XFF;P3OUT = 0XFF; P4DIR = 0XFF;P4OUT = 0XFF; P5DIR = 0XFF;P5OUT = 0XFF; P6DIR = 0XFF;P6OUT = 0XFF; P6DIR |= BIT2;P6OUT |= BIT2; //关闭电平转换 WDTCTL = WDT_ADLY_1_9; //设置内部看门狗工作在定时器模式,1.9ms中断一次 IE1 |= WDTIE; //使能看门狗中断 _EINT(); //打开全局中断 Init_Keypad(); while(1) { Key_Event(); if(key_Flag == 1) { key_Flag = 0; Dispbuf[1] = key_val / 10; Dispbuf[0] = key_val % 10; } } } /******************************************* 函数名称:watchdog_timer 功 能:看门狗中断服务函数,在这里输出数码管的 段选和位选信号 参 数:无 返回值 :无 ********************************************/ #pragma vector=WDT_VECTOR __interrupt void watchdog_timer(void) { P4OUT = 0xff; P5OUT = scandata[Dispbuf[cnt]]; //输出段选信号 P4OUT &= ~(1 << (cnt+2)); //输出位选信号 cnt++; //位计数变量在0~1之间循环 if(cnt == 2) cnt = 0; } 主程序较为简单,具体的原理参见上一个笔记,在主程序中与键盘扫描相关的函数被击中在Keypad.C中,需要说明的是在主函数中需要对Keypad.C的部分变量做声明,这样才能使用Keypad.C中的变量。Keypad.C代码如下: /******************************************************** 4*4键盘扫描函数 作者:孙浩 修改时间:2010.8.2 程序说明: 此程序以开发板的例程做部分修改,更方便程序调用。 在调用之前需要注意需要在主函数中对程序中使用的变量做外部变量声明 需要在主函数中声明的变量如下: //引用外部变量的声明 extern unsigned char key_Pressed; //按键是否被按下:1--是,0--否 extern unsigned char key_val; //存放键值 extern unsigned char key_Flag; //按键是否已放开:1--是,0--否 另外对应的键值可以在本文件的全局变量中修改,只需要对应修改 数组uchar key_Map[]的对应的值即可。 调用示例如下: Init_Keypad(); //先进行初始化 while(1) { Key_Event(); //在死循环中进行键值扫描 if(key_Flag == 1)//用来判断有无按键按下,从而读取键值进行操作 { key_Flag = 0;//key_Flag需要手动清零 } } **********************************************************/ #include //相应的函数声明 void Init_Keypad(void);//键盘初始化 void Check_Key(void); void delay(); void Key_Event(void);//读取键盘函数,在使用时通过此函数进行键盘扫描 //选择对应的端口 #define KEYOUT P1OUT #define KEYIN P1IN #define KEYDIR P1DIR typedef unsigned char uchar; typedef unsigned int uint; /***************全局变量***************/ uchar key_Pressed; //按键是否被按下:1--是,0--否 uchar key_val; //存放键值 uchar key_Flag; //按键是否已放开:1--是,0--否 //设置键盘逻辑键值与程序计算键值的映射 uchar key_Map[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}; /******************************************* 函数名称:Init_Keypad 功 能:初始化扫描键盘的IO端口 参 数:无 返回值 :无 ********************************************/ void Init_Keypad(void) { KEYDIR = 0xf0; //KEY.0~KEY.3设置为输入状态, KEY.4~KEY.7设置为输出状态 KEYOUT |= 0xf0; // KEY.4~KEY.7输出高电平 key_Flag = 0; key_Pressed = 0; key_val = 0; } /********************************************* * Check_Key(),检查按键,确认键值 *********************************************/ /******************************************* 函数名称:Check_Key 功 能:扫描键盘的IO端口,获得键值 参 数:无 返回值 :无 ********************************************/ void Check_Key(void) { uchar row ,col,tmp1,tmp2; tmp1 = 0x80; for(row = 0;row < 4;row++) //行扫描 { KEYOUT = 0xf0; //KEY.4~KEY.7输出全1 KEYOUT -= tmp1; //KEY.4~p1.7输出四位中有一个为0 tmp1 >>=1; if ((KEYIN & 0x0f) < 0x0f) //是否KEYIN的KEY.0~KEY.3中有一位为0 { tmp2 = 0x01; // tmp2用于检测出那一位为0 for(col = 0;col < 4;col++) // 列检测 { if((KEYIN & tmp2) == 0x00) // 是否是该列,等于0为是 { key_val = key_Map[row * 4 + col]; // 获取键值 return; // 退出循环 } tmp2 <<= 1; // tmp2右移1位 } } } } /******************************************* 函数名称:delay 功 能:延时约15ms,完成消抖功能 参 数:无 返回值 :无 ********************************************/ void delay() { uint tmp; for(tmp = 12000;tmp > 0;tmp--); } /******************************************* 函数名称:Key_Event 功 能:检测按键,并获取键值 参 数:无 返回值 :无 ********************************************/ void Key_Event(void) { uchar tmp; KEYOUT &= 0x00; // 设置KEYOUT全为0,等待按键输入 tmp = KEYIN; // 获取 p1IN if ((key_Pressed == 0x00)&&((tmp & 0x0f) < 0x0f)) //如果有键按下 { key_Pressed = 1; // 如果有按键按下,设置key_Pressed标识 delay(); //消除抖动 Check_Key(); // 调用check_Key(),获取键值 } else if ((key_Pressed == 1)&&((tmp & 0x0f) == 0x0f)) //如果按键已经释放 { key_Pressed = 0; // 清除key_Pressed标识 key_Flag = 1; // 设置key_Flag标识 } else { _NOP(); } } 具体的注意提防都已经在注释中做了说明,在原来的程序中这个文件是分为Keypad.C和Keypad.h两个文件,键盘扫描函数的声明单独为一个头文件,我觉得并不是特别需要。源程序中全局变量是单独列为一个头文件gdata.h的。这样在全局变量比较多的情况下可以使程序更有条理可以参考。
上一篇:MSP430学习笔记3-PWM的产生
下一篇:在msp430上使用S-100
推荐阅读最新更新时间:2024-11-16 21:30
设计资源 培训 开发板 精华推荐
- #第七届立创电赛#N32仪器
- LTC3638IMSE 5V 至 140V 输入至 5V/250mA 输出和 20kHz 最小突发频率的典型应用电路
- 【已完成】2.13-墨水屏驱动&老王0.6元的OLED屏幕已验证
- 基本 12 位、12us 逐次逼近 ADC
- FRDM-TWRPI: Tower Plug-In (TWRPI) Adaptor Board for Freedom Development Platform
- RGB灯验证板
- ADP7118RD-EVALZ,用于评估 ADP7118 20V、200mA 低噪声 CMOS LDO 的 TSOT 评估板
- 使用 MaxLinear, Inc 的 SPX385S-1.2/TR 的参考设计
- AL5802 30V 可调电流吸收线性 LED 驱动器的典型应用
- 用于电源管理的 5V DC 至 DC 单输出电源