(原创)51单片机C语言程序设计--速学教程实例(入门篇)之矩阵键盘(逐行扫描法)

合集下载

单片机矩阵键盘扫描程序

单片机矩阵键盘扫描程序
***********************************************************************/
void L1602_string(uchar hang,uchar lie,uchar *p)
{
uchar a,b=0;
if(hang == 1) a = 0x80;
{
P1 = Buffer[j];
temp = 0x10;
for(i=0; i<4; i++)
{
if(!(P1 & temp))
{
x= i+j*4;
switch(x)
{ case 0:return 1; break;
case 1:return 2; break;
case 2:return 3;break;
uint keyflag ; //键盘正在读取标志位,如果Keyflag为1,表示正在读取键盘,停止其他功能;
char x,y,m,n,c;
//Keyflag为0,读取键盘结束,恢复其他功能
char flag1=0;
//频率范围10~1000Hz
uchar Hrate = 0;//一个周期内高点平占据时间
E = 0;
delay();
P0 = del;
delay();
E = 1;
delay();
E = 0;
}
/********************************************************************
*名称: L1602_init()
*功能: 1602初始化,请参考16பைடு நூலகம்2的资料

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

51单片机矩阵键盘扫描程序
void Timer0_isr(void) interrupt 1
{
TH0=(65536-2000)/256;//重新赋值2ms
TL0=(65536-2000)%256;
Display(0,8); //调用数码管扫描
}
/*------------------------------------------------
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};//分别对应相应的数码管点亮,即位码
case 0xd7:return 11;break;//b
case 0xee:return 12;break;//c
case 0xed:return 13;break;//d
case 0xeb:return 14;break;//e
case 0xe7:return 15;break;//f
default:return 0xff;break;
}
}
/*------------------------------------------------
uS延时函数,含有输入参数unsigned char t,无返回值
unsigned char是定义无符号字符变量,其值的范围是
0~255这里使用晶振12M,精确延时请使用汇编,大致延时
长度如下T=tx2+5 uS

单片机c语言程序设计---矩阵式键盘实验报告

单片机c语言程序设计---矩阵式键盘实验报告

单片机c语言程序设计---矩阵式键盘实验报告课程名称:单片机c语言设计实验类型:设计型实验实验项目名称:矩阵式键盘实验一、实验目的和要求1.掌握矩阵式键盘结构2.掌握矩阵式键盘工作原理3.掌握矩阵式键盘的两种常用编程方法,即扫描法和反转法二、实验内容和原理实验1.矩阵式键盘实验功能:用数码管显示4*4矩阵式键盘的按键值,当K1按下后,数码管显示数字0,当K2按下后,显示为1,以此类推,当按下K16,显示F。

(1)硬件设计电路原理图如下仿真所需元器件(2)proteus仿真通过Keil编译后,利用protues软件进行仿真。

在protues ISIS 编译环境中绘制仿真电路图,将编译好的“xxx.hex”文件加入AT89C51。

启动仿真,观察仿真结果。

操作方完成矩阵式键盘实验。

具体包括绘制仿真电路图、编写c源程序(反转法和扫描法)、进行仿真并观察仿真结果,需要保存原理图截图,保存c源程序,总结观察的仿真结果。

完成思考题。

三、实验方法与实验步骤1.按照硬件设计在protues上按照所给硬件设计绘制电路图。

2.在keil上进行编译后生成“xxx.hex”文件。

3.编译好的“xxx.hex”文件加入AT89C51。

启动仿真,观察仿真结果。

四、实验结果与分析void Scan_line()//扫描行{Delay(10);//消抖switch ( P1 ){case 0x0e: i=1;break;case 0x0d: i=2;break;case 0x0b: i=3;break;case 0x07: i=4;break;default: i=0;//未按下break;}}void Scan_list()//扫描列{Delay(10);//消抖switch ( P1 ){case 0x70: j=1;break;case 0xb0: j=2;break;case 0xd0: j=3;break;case 0xe0: j=4;break;default: j=0;//未按下break;}}void Show_Key(){if( i != 0 && j != 0 ) P0=table[ ( i - 1 ) * 4 + j - 1 ];else P0=0xff;}五、讨论和心得。

51单片机矩阵键盘行扫描

51单片机矩阵键盘行扫描

51单⽚机矩阵键盘⾏扫描————————————————————————————————————————————分类:按结构原理分:触点式开关按键⽆触点开关按键接⼊⽅式独⽴式按键矩阵式键盘————————————————————————————————————————————矩阵式键盘识别⽅法(⾏扫描法)检测列线的状态:列线Y4~Y7置⾼电平,⾏线Y0~Y3置低电平。

只要有⼀列的电平为低,则表⽰键盘该列有⼀个或多个按键被按下。

若所有列线全为⾼电平,则键盘中⽆按键按下。

判断闭合按键所在的位置:⾏线置⾼电平,列线置低电平。

检测⾏线的状态。

举例:当按下第⼀⾏第⼀列的按键时⾏扫描,⾏线为低电平,列线为⾼电平,得到 1110 0000列扫描,⾏线为⾼电平,列线为低电平,得到 0000 1110将得到的结果进⾏或运算,得到 1110 1110,对应第⼀⾏第⼀列,⼗六进制为0xEE按键表⾏列bin hex111110 11100xEE121101 11100xDE131011 11100xBE140111 11100x7E211110 11010xED221101 11010xDD231011 11010xBD240111 11010x7D311110 10110xEB321101 10110xDB331011 10110xBB340111 10110x7B411110 01110xE7421101 01110xD7431011 01110xB7440111 01110x77————————————————————————————————————————————矩阵式键盘应⽤实例实现结果:通过4*4矩阵键盘对应数码管显⽰0~F设计思路:当检测到按键被按下时,将此时⾏扫描的结果存⼊临时变量,再进⾏列扫描,得到的结果和临时变量进⾏或运算。

通过数组存放按键和数码管编码,⾏列扫描得到结果后遍历数组,找到对应的编码位置并显⽰数码管编码实现代码:1 #include <reg52.h>2 typedef unsigned char uchar;3 typedef unsigned int uint;4 uchar code KEY_TABLE[] =5 {60xEE, 0xDE, 0xBE, 0x7E,70xED, 0xDD, 0xBD, 0x7D,80xEB, 0xDB, 0xBB, 0x7B,90xE7, 0xD7, 0xB7, 0x7710 };11 uchar code TABLE[] =12 {130x3F, 0x06, 0x5B, 0x4F,140x66, 0x6D, 0x7D, 0x07,150x7F, 0x6F, 0x77, 0x7C,160x39, 0x5E, 0x79, 0x71,17 };18void Delay(uchar m)19 {20 --m;21 }22void main()23 {24 uchar temp, key, i;25while(1)26 {27 P3 = 0xF0;28if (P3 != 0xF0)29 {30 Delay(2000);31if (P3 != 0xF0)32 {33 temp = P3;34 P3 = 0x0F;35 key = temp | P3;36for (i = 0; i < 16; ++i)37if (key == KEY_TABLE[i])38break;39 P2 = TABLE[i];40 }41 }42 }43 }。

单片机矩阵键盘行列扫描程序学习资料

单片机矩阵键盘行列扫描程序学习资料
switch(key)
{
case 0x7e:P0=dofly[0];break;//0按下相应的键显示相对应的码值
case 0x7d:P0=dofly[1];break;//1
case 0x7b:P0=dofly[2];break;//2
case 0x77:P0=dofly[3];break;//3
case 0xbe:P0=dofly[4];break;//4
case 0xbd:P0=dofly[5];break;//5
case 0xbb:P0=dofly[6];break;//6
case 0xb7:P0=dofly[7];break;//7
case 0xde:P0=dofly[8];break;//8
if(cord_h!=0x0f) //先检测有无按键按下
{
delay(100); //去抖
if(cord_h!=0x0f)
{
cord_h=P3&0x0f; //读入列线值
P3=cord_h|0xf0; //输出当前列线值
cord_l=P3&0xf0; //读入行线值
return(cord_h+cord_l);//键盘最后组合码值
0x77,0x7c,0x39,0x5e,0x79,0x71};//0-F
uchar keyscan(void);
void delay(uint i);
void main()
{
uchar key;
P2=0x00;//1数码管亮按相应的按键,会显示按键上的字符
while(1)
{
key=keyscan();//调用键盘扫描,
//行列扫描程序,可以自己定义端口和扫描方式,这里做简单介绍

51单片机矩阵键盘C语言编程

51单片机矩阵键盘C语言编程

X1
19 X1
P20 P21 P22 P23 P24 P25 P26 P27
21 22 23 24 25 26 27 28
+5V
RES X1
+5V
C3 1uF
R1
C1
1K
X2
18 X2
RES
9 RESET
EA/VPP RD/P37 WR/P36 ALE/PRDG
PSEN
31 17 16 30 29
1
}
/****************************************************************************** 函数名称:void keyscan() 函数功能:键盘扫描及按键处理
******************************************************************************/
//如果有按键闭合
{ keyvalue=(~HSM)+(~(LJC|0x0f));
//计算键盘值
return(keyvalue);
//返回键值
} else HSM=(HSM<<1)|0x01;
//行扫描左移 1 位,准备扫描下一行}} Nhomakorabea}
return(0x00);
}
break;
case 0x12: P0=0x66; //4
break;
case 0x22: P0=0x6d; //5
break;
case 0x42: P0=0x7d; //6
break;
case 0x82: P0=0x07; //7
break;

51单片机矩阵按键程序4 4

51单片机矩阵按键程序4 4

//以下程序都是在VC++6.0 上调试运行过的程序,没有错误,没有警告。

//单片机是STC89C52RC,但是在所有的51 52单片机上都是通用的。

51只是一个学习的基础平台,你懂得。

//程序在关键的位置添加了注释。

//用//11111111111111111代表第一个程序。

//2222222222222222222222222代表第二个程序,以此类推//1111111111111111111111111111111111111111111111111111111111111111111//1111111111111111111111111111111111111111111111111111111111111111111/****************************************************************************** ** 实验名: 矩阵键盘实验* 使用的IO : 数码管使用P0,键盘使用P3.0、P3.1、P3.2、P3.3* 实验效果: 按矩阵键盘分别显示在数码管上面显示十六进制的0到F。

* 注意:******************************************************************************* /#include<reg51.h>#define GPIO_DIG P0#define GPIO_KEY P1sbit LSA=P2^2;sbit LSB=P2^3;sbit LSC=P2^4;unsigned char code DIG_CODE[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//0、1、2、3、4、5、6、7、8、9、A、b、C、d、E、F的显示码unsigned char KeyValue;//用来存放读取到的键值void Delay10ms(); //延时10msvoid KeyDown(); //检测按键函数/****************************************************************************** ** 函数名: main* 函数功能: 主函数* 输入: 无* 输出: 无******************************************************************************* /void main(void){LSA=0; //给一个数码管提供位选LSB=0;LSC=0;while(1){KeyDown();GPIO_DIG=DIG_CODE[KeyValue];}}/****************************************************************************** ** 函数名: KeyDown* 函数功能: 检测有按键按下并读取键值* 输入: 无* 输出: 无******************************************************************************* /void KeyDown(void){char a=0;GPIO_KEY=0x0f;if(GPIO_KEY!=0x0f)//读取按键是否按下{Delay10ms();//延时10ms进行消抖if(GPIO_KEY!=0x0f)//再次检测键盘是否按下{//测试列GPIO_KEY=0X0F;switch(GPIO_KEY){case(0X07): KeyValue=0;break;case(0X0b): KeyValue=1;break;case(0X0d): KeyValue=2;break;case(0X0e): KeyValue=3;break;}//测试行GPIO_KEY=0XF0;switch(GPIO_KEY){case(0X70): KeyValue=KeyValue;break;case(0Xb0): KeyValue=KeyValue+4;break;case(0Xd0): KeyValue=KeyValue+8;break;case(0Xe0): KeyValue=KeyValue+12;break;}while((a<50)&&(GPIO_KEY!=0xf0)) //检测按键松手检测{Delay10ms();a++;}}}}/****************************************************************************** ** 函数名: Delay10ms* 函数功能: 延时函数,延时10ms* 输入: 无* 输出: 无******************************************************************************* /void Delay10ms(void) //误差0us{unsigned char a,b,c;for(c=1;c>0;c--)for(b=38;b>0;b--)for(a=130;a>0;a--);}。

51单片机矩阵键盘程序示例

51单片机矩阵键盘程序示例

;lab5_asm;vol1.0;zqy;2012/2/18;定义初始化LED_CHABIT PSW.5;数码管显示标志位,为1显示十位,为0显示个位;数字0-9ORG 00HJMP STARTORG 000BHJMP INT_T0;转到中断服务程序,更改数码管显示ORG 0100HLED_TAB1:DB 0BFH,86H,0DBH,0CFH,0E6H,0EDHDB 0FDH,87H,0FFH,0EFH,0BFHDB 86H,0DBH,0CFH,0E6H,0EDH,0FDHLED_TAB2:DB 0BFH,0BFH,0BFH,0BFH,0BFHDB 0BFH,0BFH,0BFH,0BFH,0BFHDB 86H,86H,86H,86HDB 86H,86H,86HSTART:;工作寄存器和某些数据单元的初始化MOV R0,#0;数码管显示初始化SETB LED_CHAMOVDPTR, #8300H;位选地址赋给DPTR高八位P2口,选中U13锁存器MOVA,#0FEH;位选数据,选中个位数码管,置低为选中MOVX@DPTR, A;位选数据,对片外I/O口的外设芯片访问MOVDPTR,#8200H;段选地址MOVA,#0BFH;段选数据,个位显示0MOVX@DPTR, A;定时器初始化MOV IE,#82H;开启定时器T0中断MOV TMOD,#01H;设定定时器T0为模式1MOV TH0,#0D8HMOV TL0,#0F0H;装入初值,10MS延时12MHZSETB TR0 ;启动定时器T0KEY:;按键处理LCALL KEY_START;调用判断有无键按下子程序JZ KEY;无键按下,重新扫描LCALL KEY_DELAY;有键按下,延时去抖LCALL KEY_STARTJZ KEYLCALL KEY_NEXT;判断哪一个键被按下LCALL DECODE;键值译码LCALL KEY_END;判断按键释放LJMP KEYKEY_START:MOV DPTR, #8000H;键盘地址MOV A,#0F0HMOVX @DPTR,A;行全部输出0NOPNOPNOPMOVX A,@DPTR;扫描键盘CPL A;取正逻辑,1为按下ANL A,#0FHRETKEY_NEXT:MOV R1,#0;扫描行计数器MOV R2,#0;扫描列计数器MOV R3,#0FEH;首行扫描字送R3 MOV DPTR, #8000HMOV A,R3MOVX @DPTR,AMOVX A,@DPTRCPL AANL A,#0FHMOV R4,#4S0123: JNZ SKEY0;不为全0,有键按下;全为0,进行下一行扫描INC R1;行计数器加1MOV A,R3RL AMOV R3,AMOV DPTR,#8000HMOVX @DPTR,ANOPNOPNOPMOVX A,@DPTRCPL AANL A,#0FHDJNZ R4,S0123LJMP KEYEKEY:RETSKEY0:;列号译码JBACC.0,SKEY1JBACC.1,SKEY2JBACC.2,SKEY3JBACC.3,SKEY4SKEY1:MOV A,#00H;存列号0 MOV R2,AAJMP EKEYSKEY2:MOV A,#01H;存列号1 MOV R2,AAJMP EKEYSKEY3:MOV A,#02H;存列号2MOV R2,AAJMP EKEYSKEY4: MOV A,#03H;存列号3 MOV R2,AAJMP EKEYDECODE:;行号在R1,列号在R2;键值译码MOV A,R1MOV B,#04HMUL ABADD A,R2INC AMOV R0,ARETKEY_END:MOV DPTR,#8000H;键盘地址MOVX A,@DPTR;扫描键盘CPL A;取正逻辑,1为按下ANL A,#0FHJNZ KEY_ENDLCALL KEY_DELAYJNZ KEY_ENDRETKEY_DELAY:MOV R5,#10HDS1:MOV R6,#0FFHDS2:NOPDJNZ R6,DS2DJNZ R5,DS1RETINT_T0:;中断服务程序,更改数码管显示MOV R7,AJB LED_CHA,DISP_L;检查数码管显示标志位CPL LED_CHAMOVDPTR, #8200H;段选地址MOV A,#0MOVX @DPTR,AMOVDPTR,#8300H;位选地址赋给DPTR高八位P2口,选中U13锁存器MOVA, #0FEH;位选数据,选中个位数码管,置低为选中MOVX@DPTR, A;位选数据,对片外I/O口的外设芯片访问;判断需要显示的个位数字MOV A,R0NOPMOV DPTR,#LED_TAB1NOPNOPMOVC A,@A+DPTRMOVDPTR, #8200H;段选地址MOVX @DPTR,AJMP INT_EXITDISP_L:CPL LED_CHAMOVDPTR, #8200H;段选地址MOV A,#0MOVX @DPTR,AMOVDPTR,#8300H;位选地址赋给DPTR高八位P2口,选中U13锁存器MOVA, #0FDH;位选数据,选中十位数码管,置低为选中MOVX@DPTR, A;位选数据,对片外I/O口的外设芯片访问;判断需要显示的十位数字0或1MOV A,R0NOPMOV DPTR,#LED_TAB2MOVC A,@A+DPTRMOVDPTR, #8200H;段选地址MOVX @DPTR,AINT_EXIT:MOV IE,#82HMOV TH0,#0D8HMOV TL0,#0F0H;装入初值,10MS延时SETB TR0MOV A,R7MOV DPTR,#8000HRETIEND12MHZ。

51单片机的矩阵按键扫描的设计C语言程序

51单片机的矩阵按键扫描的设计C语言程序

#include <reg51.h>#define KEY P1// ----------------------- 变量声明-------------------------------------------------------------------- void program_SCANkey(); // 程序扫描键盘 ,供主程序调用void delay(unsigned int N) ;// 延时子程序,实现 (16*N+24)us 的延时bitjudge_hitkey();// 判断是否有键按下,有返回 1,没 有返回 0void key_manage(unsigned char keycode); //键盘散转////函数名称:program_SCANkey//函数声明,变量定义unsigned char scan_key();表行,低四位代表列 )// 扫描键盘,返回键值 (高四位代void manage_key1(void);// 按键 1 处理程序 void manage_key2(void);// 按键 2 处理程序 void manage_key3(void);// 按键 3 处理程序 void manage_key4(void);// 按键 4 处理程序 //每个按键对应一个处理程序,这里// 函数功能:程序扫描键盘,// 有键按下完成按键处理,无键按下直接返回// -------------------------------------------------------------------------------------------------- void program_SCANkey(){unsigned char key_code;----------------------------------------------------------------- //函数名称: delay //入口参数:N//函数功能:延时子程序,实现(16*N+24)us 的延时// 系统采用11.0592MHz 的时钟时,延时满足要求,其它情况需要改动// --------------------------------------------------------------------------------------------------void delay(unsigned int N){int i;for(i=0;i<N;i++);}// --------------------// 函数名称:system_init()if(judge_hitkey())(1000);if(judge_hitkey())while(judge_hitkey());key_manage(key_code);// ------------------------------// 判断是否有键按下 {delay //延时20ms 左右,消除抖动干扰 //判断是否有效按键 {key_code=scan_key (;) // 等待按键释放 // 键盘扫描、键盘散转、按键处理 }}}// 函数功能:初始化设置// 设定INT0、INT1 及T0、T1的工作方式// --------------------------------------------------------------------------------------------------/* void system」nit(void ){TMOD=0x55;〃定时器1和定时器0工作在方式1,的计数模式TR0=1; //定时器 1 和定时器0开始计数TR1=1;ET0=1; //定时器1 和定时器0中断允许ET1=1;IT1=0; //选择INTO和INT1为电平触发方式IT0=0;EX0=1; //外部中断允许EX1=0;EA=1; // 系统中断允许}// --------------------------------------------------------------// 函数名称:INT0_intrupt// 函数功能:外部中断0 处理程序//void INT0_intrupt() interrupt 0 using 1{EA=0; // 系统中断禁止delay(1000); // 键盘消抖动if(INT_0==0) // 判断是否干扰{ // 的确有健按下while(INT_O==O);〃等待键盘释放delay(1000); //键盘消抖动manage_key1();}EA=1;}*/// -------------------------------------------------------------------------------------------------- // 函数名称:judge_hitkey// 函数功能:// 判断是否有键按下,有返回1,没有返回0// --------------------------------------------------------------------------------------------------bitjudge_hitkey() // 判断是否有键按下,有返回1,没有返回0{unsigned char scancode,keycode;scancode=0xff; //P1.4~P1.7 输出全 1 则无键闭合 KEY=scancode;// 函数名称:scan_key// 函数功能:// 扫描键盘,返回键值 (高四位代表行,低四位代表列 )// ----------------------------- unsignedcharscan_key() // 扫描键盘,返回键值 (高四位代表 行,低四位代表列 ){unsigned char scancode,keycode;scancode=0xef; // 键盘扫描码,采用逐行扫描的方法 while(scancode!=0xff){KEY=scancode; // 输入扫描 码,扫描 P1.4 对应的行keycode=KEY;1.0~P1.3 的状态if(keycode==0xff)return(0);elsereturn(1);// 读 P // 全 1 则无键闭合 //否则有键闭合 }//if((keycode&0x0f)!=0x0f)keycode=~keycode;return(keycode);}// --------------------------------------------------------------------------- // 函数名称:key_manage// 入口参数:keycode 扫描键盘返回的键值 (高四位代表行,低四位代表列 )// 函数功能: 键盘散转// -------------------------------------------------------------------------------------------------- void key_manage(unsigned char keycode){switch(keycode){case 0x11:manage_key1();break;case 0x12: manage_key2();break;case 0x14: manage_key3();break;case 0x18: manage_key4();break;case 0x21:manage_key5();break;case 0x22: manage_key6();break;case 0x24: manage_key7();break;case 0x28: manage_key8();break;keycode=KEY;列键盘被按下// 读出数据,看是否在此行上的某 break; scancode=(keycode<<1)|0x0f;// 扫描到按下的键,则退出// 否则,更新扫描码继续扫描 }case 0x41:manage_key9();break;case 0x42: manage_key10();break;case 0x44: manage_key11();break;case 0x48: manage_key12();break;case 0x81:manage_key13();break;case 0x82: manage_key14();break;case 0x84: manage_key15();break;case 0x88: manage_key16();break;// default:}}// -------------------------------------------------------------------------------------------------- // 函数名称:manage_key1// 函数功能:按键 1 处理程序// -------------------------------------------------------------------------------------------------- void manage_key1(void){}程序扫描键盘,有键按下完成按键处理,无键按下直接返回。

51单片机04矩阵按键逐行扫描,行列扫描代码

51单片机04矩阵按键逐行扫描,行列扫描代码

矩阵键盘扫描原理方法一:逐行扫描:我们可以通过高四位轮流输出低电平来对矩阵键盘进行逐行扫描,当低四位接收到的数据不全为1的时候,说明有按键按下,然后通过接收到的数据是哪一位为0来判断是哪一个按键被按下。

方法二:行列扫描:我们可以通过高四位全部输出低电平,低四位输出高电平。

当接收到的数据,低四位不全为高电平时,说明有按键按下,然后通过接收的数据值,判断是哪一列有按键按下,然后再反过来,高四位输出高电平,低四位输出低电平,然后根据接收到的高四位的值判断是那一行有按键按下,这样就能够确定是哪一个按键按下了。

//行列扫描#include<reg51.h>#define GPIO_KEY P0#define GPIO_LCD P2unsigned char code a[17]={~0xfc,~0x60,~0xda,~0xf2,~0x66,~0xb6,~0xbe,~0xe0,~0xfe,~0xf6,~0xee,~0x3e,~0x9c,~0x7a,~0xde,~0x8e,~0x00}; //按位取反的用法void delay10ms();void keydown();//要与下面的定义一致void main(){GPIO_LCD=a[16];//初始化数码管while(1){keydown();}}void delay10ms(){unsigned char a,b;for(a=38;a>0;a--)for(b=130;b>0;b--);}void keydown()//检测按下,按下时需要消抖,检测松开,返回按键值//没有按键时保持{unsigned char n=0,key;GPIO_KEY=0x0f;if(GPIO_KEY!=0x0f)//读取按键是否按下{delay10ms(); //延时10ms消抖if(GPIO_KEY!=0x0f)//再次检测按键是否按下{GPIO_KEY=0x0f;//测试列switch(GPIO_KEY){case 0x07: key=0;break;case 0x0b: key=1;break;case 0x0d: key=2;break;case 0x0e: key=3;break;default : GPIO_LCD=a[16];}GPIO_KEY=0xf0;//测试行switch(GPIO_KEY){case 0x70: key=key;break;case 0xb0: key=key+4;break;case 0xd0: key=key+8;break;case 0xe0: key=key+12;break;default : GPIO_LCD=a[16];}GPIO_LCD=a[key];while(++n<5&&GPIO_KEY!=0xf0)//检测按键是否松开 {delay10ms();}}}}//逐行扫描#include<reg51.h>#define GPIO_KEY P0#define GPIO_LED P2unsigned char code a[17]={~0xfc,~0x60,~0xda,~0xf2,~0x66,~0xb6,~0xbe,~0xe0,~0xfe,~0xf6,~0xee,~0x3e,~0x9c,~0x7a,~0xde,~0x8e,~0x00}; //按位取反的用法void delay10ms();void keydown1();//要与下面的定义一致void main(){GPIO_LED=a[16];//初始化数码管while(1){keydown1();}}void keydown1(){unsigned char n=0,key;GPIO_KEY=0x0f;if(GPIO_KEY!=0x0f)//检测按键是否按下{delay10ms();//延时10ms消抖if(GPIO_KEY!=0x0f)//再次检测{GPIO_KEY=0x7f;//高四位轮流输出低电平 if(GPIO_KEY!=0x7f){switch(GPIO_KEY){case 0x77: key=0;goto AA;case 0x7b: key=1;goto AA;case 0x7d: key=2;goto AA;case 0x7e: key=3;goto AA;}}GPIO_KEY=0xbf;{switch(GPIO_KEY){case 0xb7: key=4;goto AA; case 0xbb: key=5;goto AA; case 0xbd: key=6;goto AA; case 0xbe: key=7;goto AA; }}GPIO_KEY=0xdf;if(GPIO_KEY!=0xdf){switch(GPIO_KEY){case 0xd7: key=8;goto AA; case 0xdb: key=9;goto AA; case 0xdd: key=10;goto AA; case 0xde: key=11;goto AA; }}GPIO_KEY=0xef;{switch(GPIO_KEY){case 0xe7: key=12;goto AA;case 0xeb: key=13;goto AA;case 0xed: key=14;goto AA;case 0xee: key=15;goto AA;}}GPIO_LED=a[16];goto BB;AA: GPIO_LED=a[key];BB: GPIO_KEY=0x0f;while(++n<5&&GPIO_KEY!=0x0f) delay10ms();//调用函数别忘记() }}}void delay10ms(){unsigned char a,b;for(a=38;a>0;a--)for(b=130;b>0;b--); }。

单片机矩阵键盘行列扫描程序

单片机矩阵键盘行列扫描程序

//行列扫描程序,可以自己定义端口和扫描方式,这里做简单介绍#include <>//包含头文件#define uchar unsigned char#define uint unsigned intunsigned char const dofly[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//0-Fuchar keyscan(void);void delay(uint i);void main(){uchar key;P2=0x00;//1数码管亮按相应的按键,会显示按键上的字符while(1){key=keyscan();//调用键盘扫描,switch(key){case 0x7e:P0=dofly[0];break;//0 按下相应的键显示相对应的码值case 0x7d:P0=dofly[1];break;//1case 0x7b:P0=dofly[2];break;//2case 0x77:P0=dofly[3];break;//3case 0xbe:P0=dofly[4];break;//4case 0xbd:P0=dofly[5];break;//5case 0xbb:P0=dofly[6];break;//6case 0xb7:P0=dofly[7];break;//7case 0xde:P0=dofly[8];break;//8case 0xdd:P0=dofly[9];break;//9case 0xdb:P0=dofly[10];break;//acase 0xd7:P0=dofly[11];break;//bcase 0xee:P0=dofly[12];break;//ccase 0xed:P0=dofly[13];break;//dcase 0xeb:P0=dofly[14];break;//ecase 0xe7:P0=dofly[15];break;//f}}}uchar keyscan(void)//键盘扫描函数,使用行列反转扫描法{uchar cord_h,cord_l;//行列值P3=0x0f; //行线输出全为0cord_h=P3&0x0f; //读入列线值if(cord_h!=0x0f) //先检测有无按键按下{delay(100); //去抖if(cord_h!=0x0f){cord_h=P3&0x0f; //读入列线值P3=cord_h|0xf0; //输出当前列线值cord_l=P3&0xf0; //读入行线值return(cord_h+cord_l);//键盘最后组合码值 }}return(0xff); //返回该值}void delay(uint i)//延时函数{while(i--);}。

C51单片机矩阵键盘扫描去抖程序

C51单片机矩阵键盘扫描去抖程序

C51单片机矩阵键盘扫描去抖程序最近有一个C51的项目,用的是新华龙的C51 F020单片机。

项目中要实现4*5的矩阵键盘。

矩阵电路图如下如示其中,四条列线接在F020的P2~P5口线上,5条行线接在P5口线上(F020的P5口是不同于普通C51的扩展接口,不能位寻址)。

同时4条列线接在一四输入与非门(74LS20)上,门输出接F020的外中断1,这样,任何一键按下,都会产生中断,通知程序进行键盘扫描。

托一个新手给写了键盘的扫描程序,基本功能都能实现,但对于键盘的去抖处理总是做不好,表现是或者不能去抖,或者按键响应过慢,或者采集到错误键值。

看来新手对于矩阵键盘扫描原理掌握较好(网上资料多),但对于键盘去抖的知识却有所欠缺,基本都是按照书上说的延时一段时间再采集键值,实际应用中,这样的处理是远远不够的,过于简单。

实际去抖处理应该这样进行更合理一些,即连续采集键值,当采集到的键值在一段时间内是相同的,即认为按键状态已稳定,此键值为真实键值。

另外,按键释放时,也会有抖动,导致误采键值,因此在键释放时,也应进行去抖处理,处理方法同时是连续一段时间采集到无键按下状态,才认为按键被释放。

根据这个方法,我重写了新手的程序,实际应用中表现极好。

现将程序公布如下,供新手参考。

Key.h文件内容#ifndef __key_H__#define __key_H__#define NULL_KEY 0x0000#define S1 0x3801#define S2 0x3401#define S3 0x3802#define S4 0x3402#define S5 0x3804#define S6 0x3404#define S7 0x3808#define S8 0x3408#define S9 0x3810#define S10 0x3410#define S11 0x2C01#define S12 0x1C01#define S13 0x2C02#define S14 0x1C02#define S15 0x2C04#define S16 0x1C04#define S17 0x2C08#define S18 0x1C08#define S19 0x2C10#define S20 0x1C10#define KEY_DELAY 20extern unsigned int Key_Value;extern void Init_Key();extern void Scan_Key();extern bit Key_Pressed;extern bit Key_Released;extern unsigned int idata Keypress_Count;extern unsigned int idata Keyrelease_Count;#endifkey.c 文件内容#include <string.h>#include "key.h"bit Key_Down; //是否有键按下的标志unsigned int idata Keypress_Count;sbit Col_Key0 = P2^2;sbit Col_Key1 = P2^3;sbit Col_Key2 = P2^4;sbit Col_Key3 = P2^5;bit Key_Pressed;bit Key_Released;unsigned int Key_Value;bit Key_Down; //是否有键按下的标志unsigned int idata Keypress_Count; //一毫秒增加一次的变量unsigned int idata Keyrelease_Count; //一毫秒增加一次的变量//矩阵键盘使用中断1作为键盘中断void Init_Key(){P5 = 0; //行线全部置为0EX1 = 1; // 允许外部时钟秒中断IT1 = 1; // 外部时钟中断设置为边沿触发}void Key_Int() interrupt 2{Key_Pressed = 1;EX1 = 0;}void Scan_Key(){unsigned char temp,rowvalue;unsigned int key;int i;temp = P2;temp &= 0x3C;if(temp == 0x3C){Key_Released = 0;Key_Pressed = 0;key = NULL_KEY;EX1 = 1;}else{key = temp;key = key<<8;rowvalue = 0x01;for(i=0;i<5;i++){P5 = rowvalue<<i;DelayMs(1);temp = P2;temp &= 0x3C;if(temp == 0x3c){rowvalue = rowvalue<<i;key = key | rowvalue;P5 = 0x00;break;}}P5 = 0x00;DelayMs(1);}if(key!=NULL_KEY) //如果有键按下{if(key==Key_Value) //如果按下的是相同的键{if(Keypress_Count>=KEY_DELAY){Key_Down = 1;}}else if(Key_Down != 1){Keypress_Count=0;Keyrelease_Count = 0;Key_Value=key;}}else //如果无键按下{if(Key_Down) //如果当前是键释放,返回键值{if(Keyrelease_Count >= KEY_DELAY){Key_Down=0;Keypress_Count=0;Keyrelease_Count=0;Key_Released = 1;EX1 = 1;return;}}else{Keypress_Count=0;Keyrelease_Count=0;Key_Value = NULL_KEY;EX1 = 1;return;}}}在main.c中的调用方法为if(Key_Pressed == 1){//Key_Pressed = 0;Scan_Key();}if(Key_Released == 1){Key_Released = 0;Ack_Key();}其中Ack_Key()函数为具体的键盘响应程序,就不列出了。

[单片机矩阵键盘实验实验报告范文]矩阵键盘实验心得

[单片机矩阵键盘实验实验报告范文]矩阵键盘实验心得

[单片机矩阵键盘实验实验报告范文]矩阵键盘实验心得实验五矩阵键盘实验一、实验内容1、编写程序,做到在键盘上每按一个数字键(0-F)用发光二极管将该代码显示出来。

按其它键退出。

2、加法设计计算器,实验板上有12个按键,编写程序,实现一位整数加法运算功能。

可定义“A”键为“+”键,“B”键为“=”键。

二、实验目的学习独立式按键的查询识别方法。

2、非编码矩阵键盘的行反转法识别方法。

三、实验说明1、MCS51系列单片机的P0~P3口作为输入端口使用时必须先向端口写入“1”。

2、用查询方式检测按键时,要加入延时(通常采用软件延时10~20mS)以消除抖动。

3、识别键的闭合,通常采用行扫描法和行反转法。

行扫描法是使键盘上某一行线为低电平,而其余行接高电平,然后读取列值,如读列值中某位为低电平,表明有键按下,否则扫描下一行,直到扫完所有行。

行反转法识别闭合键时,要将行线接一并行口,先让它工作在输出方式,将列线也接到一个并行口,先让它工作于输入方式,程序使CPU通过输出端口在各行线上全部送低电平,然后读入列线值,如此时有某键被按下,则必定会使某一列线值为0。

然后,程序对两个并行端口进行方式设置,使行线工作于输入方式,列线工作于输出方式,并将刚才读得的列线值从列线所接的并行端口输出,再读取行线上输入值,那么,在闭合键所在行线上的值必定为0。

这样,当一个键被接下时,必定可以读得一对唯一的行线值和列线值。

由于51单片机的并口能够动态地改变输入输出方式,因此,矩阵键盘采用行反转法识别最为简便。

行反转法识别按键的过程是:首先,将4个行线作为输出,将其全部置0,4个列线作为输入,将其全部置1,也就是向P1口写入0某F0;假如此时没有人按键,从P1口读出的值应仍为0某F0;假如此时1、4、7、0四个键中有一个键被按下,则P1.6被拉低,从P1口读出的值为0某B0;为了确定是这四个键中哪一个被按下,可将刚才从P1口读出的数的低四位置1后再写入P1口,即将0某BF写入P1口,使P1.6为低,其余均为高,若此时被按下的键是“4”,则P1.1被拉低,从P1口读出的值为0某BE;这样,当只有一个键被按下时,每一个键只有唯一的反转码,事先为12个键的反转码建一个表,通过查表就可知道是哪个键被按下了。

(原创)51单片机C语言程序设计--速学教程实例(入门篇)之矩阵键盘(逐行扫描法)

(原创)51单片机C语言程序设计--速学教程实例(入门篇)之矩阵键盘(逐行扫描法)

Delay1ms(5); temp=P3; temp=temp&0x0f; if(temp!=0x0f) { temp=P3; switch(temp) { case 0xde:num=9; break; case 0xdd:num=10; break; case 0xdb:num=11; break; case 0xd7:num=12; break; } } } else num=17; P3=0xef; temp=P3; temp=temp&0x0f; if(temp!=0x0f) { Delay1ms(5); temp=P3; temp=temp&0x0f; if(temp!=0x0f) { temp=P3; switch(temp) { case 0xee:num=13; break; case 0xed:num=14; break; case 0xeb:num=15; break; case 0xe7:num=16; break; } }
case 0x7e:num=1; break; case 0x7d:num=2; break; case 0x7b:num=3; break; case 0x77:num=4; break; } } } else num=17; P3=0xbf; temp=P3; temp=temp&0x0f; if(temp!=0x0f) { Delay1ms(5); temp=P3; temp=temp&0x0f; if(temp!=0x0f) { temp=P3; switch(temp) { case 0xbe:num=5; break; case 0xbd:num=6; break; case 0xbb:num=7; break; case 0xb7:num=8; break; } } } else num=17; P3=0xdf; temp=P3; temp=temp&0x0f; if(temp!=0x0f) {

51单片机的矩阵按键扫描的设计C语言程序

51单片机的矩阵按键扫描的设计C语言程序

51单片机的矩阵按键扫描的设计C语言程序以下为一个基于51单片机的矩阵按键扫描的设计C语言程序:```c#include <reg51.h>//定义端口连接到矩阵键盘sbit col1 = P2^0;sbit col2 = P2^1;sbit col3 = P2^2;sbit row1 = P2^3;sbit row2 = P2^4;sbit row3 = P2^5;sbit row4 = P2^6;//声明按键函数char read_keypad(;void maiwhile (1)char key = read_keypad(; // 读取按键值//根据按键值进行相应操作switch(key)case '1'://第一行第一列按键逻辑//在此处添加相应的代码break;case '2'://第一行第二列按键逻辑//在此处添加相应的代码break;//继续处理其他按键//...default://未识别到按键break;}}//按键扫描函数char read_keypacol1 = 0; col2 = 1; col3 = 1; // 激活第一列if (row1 == 0) { // 第一行第一列按键被按下while (row1 == 0); //等待按键释放return '1'; // 返回按键值}if (row2 == 0) { // 第二行第一列按键被按下while (row2 == 0); //等待按键释放return '4'; // 返回按键值}if (row3 == 0) { // 第三行第一列按键被按下while (row3 == 0); //等待按键释放return '7'; // 返回按键值}if (row4 == 0) { // 第四行第一列按键被按下while (row4 == 0); //等待按键释放return '*'; // 返回按键值}col1 = 1; col2 = 0; col3 = 1; // 激活第二列//处理第二列的按键逻辑//...col1 = 1; col2 = 1; col3 = 0; // 激活第三列//处理第三列的按键逻辑//...return '\0'; // 返回空字符表示未检测到按键```以上代码中,我们使用51单片机的P2端口连接到矩阵键盘的列和行,通过扫描不同的列和检测行的状态来判断按键是否被按下。

单片机矩阵按键c语言编程

单片机矩阵按键c语言编程

/*矩阵按键,说明数码管显示用的是阳极的,若你用的是阴极的,你可以把table中元素取反,P0口取反*/#include<reg52.h>#define uchar unsigned char#define uint unsigned intsbit dula=P2^6;sbit wela=P2^7;uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};void delay(uint x){uint i,j;for(i=x;i>0;i--)for(j=110;j>0;j--);}void display(uchar num){P0=table[num];dula=1;dula=0;}void mascan(){uchar temp,key;P3=0xfe;temp=P3;temp=temp&0xf0;if(temp!=0xf0){delay(10);temp=P3;temp=temp&0xf0;if(temp!=0xf0){temp=P3;switch(temp){case 0xee:key=0;break;case 0xde:key=1;break;case 0xbe:key=2;break;case 0x7e:key=3;break;}while(temp!=0xf0){temp=P3;temp=temp&0xf0;}display(key);}}P3=0xfd;temp=P3;temp=temp&0xf0;if(temp!=0xf0){delay(10);temp=P3;temp=temp&0xf0;if(temp!=0xf0){temp=P3;switch(temp){case 0xed:key=4;break;case 0xdd:key=5;break;case 0xbd:key=6;break;case 0x7d:key=7;break;}while(temp!=0xf0){temp=P3;temp=temp&0xf0;}display(key);}}P3=0xfb;temp=P3;temp=temp&0xf0;if(temp!=0xf0){delay(10);temp=P3;temp=temp&0xf0;if(temp!=0xf0){temp=P3;switch(temp){case 0xeb:key=8;break;case 0xdb:key=9;break;case 0xbb:key=10;break;case 0x7b:key=11;break;}while(temp!=0xf0){temp=P3;temp=temp&0xf0;}display(key);}}P3=0xf7;temp=P3;temp=temp&0xf0;if(temp!=0xf0){delay(10);temp=P3;temp=temp&0xf0;if(temp!=0xf0){temp=P3;switch(temp){case 0xe7:key=12;break;case 0xd7:key=13;break;case 0xb7:key=14;break;case 0x77:key=15;break;}while(temp!=0xf0){temp=P3;temp=temp&0xf0;}display(key);}}}void main(){P0=1;dula=1;dula=0;P0=0x3f;wela=1;wela=0;while(1){ mascan(); }}。

51单片机矩阵键盘的编程

51单片机矩阵键盘的编程

51单片机矩阵键盘的编程C51 单片机上的外设键盘键是使用的矩阵方式扩展的,但是硬件仿真时必须把蜂民器的开关打开触使行扫描的74HC53 的E 端接地为输出型,否则测死了也没反应,我还以为是我的程序有问题呢,后来才找到的。

其原理74HC138 译码器在输出端Y1 与WR(P3)都处于低电平通过或非门,转化成行扫描的74HC53 的片选端打开写入数据,在输出端的高4 位通过移位方式输出到外设键盘中。

然后给WR 一个高电平来给74HC53 一个低电平使得输入无效进行锁存操作。

然后通过RD(P3)与Y2 共同输出低电平通过或非门加上个非门把低电平送到列扫描的74HC53 的片选端E 上,在读取数据前必须先将要获取的高4 位进行置1,然后读取高4 位数据,通过RD 送出高电平进行锁住输出,防止74HC53 同时输入输出导致芯片烧毁。

然后根据获得的unsigned char 进行移位比对操作来获得是哪一列,然后在通过运算得到第几个按键被按下。

这是最简单的矩阵方式扩展键盘的代码流程,上述是我理解的流程,测试已没问题。

#includereg52.h#includeabsacc.hvoid my_delay10nms(unsigned int n){unsigned i,j;while(n --){for(i = 128;i 0;i --)for(j = 10;j 0;j --);}}sbit LED_BIT = P1;vo i dmain(void){unsigned char Key_h;unsigned char Key_Val;unsigned char Key_r;unsigned char Last_key;unsigned char Key_Temp;while(1){Key_Val=0;for(Key_h=4;Key_h8;Key_h++){P2=0x88;P0=(1Key_h);P3=~(16);P3|=(16);P2=0x90;P3=~(17); //读P0|=0xf0;Key_Temp=P00xf0; // P3|=(17); // 防止芯片烧坏if(Key_Temp) {for(Key_r=4;Key_r8;Key_r++){if(Key_Temp(1Key_r)){Key_Val=(Key_h-。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Delay1ms(5); temp=P3; temp=temp&0x0f; if(temp!=0x0f) { temp=P3; switch(temp) { case 0xde:num=9; break; case 0xdd:num=10; break; case 0xdb:num=11; break; case 0xd7:num=12; break; } } } else num=17; P3=0xef; temp=P3; temp=temp&0x0f; if(temp!=0x0f) { Delay1ms(5); temp=P3; temp=temp&0x0f; if(temp!=0x0f) { temp=P3; switch(temp) { case 0xee:num=13; break; case 0xed:num=14; break; case 0xeb:num=15; break; case 0xe7:num=16; break; } }
} else num=17; return num; } /**********************************************************Байду номын сангаас*******/ /* 名称:主函数 */ /* 功能:将对应的按键值显示出来 */ /******************************************************************/ void main() { uchar key; P2=0x00; //第一个数码管亮 按相应的按键,会显示按键上的字符 while(1) { key=keyscan(); //调用键盘扫描 if((key-1)<16) P0=table[(key-1)]; else P0=0x00; } }
/******************************************************************/ /* 名称:矩阵键盘逐行扫描法 */ /* 作者:苏涛 */ /* 时间:2011-01-15 */ /* 单位:安徽建筑工业学院 电子与信息工程学院 */ /* 07 级电子信息工程专业 二班 */ /******************************************************************/ #include <reg52.h> //头文件调用,写程序时都要加上 #define uint unsigned int //宏定义,为了后面定义变量书写简便 #define uchar unsigned char uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f, 0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//共阴数码管 0-f /******************************************************************/ /* 名称:延时函数 */ /* 功能:C 语言中常用的 for 循环延时方法 */ /* 延时长短可以通过变量初值来改变 */ /******************************************************************/ void Delay1ms(uint count) { uint i,j; for(i=0;i<count;i++) for(j=0;j<110;j++); } /******************************************************************/ /* 名称:按键扫描函数 */ /* 功能:逐行检测是否有键按下 */ /* 有或者没有都有返回值 */ /******************************************************************/ uchar keyscan() { uchar num,temp; P3=0x7f; temp=P3; temp=temp&0x0f; if(temp!=0x0f) { Delay1ms(5);//按键去抖动 temp=P3; temp=temp&0x0f; if(temp!=0x0f) { temp=P3; switch(temp) {
case 0x7e:num=1; break; case 0x7d:num=2; break; case 0x7b:num=3; break; case 0x77:num=4; break; } } } else num=17; P3=0xbf; temp=P3; temp=temp&0x0f; if(temp!=0x0f) { Delay1ms(5); temp=P3; temp=temp&0x0f; if(temp!=0x0f) { temp=P3; switch(temp) { case 0xbe:num=5; break; case 0xbd:num=6; break; case 0xbb:num=7; break; case 0xb7:num=8; break; } } } else num=17; P3=0xdf; temp=P3; temp=temp&0x0f; if(temp!=0x0f) {
相关文档
最新文档