键盘扫描及动态LED 显示实验报告

键盘扫描及动态LED 显示实验报告
键盘扫描及动态LED 显示实验报告

《单片机》实验报告

一.实验题目

实验4.7 7279 键盘扫描及动态LED 显示实验

二.实验要求

本实验利用7279 进行键盘扫描及动态LED 数码管显示控制。

三.实验源程序

#include

//*** 函数定义***

void long_delay(void); // 长延时

void short_delay(void); // 短暂延时

void delay10ms(unsigned char); // 延时10MS

void write7279(unsigned char, unsigned char); // 写入到HD7279

unsigned char read7279(unsigned char); // 从HD7279读出

void send_byte(unsigned char); // 发送一个字节

#define uchar unsigned char

#define uint unsigned int

uchar

bianma[]={0x1b,0x13,0x0b,0x03,0x1a,0x12,0x0a,0x02,0x19,0x11,0x09,0x01,0x18,0x10,0x08,0x 00};

unsigned char receive_byte(void); // 接收一个字节

//*** 变量及I/O口定义***

unsigned char digit[5];

unsigned char key_number, j, k,mk; //mk为按键次数计数值

unsigned int tmr;

unsigned long wait_cnter;

sbit cs=P1^0; // cs at P1.0

sbit clk=P1^1; // clk 连接于P1.1

sbit dat=P1^2; // dat 连接于P1.2

sbit key=P1^3; // key 连接于P1.3

void write7279(unsigned char cmd, unsigned char dta) {

send_byte (cmd);

send_byte (dta);

}

unsigned char read7279(unsigned char command) {

send_byte(command);

return(receive_byte());

}

void send_byte( unsigned char out_byte)

{

unsigned char i;

cs=0;//芯片使能

long_delay();

for (i=0;i<8;i++) //分8次移入数据

{

if (out_byte&0x80)//先传高位

{

dat=1;

}

else

{

dat=0;

}

clk=1;

short_delay();

clk=0;

short_delay();

out_byte=out_byte*2;//数据左移

}

dat=0;

}

unsigned char receive_byte(void)

{

unsigned char i, in_byte;

dat=1; // set to input mode

long_delay();

for (i=0;i<8;i++)//分8次读入数据高位在前

{

clk=1;

short_delay();

in_byte=in_byte*2; //数据左移

if (dat)

{

in_byte=in_byte|0x01;

}

clk=0;

short_delay();

}

dat=0;

return (in_byte);

}

void long_delay(void)

{

unsigned char i;

for (i=0;i<0x30;i++);

}

void short_delay(void)

{

unsigned char i;

for (i=0;i<8;i++);

}

void main(){

uchar jianpan,i,num;

send_byte(0xa4); //全部复位指令

while(1){

if(key==0){ //如果按键按下

send_byte(0x15); //读键盘指令

jianpan=receive_byte(); //接收键盘数据// P0=num;

for(i=0;i<16;i++){

if(jianpan==bianma[i]){ //等于判断一定是双等于号

num=i;

break;

}

}

send_byte(0xa1);

write7279(0xc8,num);

while(key==0);

}

} }

实验报告七-键盘扫描及显示实验

信息工程学院实验报告 课程名称:微机原理与接口技术 实验项目名称:键盘扫描及显示实验 实验时间: 班级: 姓名: 学号: 一、实 验 目 的 1. 掌握 8254 的工作方式及应用编程。 2. 掌握 8254 典型应用电路的接法。 二、实 验 设 备 了解键盘扫描及数码显示的基本原理,熟悉 8255 的编程。 三、实 验 原 理 将 8255 单元与键盘及数码管显示单元连接,编写实验程序,扫描键盘输入,并将扫描结果送数码管显示。键盘采用 4×4 键盘,每个数码管显示值可为 0~F 共 16 个数。实验具体内容如下:将键盘进行编号,记作 0~F ,当按下其中一个按键时,将该按键对应的编号在一个数码管上显示出来,当再按下一个按键时,便将这个按键的编号在下一个数码管上显示出来,数码管上可以显示最近 6 次按下的按键编号。 键盘及数码管显示单元电路图如图 7-1 和 7-2 所示。8255 键盘及显示实验参考接线图如图 7-3 所示。 图 7-1 键盘及数码管显示单元 4×4 键盘矩阵电路图 成 绩: 指导老师(签名):

图 7-2 键盘及数码管显示单元 6 组数码管电路图 图 7-3 8255 键盘扫描及数码管显示实验线路图 四、实验内容与步骤 1. 实验接线图如图 7-3 所示,按图连接实验线路图。

图 7-4 8255 键盘扫描及数码管显示实验实物连接图 2.运行 Tdpit 集成操作软件,根据实验内容,编写实验程序,编译、链接。 图 7-5 8255 键盘扫描及数码管显示实验程序编辑界面 3. 运行程序,按下按键,观察数码管的显示,验证程序功能。 五、实验结果及分析: 1. 运行程序,按下按键,观察数码管的显示。

单片机矩阵键盘扫描程序

#include #include #define uint unsigned int #define uchar unsigned char sbit E=P2^7; //1602使能引脚 sbit RW=P2^6; //1602读写引脚 sbit RS=P2^5; //1602数据/命令选择引脚 uint keyflag ; //键盘正在读取标志位,如果Keyflag为1 ,表示正在读取键盘,停止其他功能; char x,y,m,n,c; //Keyflag为0,读取键盘结束,恢复其他功能 char flag1=0; //频率范围10~1000Hz uchar Hrate = 0; //一个周期内高点平占据时间 uchar Lrate = 0; //一个周期内低电平占据时间 uint FREQ0; //定时器T0的计数变量// uint FREQ1; //定时器T1的计数变量// sbit P2_1=P2^0; //设置P2.1,作为信号输出口// uint disbuf[3]; uint figure=0; int sum2=0; int sum1=0; int flag=0; uint count=0; uint max=0; uint disbuf_temp=0; /******************************************************************** * 名称: 1602显示延时函数delay() * 功能: 延时,延时时间大概为5US。

* 输出: 无 ***********************************************************************/ void delay() { _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); } /******************************************************************** * 名称: bit Busy(void) * 功能: 这个是一个读状态函数,读出函数是否处在忙状态 * 输入: 输入的命令值 * 输出: 无 ***********************************************************************/ bit Busy(void) { bit busy_flag = 0; RS = 0; RW = 1; E = 1; delay(); busy_flag = (bit)(P0 & 0x80); E = 0; return busy_flag; } /******************************************************************** * 名称: wcmd(uchar del) * 功能: 1602命令函数 * 输入: 输入的命令值 * 输出: 无 ***********************************************************************/ void wcmd(uchar del) { while(Busy()); RS = 0; RW = 0; E = 0; delay(); P0 = del; delay(); E = 1;

经典的矩阵键盘扫描程序

键盘是单片机常用输入设备,在按键数量较多时,为了节省I/O口等单片机资源,一般采取扫描的方式来识别到底是哪一个键被按下。即通过确定被按下的键处在哪一行哪一列来确定该键的位置,获取键值以启动相应的功能程序。 4*4矩阵键盘的结构如图1(实物参考见万用板矩阵键盘制作技巧)。在本例中,矩阵键盘的四列依次接到单片机的P1.0~P1.3,四行依次接到单片机的P1.4~P1.7;同时,将列线上拉,通过10K电阻接电源。 查找哪个按键被按下的方法为:一个一个地查找。 先第一行输出0,检查列线是否非全高; 否则第二行输出0,检查列线是否非全高; 否则第三行输出0,检查列线是否非全高; 如果某行输出0时,查到列线非全高,则该行有按键按下; 根据第几行线输出0与第几列线读入为0,即可判断在具体什么位置的按键按下。 下面是具体程序:

void Check_Key(void) { unsigned char row,col,tmp1,tmp2; tmp1 = 0x10; //tmp1用来设置P1口的输出,取反后使 P1.4~P1.7中有一个为0 for(row=0;row<4;row++) // 行检测 { P1 = 0x0f; // 先将p1.4~P1.7置高 P1 =~tmp1; // 使P1.4~p1.7中有一个为0 tmp1*=2; // tmp1左移一位 if ((P1 & 0x0f) < 0x0f) // 检测P1.0~P1.3中是否有一位为0,只要有,则说明此行有键按下,进入列检测 { tmp2 = 0x01; // tmp2用于检测出哪一列为0 for(col =0;col<4;col++) // 列检测 { if((P1 & tmp2)==0x00) // 该列如果为低电平则可以判定为该列 { key_val =key_Map[ row*4 +col ]; // 获取键值,识别按键;key_Map为按键的定义表 return; // 退出循环 } tmp2*=2; // tmp2左移一位 } } } } //结束 这是一种比较经典的矩阵键盘识别方法,实现起来较为简单,程序短小精炼。

51单片机矩阵键盘扫描程序

/*----------------------------------------------- 名称:矩阵键盘依次输入控制使用行列逐级扫描 论坛:https://www.360docs.net/doc/582337019.html, 编写:shifang 日期:2009.5 修改:无 内容:如计算器输入数据形式相同从右至左使用行列扫描方法 ------------------------------------------------*/ #include //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义 #define DataPort P0 //定义数据端口程序中遇到DataPort 则用P0 替换 #define KeyPort P1 sbit LATCH1=P2^2;//定义锁存使能端口段锁存 sbit LATCH2=P2^3;// 位锁存 unsigned char code dofly_DuanMa[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f, 0x77,0x7c,0x39,0x5e,0x79,0x71};// 显示段码值0~F unsigned char code dofly_WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//分别对应相应的数码管点亮,即位码 unsigned char TempData[8]; //存储显示值的全局变量 void DelayUs2x(unsigned char t);//us级延时函数声明 void DelayMs(unsigned char t); //ms级延时 void Display(unsigned char FirstBit,unsigned char Num);//数码管显示函数 unsigned char KeyScan(void);//键盘扫描 unsigned char KeyPro(void); void Init_Timer0(void);//定时器初始化 /*------------------------------------------------ 主函数 ------------------------------------------------*/ void main (void) { unsigned char num,i,j; unsigned char temp[8]; Init_Timer0(); while (1) //主循环 { num=KeyPro();

C语言 4x4键盘扫描程序

C语言 4*4键盘扫描电路模块 #include #define uchar unsigned char //byte #define uint unsigned int //word void keyscan(); //函数声明 void fun0(); //定义每个按键的功能函数 void fun1(); void fun2(); void fun3(); void fun4(); void fun5(); void fun6(); void fun7(); void fun8(); void fun9(); void fun10(); void fun11(); void fun12(); void fun13(); void fun14(); void fun15(); /******************************************************************** ******** 主程序 ********************************************************************* *******/ void main(void) { while(1) //循环扫描 { keyscan(); } } /******************************************************************** ******** 按键功能函数 fun0~fun15 ********************************************************************* *******/ void fun0(void) { P3=0x00; }

经典的矩阵键盘扫描程序

经典的矩阵键盘扫描程序 查找哪个按键被按下的方法为:一个一个地查找。 先第一行输出0,检查列线是否非全高; 否则第二行输出0,检查列线是否非全高; 否则第三行输出0,检查列线是否非全高; 如果某行输出0时,查到列线非全高,则该行有按键按下; 根据第几行线输出0与第几列线读入为0,即可判断在具体什么位置的按键按下。 下面是具体程序: void Check_Key(void) { unsigned char row,col,tmp1,tmp2; tmp1 = 0x10; //tmp1用来设置P1口的输出,取反后使 P1.4~P1.7中有一个为0 for(row=0;row<4;row++) // 行检测 { P1 = 0x0f; // 先将p1.4~P1.7置高 P1 =~tmp1; // 使P1.4~p1.7中有一个为0 tmp1*=2; // tmp1左移一位 if ((P1 & 0x0f) < 0x0f) // 检测P1.0~P1.3中是否有一位为0,只要有,则说明此行有键按下,进入列检测 { tmp2 = 0x01; // tmp2用于检测出哪一列为0 for(col =0;col<4;col++) // 列检测

{ if((P1 & tmp2)==0x00) // 该列如果为低电平则可以判定为该列 { key_val =key_Map[ row*4 +col ]; // 获取键值,识别按键;key_Map为按键的定义表 return; // 退出循环 } tmp2*=2; // tmp2左移一位 } } } } //结束 这是一种比较经典的矩阵键盘识别方法,实现起来较为简单,程序短小精炼。 4*4矩阵键盘扫描程序 /* 设置行线为输入线,列线为输出线 */ uchar KeyScan(); //按键扫描子程序 void delay10ms(); //延时程序 uchar key_free(); //等待按键释放程序 void key_deal(); //键处理程序 //主程序 void main() { while(1) { KeyScan(); key_free(); key_deal(); } } //按键扫描子程序 uchar KyeScan() { unsigned char key,temp; P1=0xF0; if(P1&0xF0!=0xF0) { delay10ms(); //延时去抖动 if(P1&0xF0!=0xF0) { P1=0xFE; //扫描第一列

2x2行列式键盘扫描程序

#include #define uchar unsigned char #define uint unsigned int sbit rs=P3^5; sbit dula=P2^6; sbit wela=P2^7; sbit led2=P1^1; sbit led4=P1^3; sbit led6=P1^5; sbit led8=P1^7; sbit feng=P2^3; uchar templ; void delay1(uint z) { uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); } void main() { dula=1; P0=0; dula=0; while(1) { P3=0xfb; templ=P3; templ=templ&0xf0; while(templ!=0xf0) { delay1(10); templ=P3; templ=templ&0xf0; while(templ!=0xf0) { templ=P3; switch(templ) { case 0xbb: led6=~led6; feng=0;

feng=1; break; case 0xeb: led4=~led4; feng=0; delay1(100); feng=1; break; } while(templ!=0xf0) { templ=P3; templ=templ&0xf0; } } } P3=0xfe; templ=P3; templ=templ&0xf0; while(templ!=0xf0) { delay1(10); templ=P3; templ=templ&0xf0; while(templ!=0xf0) { templ=P3; switch(templ) { case 0xbe: led8=~led8; feng=0; delay1(100); feng=1; break; case 0xee: led2=~led2; feng=0;

经典按键扫描程序

以下假设你懂C语言,因为纯粹的C语言描述,所以和处理器平台无关,你可以在MCS-51,AVR,PIC,甚至是ARM平台上面测试这个程序性能。以下以AVR的MEGA8作为平台讲解,没有其它原因,因为我手头上只有AVR的板子而已没有51的。用51也可以,只是芯片初始化部分不同,还有寄存器名字不同而已。 核心算法: unsigned char Trg; unsigned char Cont; void KeyRead( void ) { unsigned char ReadData = PINB^0xff; // 1 Trg = ReadData & (ReadData ^ Cont); // 2 Cont = ReadData; // 3 } 下面是程序解释:Trg(triger)代表的是触发,Cont(continue)代表的是连续按下。 1:读PORTB的端口数据,取反,然后送到ReadData 临时变量里面保存起来。(端口值与0XFF 按位异或,有按键按下为0,异或后相应的位就为1,相当于将读取的端口值取反) 2:算法1,用来计算触发变量的。一个位与操作,一个异或操作,我想学过C语言都应该懂吧?Trg为全局变量,其它程序可以直接引用。 3:算法2,用来计算连续变量。 看到这里,有种“知其然,不知其所以然”的感觉吧?代码很简单,但是它到底是怎么样实现我们的目的的呢?好,下面就让我们绕开云雾看青天吧。 我们最常用的按键接法如下:AVR是有内部上拉功能的,但是为了说明问题,我是特意用外部上拉电阻。(STM32可以将端口设置为输入上拉模式)那么,按键没有按下的时候,读端口数据为1,如果按键按下,那么端口读到0。下面就看看具体几种情况之下,这算法是怎么一回事。 (1)没有按键的时候 端口为0xff,ReadData读端口并且取反,很显然,就是 0x00 了。(0XFF^0XFF=0X00)Trg = ReadData & (ReadData ^ Cont); (初始状态下,Cont也是为0的)很简单的数学计算,因为ReadData为0,则它和任何数“相与”,结果也是为0的。 Cont = ReadData; 保存Cont 其实就是等于ReadData,为0; 结果就是: ReadData = 0; Trg = 0; Cont = 0; (2)第一次PB0按下的情况 端口数据为0xfe,ReadData读端口并且取反,很显然,就是 0x01 了。(0XFE^0XFF=0X01)Trg = ReadData & (ReadData ^ Cont); 因为这是第一次按下,所以Cont是上次的值,应为为0。那么这个式子的值也不难算,也就是 Trg = 0x01 & (0x01^0x00) = 0x01 Cont = ReadData = 0x01; 结果就是: ReadData = 0x01; Trg = 0x01;Trg只会在这个时候对应位的值为1,其它时候都为0 Cont = 0x01;

键盘扫描原理及应用键盘

本资源为网上搜集而来,如果该程序涉及或侵害到您的版权请立即写信通知我

键盘扫描 键盘是由按键构成,是单片机系统里最常用的输入设备。我们可以通过键盘输入数据或命令来实现简单的人-机通信。 1.按键及键抖动 按键是一种常开型按钮开关。平时,按键的两个触点处于断开状态,按下按键时两个触点才闭合(短路)。如图1-1所示,平常状态下,当按键K未被按下时,按键断开,PA0输入口的电平为高电平;当按键K被按下时,按键闭合,PA0输入口的电平为低电平。 图1-1 按键电路 图1-2 按键抖动 一般的按键所用开关都是机械弹性开关,由于机械触点的弹性作用,按键开

关在闭合时不会马上稳定地连接,在断开进也不会马上完全的断开,在闭合和断开的瞬间均有一连串的抖动。按键按下的电压信号波形图如图1-2所示,从图中可以看出按键按下和松开的时候都存在着抖动。抖动时间的长短因按键的机械特性不同而有所不同,一般为5ms~10ms。 如果不处理键抖动,则有可能引起一次按键被误读成多次,所以为了确保能够正确地读到按键,必须去除键抖动,确保在按键的稳定闭合和稳定断开的时候来判断按键状态,判断后再做处理。按键在去抖动,可用硬件或软件两种方法消除。由于使用硬件方法消除键抖动,一般会给系统的成本带来提高,所以通常情况下都是使用软件方法去除键抖动。 常用的去除键抖动的软件方法有很多种,但是都离不开基本的原则:就是要么避开抖动的时候检测按键或是在抖动的时候检测到的按键不做处理。这里说明一下常用的两种方法: 第一种方法是检测到按键闭合电平后先执行一个延时程序,做一个12ms~24ms的延时,让前抖动消失后再一次检测按键的状态,如果仍是闭合状态的电平,则认为真的有按键按下;若不是闭合状态电平,则认为没有键按下。若是要判断按键松开的话,也是要在检测到按键释放电平之后再给出12ms~24ms的延时,等后抖动消失后再一次检测按键的状态,如果仍为断开状态电平,则确认按键松开。这种方法的优点是程序比较简单,缺点是由于延时一般采用跑空指令延时,造成程序执行效率低。 第二种方法是每隔一个时间周期检测一次按键,比如每5ms扫描一次按键,要连续几次都扫描到同一按键才确认这个按键被按下。一般确认按键的扫描次数由实际情况决定,扫描次数的累积时间一般为50ms~60ms。比如,以5ms为基本时间单位去扫描按键的话,前后要连续扫描到同一个按键11次而达到50ms 来确认这个按键。按键松开的检测方法也是一样要连续多次检测到按键状态为断开电平才能确认按键松开。这种方法的优点是程序执行效率高,不用刻意加延时指令,而且这种方法的判断按键抗干扰能力要更好;缺点是程序结构较复杂。 在以下的介绍中,我们将使用第二种方法来去除键抖动。 2.键盘结构及工作原理 键盘一般有独立式和行列式(矩阵式)两种。当然还有其它的结构,比如交互式结构等等,不过其它的结构比较少用,在这里就不介绍了。在中颖的单片机中,有些单片机的LCD驱动引脚的SEGMENT口可以共享按键扫描口,当选择为按键扫描口时,可以使用这些口来扫描按键,所以在外部电路可以连接LCD和按键矩阵,采用分时扫描进行处理,下面也将介绍这个特殊应用的方法和注意的地方。 独立式键盘结构

矩阵键盘扫描汇编程序

4*4矩阵键盘扫描汇编程序(基于51单片机) // 程序名称:4-4keyscan.asm ;// 程序用途:4*4矩阵键盘扫描检测 ;// 功能描述:扫描键盘,确定按键值。程序不支持双键同时按下, ;// 如果发生双键同时按下时,程序将只识别其中先扫描的按键;// 程序入口:void ;// 程序出口:KEYNAME,包含按键信息、按键有效信息、当前按键状态;//================================================================== ==== PROC KEYCHK KEYNAME DATA 40H ;按键名称存储单元 ;(b7-b5纪录按键状态,b4位为有效位, ;b3-b0纪录按键) KEYRTIME DATA 43H ;重复按键时间间隔 SIGNAL DATA 50H ;提示信号时间存储单元 KEY EQU P3 ;键盘接口(必须完整I/O口) KEYPL EQU P0.6 ;指示灯接口 RTIME EQU 30 ;重复按键输入等待时间 KEYCHK: ;//=============按键检测程序========================================= ==== MOV KEY,#0FH ;送扫描信号 MOV A,KEY ;读按键状态 CJNE A,#0FH,NEXT1 ;ACC<=0FH ; CLR C ;Acc等于0FH,则CY为0,无须置0 NEXT1: ; SETB C ;Acc不等于0FH,则ACC必小于0 FH, ;CY为1,无须置1 MOV A,KEYNAME ANL KEYNAME,#1FH ;按键名称屏蔽高三位 RRC A ;ACC带CY右移一位,纪录当前按键状态 ANL A,#0E0H ;屏蔽低五位

经典的verilog键盘扫描程序

经典的verilog键盘扫描程序 作者:ilove314 拿到威百仕( VibesIC )的板子后就迫不及待的开始我的学习计划,从最基础的分频程序开始,但看到这个键盘扫描程序后,直呼经典,有相见恨晚的感觉,还想说一句:威百仕( VibesIC ),我很看好你!WHY?待我慢慢道来,这个程序的综合后是0error,0warning。想想自己编码的时候那个warning是满天飞,现在才明白HDL设计有那么讲究了,代码所设计的不仅仅是简单的逻辑以及时序的关系,更重要的是你要在代码中要表现出每一个寄存器,甚至每一个走线。想想我写过的代码,只注意到了前者,从没有注意过后者,还洋洋自得以为自己也算是个高手了,现在想来,实在惭愧啊!学习学习在学习,这也重新激发了我对HDL设计的激情,威百仕给了我一个方向,那我可要开始努力喽! 废话说了一大堆,看程序吧:(本代码经过ise7.1i综合并下载到SP306板上验证通过) //当三个独立按键的某一个被按下后,相应的LED被点亮;再次按下后,LED熄灭,按键控制LED亮灭

module key_debounce( clk,rst_n,s1_n,s2_n,s3_n,s4_n,s5_n,led_d1,led_d2,led_d3,led_d 4,led_d5); input clk; //主时钟信号,10MHz input rst_n; //复位信号,低有效 input s1_n,s2_n,s3_n,s4_n,s5_n; output led_d1,led_d2,led_d3,led_d4,led_d5; reg[4:0] s_rst; always @(posedge clk or negedge rst_n) if (!rst_n) s_rst <= 5'b11111; else s_rst <= {s5_n,s4_n,s3_n,s2_n,s1_n}; reg[4:0] s_rst_r; always @ ( posedge clk or negedge rst_n ) if (!rst_n) s_rst_r <= 5'b11111; else s_rst_r <= s_rst; wire[4:0] s_an = s_rst_r & ( ~s_rst); reg[19:0] cnt; //计数寄存器 always @ (posedge clk or negedge rst_n) if (!rst_n) cnt <= 20'd0; //异步复位 else if(s_an) cnt <=20'd0; else cnt <= cnt + 1'b1; reg[4:0] low_s; always @(posedge clk or negedge rst_n) if (!rst_n) low_s <= 5'b11111; else if (cnt == 20'h30D40) low_s <= {s5_n,s4_n,s3_n,s2_n,s1_n}; reg [4:0] low_s_r; always @ ( posedge clk or negedge rst_n ) if (!rst_n) low_s_r <= 5'b11111; else low_s_r <= low_s; wire[4:0] led_ctrl = low_s_r[4:0] & ( ~low_s[4:0]); reg d1,d2,d3,d4,d5; always @ (posedge clk or negedge rst_n) if (!rst_n) begin d1 <= 1'b0; d2 <= 1'b0; d3 <= 1'b0; d4 <= 1'b0; d5 <= 1'b0; end else begin // if ( led_ctrl[0] ) d1 <= ~d1; if ( led_ctrl[1] ) d2 <= ~d2; if ( led_ctrl[2] ) d3 <= ~d3; if ( led_ctrl[3] ) d4 <= ~d4; if ( led_ctrl[4] ) d5 <= ~d5; end assign led_d1 = d1 ? 1'b1 : 1'b0; //LED翻转输出assign led_d2 = d2 ? 1'b1 : 1'b0; assign led_d3 = d3 ? 1'b1 : 1'b0; assign led_d4 = d4 ? 1'b1 : 1'b0; assign led_d5 = d5 ? 1'b1 : 1'b0; endmodule

键盘扫描方法

键盘扫描方法 传统的键盘扫描方法如图1所示,该方法虽然被广泛应用于很多场合,但有一个不足的地方,如果按键一直没有释放,或者按键坏了,一直处于闭合状态,则程序一直处于检测按键是否释放,系统将无法运行。只要对其稍加改进,就可以避免产生这个问题。 假设键盘接口电路采用独立式键盘接口,所有按键公共端接地,而且没有按键按下时IO口为高电平。当按键没有按下时,IO口为高电平;当按键按下时,IO口为低电平;当按键释放时,IO口为高电平。一个完整的按键过程是——按键未按下,按键按下,按键释放,而对应的IO口的电平变化为——高电平,低电平,高电平。所以,可以通过判断IO口电平变化的变化顺序是否满足高电平→低电平→高电平,来判断是否有按键按下,而对于其它的电平变化顺序都是无效的。那么该如何实现呢?在键盘扫描过程中,如果IO口为高电平,则需要判断是由于未按键,还是按键按下后释放引起的;如果IO口为低电平,则需要判断是由于未按键还是扫描之前本来就是低电平引起的。所以我们需要引入一个全局位变量KEY_EN,来标志按键的状态, KEY_EN=0表示按键未按下;KEY_EN=1表示按键按下。另外,我们还需引入一个全局字节变量KEY_TP来暂存键值,这是因为只有当IO口电平变化满足高电平→低电平→高电平,才表示一个按键有效,而只有在IO口为低电平的时候才能够读取到键值。具体的键盘扫描流程如图2所示,键盘初始化KEY_EN=0。

图1 传统键盘扫描

图2 改进后键盘扫描 接下来我们介绍一种代码效率极高的键盘扫描方法。键盘接口电路同样采用独立式,假设有8个按键,所有按键公共端接地,键盘扫描口为P0.7~P0.0,而且没有按键按下时为高电平,键盘扫描程序如下: unsigned char Trigger; unsigned char Continue; void delayms(unsigned char n) { …… } void key_scan() { unsigned char ReadData; if (P0!=0xff&&Trigger==0x00) delayms(20); ReadData = P0 ^ 0xff; Trigger = ReadDate & (ReadData ^ Continue);

极其简单好用的按键扫描程序C语言

极其简单好用的按键扫描程序(C语言) 不过我在网上游逛了很久,也看过不少源程序了,没有发现这种按键处理办法的踪迹,所以,我将他共享出来,和广大同僚们共勉。我非常坚信这种按键处理办法的便捷和高效,你可以移植到任何一种嵌入式处理器上面,因为C语言强大的可移植性。 同时,这里面用到了一些分层的思想,在单片机当中也是相当有用的,也是本文的另外一个重点。 对于老鸟,我建议直接看那两个表达式,然后自己想想就会懂的了,也不需要听我后面的自吹自擂了,我可没有班门弄斧的意思,hoho~~但是对于新手,我建议将全文看完。因为这是实际项目中总结出来的经验,学校里面学不到的东西。 以下假设你懂C语言,因为纯粹的C语言描述,所以和处理器平台无关,你可以在MCS-51,AVR,PIC,甚至是ARM平台上面测试这个程序性能。当然,我自己也是在多个项目用过,效果非常好的。 好了,工程人员的习惯,废话就应该少说,开始吧。以下我以AVR的MEGA8作为平台讲解,没有其它原因,因为我手头上只有AVR的板子而已没有51的。用51也可以,只是芯片初始化部分不同,还有寄存器名字不同而已。 核心算法: unsigned char Trg; unsigned char Cont; void KeyRead( void ) { unsigned char ReadData = PINB^0xff; // 1 Trg = ReadData & (ReadData ^ Cont); // 2 Cont = ReadData; // 3 } 完了。有没有一种不可思议的感觉?当然,没有想懂之前会那样,想懂之后就会惊叹于这算法的精妙!! 下面是程序解释: Trg(triger)代表的是触发,Cont(continue)代表的是连续按下。 1:读PORTB的端口数据,取反,然后送到ReadData 临时变量里面保存起来。 2:算法1,用来计算触发变量的。一个位与操作,一个异或操作,我想学过C语言都应该懂吧?Trg为全局变量,其它程序可以直接引用。 3:算法2,用来计算连续变量。 看到这里,有种“知其然,不知其所以然”的感觉吧?代码很简单,但是它到底是怎么样实现我们的目的的呢?好,下面就让我们绕开云雾看青天吧。 我们最常用的按键接法如下:AVR是有内部上拉功能的,但是为了说明问题,我是特意用外部上拉电阻。那么,按键没有按下的时候,读端口数据为1,如果按键按下,那么端口读到0。下面就看看具体几种情况之下,这算法是怎么一回事。 (1)没有按键的时候 端口为0xff,ReadData读端口并且取反,很显然,就是0x00 了。

PIC单片机键盘扫描程序

//3*3键盘扫描程序,键盘为3个行上拉电阻,扫描函数完全自主知识产权//数码管扫描函数据说是华为的程序员编写的,本人稍加改动 #include #define uchar unsigned char #define uint unsigned int __CONFIG(PWRTDIS&HS&WDTDIS&LVPDIS&BORDIS); const uchar table[]={0x3F,0x06,0x5B,0x4F,0x66, 0x6D,0x7D,0x07,0x7F,0x6F};//共阴极数码管段表 const uchar keycode[9][2]={{0x1E,1},{0x2E,2},{0x36,3},{0x1D,4}, {0x2D,5},{0x35,6},{0x1B,7},{0x2B,8},{0x33,9}};//矩阵键盘键值码 void delayms(uint delay) { uint i; for(;delay>0;delay--) for(i=0;i<453;i++); } void init() { ADCON1=0x8E; TRISD=0x00; TRISA&=0xE1; PORTD=0x00; PORTA=0x00; } uchar scankey() { uchar key3H,key3L,scancode; TRISB=0x38;//高3位置为输入,低3位为输出 PORTB=0x00;//低3位输出低电平 key3H=PORTB;//读取D口状态 key3H=PORTB&0x38; if(key3H!=0x38) { key3H=PORTB; delayms(5); if(key3H!=0x38) { TRISB=0x07;//低3位输入,高3位输出 PORTB=0x00;//高3位输出低电平

51单片机矩阵键盘扫描程序

/* --------------------------------------------- 名称: 矩阵键盘依次输入控制使用行列逐级扫描 论坛: 编写: shifang 日期: 2009.5 修改:无内容: 如计算器输入数据形式相同从右至左使用行列扫描方法 */ #include // 包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的 定义#define DataPort P0 〃定义数据端口程序中遇到DataPort则用P0替换#define KeyPortP1 sbit LATC H仁P2八2;/定义锁存使能端口段锁存 sbit LATCH2=P2A3;/位锁存 unsigned char code dofly_DuanMa[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f, 0x77,0x7c,0x39,0x5e,0x79,0x71};/显示段码值0~F un sig nedcharcodedofly_WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};〃

分 别对应相应的数码管点亮,即位码 unsigned char TempData[8]; //存储显示值的全局变量 void DelayUs2x(unsigned char t);//us 级延时函数声明 void DelayMs(unsigned char t); //ms 级延时 void Display (un sig ned char FirstBit, un sig ned char Num);/数码管显示函数un sig ned char KeySca n(v oid);/键盘扫描unsigned char KeyPro(void); void Init_Timer0(void);// 定时器初始化 /* ----------------------------------------------- 主函数 ----------------------------------------------- */ void main (void){unsigned char num,i,j; unsigned char temp[8]; Init_Timer0(); while (1)// 主循环{num=KeyPro(); if(num!=0xff){if(i<8){temp[i]=dofly_DuanMa[num]; for(j=0;j<=i;j++) TempData[7-i+j]=temp[j];}i++; if(i==9)〃多出一个按键输入为了清屏原本应该为8{i=0;

4×4键盘扫描程序

键盘程序 假设P2.0-P2.3为H0-H3,P2.4-P2.7为L0-L3 (列) L0 L1 L2 L3 (行) H0 0 1 2 3 H1 4 5 6 7 H2 8 9 A B H3 C D E F 首先,行为P2口的低四位,而列为高四位。P0口为数码管输出口。第一种思路就是逐行逐列判断法。 #include #include #define uint unsigned int #define uchar unsigned char uchar code table[17] = { 0xc0,0xf9,0xa4,0xb0, 0x99,0x92,0x82,0xf8, 0x80,0x90,0x88,0x83, 0xc6,0xa1,0x86,0x8e,0xbf};//八段数码管对应0-F值. uchar temp; void Delay_1ms(uint i)//1ms延时 { uint x, j;

for(j=0;j

temp=P2&0x0f; for(j=0; j<4; j++) { if(!(temp&(0x01<

单片机汇编键盘扫描程序

单片机——汇编——键盘扫描程序键盘接口如图: 显示P0口 数码管选择P2口 LED EQU P0 KEY EQU P1 DUAN EQU P2 QIAN EQU 30H HOU EQU 40H XS EQU 50H ORG 00H LJMP START ;*************************** ORG 30H START: MOV R0,#50H L1: CLR A MOV @R0,A INC R0 CJNE R0,#58H,L1 MOV DPTR,#SJ L2: MOV R0,#50H MOV R2,#00H

L3: MOV A,@R0 MOV LED,A MOV DUAN,R2 LCALL DELAY INC R0 INC R2 MOV KEY,#0FH JNB P1.0,S1 JNB P1.1,S1 JNB P1.2,S1 JNB P1.3,S1 CJNE R2,#08H,L3 LJMP L2 ;******************************** S1: MOV R5,#10 ;延时20ms去抖DELAY2: LCALL DELAY DJNZ R5,DELAY2 MOV B,#00H MOV KEY,#0FH JNB P1.0,S0 INC B JNB P1.1,S0 INC B JNB P1.2,S0 INC B JNB P1.3,S0 LJMP L2 S0: LCALL SAO LJMP L2 SAO: ;键盘输入子程序CLR A MOV KEY,#0F0H JNB P1.4,FZ0 INC A JNB P1.5,FZ0 INC A JNB P1.6,FZ0 INC A JNB P1.7,FZ0 RET

2X2键盘扫描程序

--天目学院单片机设计报告 题目:2×2矩阵式键盘 学年:06/07学年学期:第二学期 专业:电子信息工程 班级:天目电子信息工程041 学号:200405052118姓名:毛陈华 指导教师:舒洪波 学科:单片机原理与应用及C51程序设计 时间:2007年5月28日— 2007年6月12日

2×2矩阵式键盘 摘要:本设计主要是用来学习键盘扫描程序的设计,数码管的动态显示程序设计。设计中,将单片机8051的并行口P1的P1.0,P1.1接键盘的行,将P1.2,P1.3接键盘的列,将并行口P2的P2.7~P2.0分别接数码管的数据段g,f,a,b,d,h,e,c. 以及将P3.6,P3.7分别接数码管的偏选端,当按下第0行0列时数码管就显示00,按下第0行1列时数码管就显示01,第1行0列时数码管就显示02,第1行1列时数码管就显示03。本设计一共四个按键,用双数码管动态显示。 关键字:键盘扫描,数码管动态显示 1.系统设计部分 如图1-0所示,此按键设计是以单片机8051为核心,以按键和数码管为扩展,实现键盘识别和动态显示的功能。 图1-0 1.1设计要求 此矩阵式键盘具有按键识别功能,当按下第0行0列时数码管就显示00,按下第0行1列时数码管就显示01,第1行0列时数码管就显示02,第1行1列时数码管就显示03。 1.2总体设计方案 1.2.1 设计思路 将单片机8051的并行口P1的P1.0,P1.1接键盘的行,将P1.2,P1.3接键盘的列,将并行口P2的P2.7~P2.0分别接数码管的数据段g,f,a,b,d,h,e,c. 以及将P3.6,P3.7分别接数码管的偏选端,当按下第0行0列时数码管就显示00,按下第0行1列时数码管就显示01,第1行0列时数码管就显示02,第1行1列时数码管就显示03。 1.2.2 方案论证与选择 方案一:将单片机8051的并行口P1的P1.0,P1.1接键盘的行,将P1.2,P1.3接键盘的列,将并行口P2的P2.7~P2.0分别接数码管的数据段g,f,a,b,d,h,e,c. 以及将P3.6,P3.7分别接数码管的偏选端。 方案二:将单片机8051的并行口P0的P00,P01接键盘的行,将P0.2,P0.3接键盘的列,将并行口P2的P2.7~P2.0分别接数码管的数据段g,f,a,b,d,h,e,c. 以及将P3.6,P3.7分别接数码管的偏选端。 点评:由于在方案二中,P0口内部没有上拉电阻,如用此方案,就要比方案一多接几个上拉电阻,在键盘多的时候很容易弄错,所以在这里我们选择方案一。

相关主题
相关文档
最新文档