51单片机矩阵键盘扫描程序
毕业设计(论文)-基于51单片机控制的电子密码锁设计
基于51单片机控制的电子密码锁设计摘要:本设计以单片机以AT89C51作为密码锁监控装置的检测和控制核心,分为主机控制和从机执行机构,实现要是信息在主机的初步认证注册、密码信息的加密、钥匙丢失报废等功能。
根据51单片机之间的串行通信原理,这便对于密码信息的随机加密和保护。
而且采用键盘输入的电子密码锁具有较高的优势。
采用数字信号编码和二次调制方式,不仅可以实现多路信息的控制,提高信号传输的抗干扰性,减少错误动作,而且功率消耗低;反应速度快、传输效率高、工作稳定可靠等。
软件设计采用自上而下的模块化设计思想,以使系统朝着分布式、小型化方向发展,增强系统可扩展性和运行的稳定性。
测试结果表明,本系统各功能已达到本设计的所有要求。
关键词:AT89C51;密码锁;单片机设计;电子锁目录摘要 (1)关键词 (1)第一章密码锁的简介及现况 (1)1.1引言 (1)1.2电子密码锁的简介 (1)1.3电子密码锁发展趋势 (2)1.4本设计所要实现的目标 (2)1.5设计的密码锁的功能 (2)第二章设计方案的选择 (3)2.1方案的论证与比较 (3)第三章单片机的组成 (4)3.1AT89C51单片机的简介 (4)3.2电路图的绘制 (7)第四章单片机硬件资源 (7)4.1开锁机构 (7)4.2按键电路设计 (8)4.3显示电路设计 (10)4.4AT89C51单片机复位方式 (11)4.5密码锁的电源电路设计 (12)第五章程序调试 (13)5.1程序调试用到的软件及工具 (13)5.2KEIL C51简介 (14)5.3调试过程 (14)5.4调试、仿真与实现 (15)第六章软件设计 (16)6.1系统软件设计的总统思想 (16)6.2各子程序设计 (17)1 键盘扫描子程序 (17)2 LED显示子程序 (18)3 密码比较和报警程序 (19)设计总结与展望 (21)致谢 (22)附录:总原理图 (22)参考文献 (24)第一章密码锁的简介及现况1.1引言在日常的生活和工作中,住宅与部门的安全防范、单位的文件档案、财务报表以及一些个人资料的保存多以加锁的办法来解决。
单片机按键程序设计
单片机按键程序设计单片机按键的基本原理其实并不复杂。
通常,按键就是一个简单的开关,当按键按下时,电路接通,对应的引脚电平发生变化;当按键松开时,电路断开,引脚电平恢复到初始状态。
在程序设计中,我们需要不断检测引脚的电平变化,从而判断按键是否被按下。
在实际的按键程序设计中,有多种方式可以实现按键检测。
其中一种常见的方法是查询法。
这种方法是通过不断地读取按键对应的引脚状态来判断按键是否被按下。
以下是一个简单的查询法示例代码:```cinclude <reg51h> //包含 51 单片机的头文件sbit key = P1^0; //定义按键连接的引脚void main(){while(1) //无限循环{if(key == 0) //如果按键按下,引脚为低电平{//执行按键按下的操作//比如点亮一个 LED 灯P2 = 0xfe;while(key == 0);//等待按键松开}}}```上述代码中,我们首先定义了按键连接的引脚`key`,然后在主函数的无限循环中不断检测按键引脚的状态。
当检测到按键按下时,执行相应的操作,并通过`while(key == 0)`等待按键松开。
除了查询法,还有中断法可以用于按键检测。
中断法的优点是能够及时响应按键动作,不会因为程序的其他操作而导致按键响应延迟。
```cinclude <reg51h> //包含 51 单片机的头文件sbit key = P1^0; //定义按键连接的引脚void int0_init()//中断初始化函数{IT0 = 1; //下降沿触发中断EX0 = 1; //使能外部中断 0EA = 1; //开总中断}void int0() interrupt 0 //外部中断 0 服务函数{//执行按键按下的操作//比如点亮一个 LED 灯P2 = 0xfe;}void main(){int0_init();//初始化中断while(1);//无限循环,保持程序运行}```在上述代码中,我们首先在`int0_init` 函数中对中断进行了初始化设置,然后在`int0` 函数中编写了按键按下时的处理代码。
51单片机矩阵键盘线反转法体会
51单片机矩阵键盘线反转法体会独立式键盘扫描只需读取IO口状态,而矩阵式键盘描通常有两种实现方法:逐行扫描法和线反转法。
(1)逐行扫描法依次从第一至最末行线上发出低电平信号, 如果该行线所连接的键没有按下的话, 则列线所接的端口得到的是全“1”信号, 如果有键按下的话, 则得到非全“1”信号。
(2)线反转法线反转法比行扫描速度快,原理是先将行线作为输出线, 列线作为输入线, 行线输出全“0”信号, 读入列线的值, 那么在闭合键所在的列线上的值必为0;然后从列线输出全“0”信号,再读取行线的输入值,闭合键所在的行线值必为 0。
这样,当一个键被按下时, 必定可读到一对唯一的行列值。
再由这一对行列值可以求出闭合键所在的位置。
/*在TX-1C实验板上实现如下描述:实验板上电时,数码管不显示,顺序按下矩阵键盘后,在数码管上依次显示0~F,6个数码管同时显示。
这里用“线反转”的方法写,可以代替郭天祥书上例【4.2.1】该书上使用逐行扫描的方式。
*/#include<reg52.h>#define uchar unsigned char#define uint unsigned intsbit duan=P2^6; //打开位选和段选sbit wei=P2^7;uchar code table[]={ //数码管显示数值表0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};void delay(uint x) //毫秒级延时函数{uint i,j;for(i=x;i>0;i--)for(j=110;j>0;j--);}void xianshi(uchar num) //段选显示函数{P0=table[num];duan=1;duan=0;}uchar keyscan(void) //矩阵键盘扫描函数{uchar h,l; //定义行、列值中间变量P3=0x0f; //列线输出全为0h=P3&0x0f; //读入行线if(h!=0x0f) //检测有无按键按下{ delay(10); //延时去抖if(h!=0x0f) //如果确实按下{h=P3&0x0f; //再次读入行线P3=0xf0; //输出当前列线值,行线反转l=P3&0xf0; //读入列线值return (h+l); //键盘最后组合编码值,也就是键值}}return 0xff; //其余情况返回该值}void main(){uchar key;P0=0; //关闭所有数码管段选,实验板上电数码管不显示duan=1;duan=0;P0=0xc0; //选中6位数码管wei=1;wei=0;while(1){key=keyscan(); //用key读取keyscan()的值switch(key){case 0xee: key=0; while(keyscan()!=0xff); xianshi(key); break;//while(keyscan()!=0xff)是松手检测语句,松手时检测case 0xde: key=1; while(keyscan()!=0xff); xianshi(key); break; //keyscan()函数会得到返回值0xff,!=oxff时表示按下去了case 0xbe: key=2; while(keyscan()!=0xff); xianshi(key); break;case 0x7e: key=3; while(keyscan()!=0xff); xianshi(key); break;case 0xed: key=4; while(keyscan()!=0xff); xianshi(key); break;case 0xdd: key=5; while(keyscan()!=0xff); xianshi(key); break;case 0xbd: key=6; while(keyscan()!=0xff); xianshi(key); break;case 0x7d: key=7; while(keyscan()!=0xff); xianshi(key); break;case 0xeb: key=8; while(keyscan()!=0xff); xianshi(key); break;case 0xdb: key=9; while(keyscan()!=0xff); xianshi(key); break;case 0xbb: key=10; while(keyscan()!=0xff); xianshi(key); break;case 0x7b: key=11; while(keyscan()!=0xff); xianshi(key); break;case 0xe7: key=12; while(keyscan()!=0xff); xianshi(key); break;case 0xd7: key=13; while(keyscan()!=0xff); xianshi(key); break;case 0xb7: key=14; while(keyscan()!=0xff); xianshi(key); break;case 0x77: key=15; while(keyscan()!=0xff); xianshi(key); break;default: break;}}}/*后记*//*刚开始写这个程序时我把主函数里面的switch—case语句这样写的,while(1){key=keyscan(); //用key读取keyscan()的值switch(key){case 0xee: key=0; break;case 0xde: key=1; break;case 0xbe: key=2; break;case 0x7e: key=3; break;case 0xed: key=4; break;case 0xdd: key=5; break;case 0xbd: key=6; break;case 0x7d: key=7; break;case 0xeb: key=8; break;case 0xdb: key=9; break;case 0xbb: key=10; break;case 0x7b: key=11; break;case 0xe7: key=12; break;case 0xd7: key=13; break;case 0xb7: key=14; break;case 0x77: key=15; break;default: break;}xianshi(key);}运行程序后发现当手按下按键时会有数码的显示,但是一旦放开按键数码管就什么都不显示了。
51键盘矩阵扫描程序
51键盘矩阵扫描程序假设按下的是S1键进行如下检测(4*4键盘)先在P3口输出p3 00001111低四位行会有变化cord_h =00001111&00001110 =00001110if !=00001111延时0.1uscord_h=00001110&00001111=00001110if !=00001111P3再输出11111110P3 =00001110|11110000=11111110输出高四位cord_l=P3&0xf0 //此时P3口就是(实际值)输入值01111110 而不是上面的11111110cord_l=01111110&11110000=01110000cord_h+cord_l=00001110+01110000=01111110=0x7e //此编码即为S1的编码#include <reg52.h>//包含头文件#define uchar unsigned char#define uint unsigned intunsigned char consttable[]={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=table[0];break;//0 按下相应的键显示相对应的码值case 0x7d:P0=table[1];break;//1case 0x7b:P0=table[2];break;//2case 0x77:P0=table[3];break;//3case 0xbe:P0=table[4];break;//4case 0xbd:P0=table[5];break;//5case 0xbb:P0=table[6];break;//6case 0xb7:P0=table[7];break;//7case 0xde:P0=table[8];break;//8case 0xdd:P0=table[9];break;//9case 0xdb:P0=table[10];break;//acase 0xd7:P0=table[11];break;//bcase 0xee:P0=table[12];break;//ccase 0xed:P0=table[13];break;//dcase 0xeb:P0=table[14];break;//ecase 0xe7:P0=table[15];break;//f}}}uchar keyscan(void)//键盘扫描函数,使用行列反转扫描法{uchar cord_h,cord_l;//行列值P3=0x0f; //行线输出全为0cord_h=P3&0x0f; //读入列线值if(cord_h!=0x0f) //先检测有无按键按下{delay(100); //去抖cord_h=P3&0x0f; //读入列线值if(cord_h!=0x0f){P3=cord_h|0xf0; //输出当前列线值cord_l=P3&0xf0; //读入行线值return(cord_h+cord_l);//键盘最后组合码值}}return(0xff); //返回该值}void delay(uint i)//延时函数{while(i--);}。
经典的矩阵键盘扫描程序
经典的矩阵键盘扫描程序查找哪个按键被按下的方法为:一个一个地查找。
先第一行输出0,检查列线是否非全高;否则第二行输出0,检查列线是否非全高;否则第三行输出0,检查列线是否非全高;如果某行输出0时,查到列线非全高,则该行有按键按下;根据第几行线输出0与第几列线读入为0,即可判断在具体什么位置的按键按下。
下面是具体程序:void Check_Key(void){unsigned char row,col,tmp1,tmp2;tmp1 = 0x10; //tmp1用来设置P1口的输出,取反后使P1.4~P1.7中有一个为0for(row=0;row<4;row++) // 行检测{P1 = 0x0f; // 先将p1.4~P1.7置高P1 =~tmp1; // 使P1.4~p1.7中有一个为0tmp1*=2; // tmp1左移一位if ((P1 & 0x0f) < 0x0f) // 检测P1.0~P1.3中是否有一位为0,只要有,则说明此行有键按下,进入列检测{tmp2 = 0x01; // tmp2用于检测出哪一列为0for(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; //扫描第一列temp=P1;temp=temp&0xF0;if(temp!=0xF0) //如果本列有键按下{switch(temp){case 0xE0: //第一行有键按下key=1;break;case 0xD0: //第二行有键按下key=4;break;case 0xB0: //第三行有键按下key=8;break;case 0x70: //第四行有键按下key=12;break;}}P1=0xFD; //扫描第二列temp=P1;temp&=0xF0;if(temp!=0xF0){switch(temp){case 0xE0: //第一行有键按下key=1;break;case 0xD0: //第二行有键按下key=5;break;case 0xB0: //第三行有键按下key=9;break;case 0x70: //第四行有键按下key=13;break;}}P1=0xFb; //扫描第三列temp=P1;temp&=0xF0;if(temp!=0xF0){switch(temp){case 0xE0: //第一行有键按下key=2;break;case 0xD0: //第二行有键按下key=6;break;case 0xB0: //第三行有键按下key=10;break;case 0x70: //第四行有键按下key=14;break;}}P1=0xF7; //扫描第四列temp=P1;temp&=0xF0;if(temp!=0xF0){switch(temp){case 0xE0: //第一行有键按下key=3;break;case 0xD0: //第二行有键按下key=7;break;case 0xB0: //第三行有键按下key=11;break;case 0x70: //第四行有键按下key=15;break;}}}return(key);}}//延时程序void delay10ms(){unsigned char i,j;for(i=0;i<10;b++)for(j=0;j<120;j++)//延时1ms{}}//等待按键释放程序uchar key_free(){key=key_scan(); //取扫描到的键值P1=0xF0;//置行线全为高电平,列线全为低电平wheile(P1&0xF0!=0xF0) //如果仍有键按下{}return(key);//返回键值}51单片机矩阵键盘扫描、数码管显示键值实验/***********************************************程序名称:矩阵键盘扫描显示键值简要说明:P1口接矩阵键盘:低四位列,高四位行使用共阳型数码管:P0口输出数码管段码,P2口输出数码管位码编写:***********************************************/#include <AT89x52.h>#define uchar unsigned char;uchar key_val=0; //定义键值,初始默认为0uchar code TAB[16]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xC6,0xa1,0x86,0x8e}; //0~F 共阳数码管显示段码/*****按键扫描*****/void Check_Key(void){unsigned char row,col,tmp1,tmp2;tmp1 = 0x10; //tmp1用来设置P1口的输出,取反后使P1.4~P1.7中有一个为0for(row=0;row<4;row++) // 行检测{P1 = 0x0f; // 先将p1.4~P1.7置高P1 =~tmp1; // 使P1.4~p1.7中有一个为0tmp1*=2; // tmp1左移一位if ((P1 & 0x0f) < 0x0f) // 检测P1.0~P1.3中是否有一位为0,只要有,则说明此行有键按下,进入列检测{tmp2 = 0x01; // tmp2用于检测出哪一列为0for(col =0;col<4;col++) // 列检测{if((P1 & tmp2)==0x00) // 该列如果为低电平则可以判定为该列{key_val = row*4 +col; // 获取键值,识别按键return; // 退出循环}tmp2*=2; // tmp2左移一位}}}}/*****主函数,显示键值*****/void main(){P2=0x00; //位码,这里全部置低,点亮8位数码管(见视频效果)while(1){Check_Key();P0=TAB[key_val]; //显示}}实验7 矩阵按键识别技术矩阵按键部分由16个轻触按键按照4行4列排列,连接到JP50端口。
51单片机应用程序实例
广告灯的左移右移
1. 实验任务
做单一灯的左移右移,硬件电路如图 4.1 所示,八个发光二极管 L1-L8 分别接在单 片机的 P1.0-P1.7 接口上,输出“0”时,发光二极管亮,开始时 P1.0→P1.1→P1.2→P1.3→┅→P1.7→P1.6→┅→P1.0 亮,重复循环。
2. 电路原理图
图 4.1
每次送出的数据是不同,具体的数据如下表 1 所示
P1.7 P1.6 P1.5 P1.4 P1.3 P1.2 P1.1 L8 L7 L6 L5 L4 L3 L2 1111111 1111110 1111101 1111011
P1.0 L1 0 1 1 1
说明
L1 亮 L2 亮 L3 亮 L4 亮
1110111 1 1101111 1 1011111 1 0111111 1
一键多功能按键识别技术
1.实验任务 如图 9.1 所示,开关 SP1 接在 P3.7/RD 管脚上,在 AT89S51 单片机的 P1 端口接有四 个发光二极管,上电的时候,L1 接在 P1.0 管脚上的发光二极管在闪烁,当每一次按 下开关 SP1 的时候,L2 接在 P1.1 管脚上的发光二极管在闪烁,再按下开关 SP1 的时 候,L3 接在 P1.2 管脚上的发光二极管在闪烁,再按下开关 SP1 的时候,L4 接在 P1.3 管脚上的发光二极管在闪烁,再按下开关 SP1 的时候,又轮到 L1 在闪烁了,如此轮 流下去。 2.电路原理图
矩阵式键盘设计实训报告
一、实验目的1. 掌握矩阵式键盘的工作原理及电路设计方法。
2. 熟悉单片机与矩阵键盘的接口连接及编程技巧。
3. 提高动手实践能力,培养创新意识。
二、实验设备1. 单片机实验平台2. 矩阵键盘模块3. 数字多用表4. 编译器(如Keil51)5. 连接线三、实验原理矩阵键盘是一种常用的键盘设计方式,通过行列交叉点连接按键,从而实现多个按键共用较少的I/O端口。
矩阵键盘通常采用逐行扫描的方式检测按键状态,当检测到按键按下时,根据行列线的电平状态确定按键位置。
四、实验内容1. 矩阵键盘电路设计2. 矩阵键盘编程3. 矩阵键盘测试与调试五、实验步骤1. 电路设计(1)根据矩阵键盘的规格,确定行线和列线的数量。
(2)将行线和列线分别连接到单片机的I/O端口。
(3)在行线上串联电阻,防止按键抖动。
(4)连接电源和地线。
2. 编程(1)初始化单片机的I/O端口,将行线设置为输出,列线设置为输入。
(2)编写逐行扫描程序,逐行拉低行线,读取列线状态。
(3)根据行列线状态判断按键位置,并执行相应的操作。
3. 测试与调试(1)将编写好的程序下载到单片机中。
(2)连接矩阵键盘,观察按键是否正常工作。
(3)使用数字多用表检测行列线电平,确保电路连接正确。
(4)根据测试结果,对程序进行调试,直到矩阵键盘正常工作。
六、实验结果与分析1. 电路连接正确,按键工作正常。
2. 逐行扫描程序能够正确检测按键位置。
3. 按键操作能够触发相应的程序功能。
七、实验总结1. 通过本次实训,掌握了矩阵式键盘的工作原理及电路设计方法。
2. 熟悉了单片机与矩阵键盘的接口连接及编程技巧。
3. 提高了动手实践能力,培养了创新意识。
八、心得体会1. 在实验过程中,遇到了电路连接错误和程序调试困难等问题,通过查阅资料、请教老师和同学,最终成功解决了问题。
2. 本次实训让我深刻体会到理论知识与实际操作相结合的重要性,同时也认识到团队合作的重要性。
九、改进建议1. 在电路设计过程中,可以考虑增加去抖动电路,提高按键稳定性。
基于51单片机的“扫地机器人”设计报告
第十二届智能控制设计大赛初级组之基于51单片机的“扫地机器人”设计报告目录一、设计要求 ........................................................................................ 错误!未定义书签。
1.基本要求:.......................................................................................... 错误!未定义书签。
2.拓展要求:.......................................................................................... 错误!未定义书签。
二、设计思路 ........................................................................................ 错误!未定义书签。
三、方案比较 (3)1、洞洞板的选择 (3)2、芯片的选择 (3)3、单片机键盘的选择 (3)4、LCD的选择...................................................................................... 错误!未定义书签。
5、电源的选择....................................................................................... 错误!未定义书签。
6、储存模块的选择 (4)7、时钟模块的选择 (4)8、最终选用方案 (4)四、一些模块的选择及底盘制作 ........................................................... 错误!未定义书签。
51单片机简易计算器设计报告
51单片机简易计算器设计报告
本文将介绍51单片机简易计算器的设计报告。
该计算器通过
16位的LCD显示屏实现了基本计算功能,包括加、减、乘、除、取反、开方等。
1. 硬件设计
该计算器的核心部件是STC89C52单片机。
STC89C52是一种
高性能、低功耗的8位单片机,拥有8KB的Flash程序存储器和128字节的内部RAM,可提供多种功能和通讯接口。
通过
I/O口与LCD模块通讯,实现输出功能。
该计算器使用16位的LCD显示屏,显示范围为-99.99~99.99,共有6个数字位。
显示屏使用了ST7920控制器,可通过串行、并行等多种方式控制。
2. 软件设计
该计算器的软件设计主要包括三部分:键盘扫描,计算功能和LCD显示。
键盘扫描:该计算器采用4x5矩阵键盘,通过程序对键盘进行扫描,实现对不同按键的检测。
计算功能:该计算器可以实现基本的四则运算、取反、开方等功能。
对于四则运算,通过栈来实现计算,将运算符压入栈中,然后将操作数从栈中取出进行计算。
LCD显示:该计算器使用16位的LCD显示屏,通过程序控制数据和命令的传输,将计算结果显示在LCD屏幕上。
3. 总结
通过对51单片机简易计算器的设计报告,可以看出该计算器实现了基本的计算功能,通过硬件设计和软件设计相结合,将计算器的功能实现得十分完整。
该计算器的设计初步掌握了51单片机的应用,有助于后续项目的开展。
51单片机数码管显示及矩阵键盘扫描程序
51单片机数码管显示及矩阵键盘扫描程序硬件实验十一八段数码管实验一、实验任务1、在静态数码管上轮流显示数字0-9。
2、在两个4位数码管上动态显示数字0-9二、流程图及程序静态显示:流程图:程序代码:#include#define uchar unsigned chucharcodevalue[10]={0xC0,0xF9,0xA4,0xB0,0X99,0x92,0x82,0xF8,0 x80,0x90};//0 -9数码管显示段码void delay(char x) //延时子程序{uchar i;for(i=0;i<200;i++);}main() //主函数{int i;while(1){for(i=0;i<10;i++) //显示0-9{P0=codevalue[i];delay(500); //延时1秒}}}动态显示:#include#includetab1[]={0x3f,0x06,0x5b,0x4f,0x66,0x6D,0x7D,0x07,0x7f,0x6f}; //数码管显示数字字段unsigned char tab2[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//片选字段unsigned char i,k,j,x;void delay(x); //声明延时子函数void main() //主函数{while(1){for(i=0;i<8;i++) //显示0-7{ P1=tab1[i];P0=tab2[i];delay(5); //延时}P1=tab1[8]; P0=tab2[0]; delay(5); //显示8-9P1=tab1[9]; P0=tab2[1]; delay(5);}}void delay(x) //延时函数定义{do{for(j=0;j<250;j++)for(k=0;k<250;k++);}}硬件实验十二矩阵键盘扫描显示一、实验任务1、把矩阵键盘上的按键输入的键码在静态数码管上显示出来。
矩阵键盘的键值计算及编程
2 读取I/O口值的练习
.j
用程序控制单片机P2口工作,让高四位全高电平,低四位全低电平。 即:P2=0xf0; 具体实现见操作,结果如图。
P1口高四位是指:P1.7 P1.6 P1.5 P1.4
一般都是自高到低读出一个端口各脚电平 ,得到8位二进制数,再将8位二进制转换成2位十六进数。
P3口值= P3.7 P3.6 P3.5 P3.4P3.3 P3.2 P3.1 P3.0 =1111 1010=0xfa
2 读取I/O口值的练习
.j
当 程序使P2=0x0f; 外接一个两脚开关到P2口只能让P2产生如下四个新的值: 0x0e, 0x0d,0x0b,0x07 0x0d 0x0b
找出行线值 置行线所处端口位置高电平
找出列线值 置列线所处端口位置高电平
行线值+列线值=键值
计算键值一般方法
3 键盘的键值
.j
先找出行线值,再找出列线值,最后绘出矩阵键盘的键值。
总结
4×4矩阵键盘的键值 共有16个,计算键值时总是:
4 键盘扫描编程__线反转法
.j
/************键盘扫子描函数*******************/ char keyscan(void) //键盘扫描函数,键盘使用P2口 { char value_h,value_l; //value_h行值变量,value_l列值变量 P2=0xf0; //将行线所处位置置高电平 if((P2&0xf0)!=0xf0) //判断是否有键按下 { delay(10); //延时防抖 if((P2&0xf0)!=0xf0) //仍有键按下 { value_h=P2&0xf0; //读出P2口值给变量value_h P2=0x0f; //将列线所处位置置高电平 value_l=P2&0x0f; //读出P2口值给变量value_l return(value_l+value_h); //找到的键值返回给调用函数 } } }
51单片机实验指导书
.51系列单片机原理与应用实验华南师范大学物理与工程工程学院微机教研室20010年9月目录实验须知 (2)实验一数字量输入输出实验 (4)实验二交通灯控制实验 (6)实验三定时与中断实验 (8)实验四串行通信实验 (11)实验五串行A/D转换实验 (13)实验六现实人体视觉暂留特性测试实验 (14)实验七实时时钟制作实验 (17)实验八简易电子琴制作实验 (18)实验九 EEPROM应用—数字密码锁 (20)实验十综合实验:教学板自检程序设计 (25)实验十一数据采集—火灾报警装置的软硬件设计 (26)附录一实验教学板 (27)附录二实验用软件使用说明 (28)实验须知一、预习要求1.实验前认真阅读实验指导书的相关内容,明确实验目的和实验任务。
2.实验前应做好预习报告,在报告中,要求画出所设计的实验电路原理图、程序流程图,编写好程序,并对程序加以注释,还要拟订好实验步骤。
二、实验要求1.按实验中心安排的时间到指定实验室上实验课,不要迟到、缺席。
有特殊原因不能在原安排时间来实验时,须提前一天通知实验中心负责教师。
2.认真完成每次实验的各项任务,实验结果要请指导教师检查。
教师对实验内容提问,并对完成者进行记录。
3.爱护设备,保持清洁,不得在实验室内大声喧哗,不要将食物带入实验室,不擅自更换设备。
4.在实验箱(板)通电状态下,不要用手随意触摸电路板上除按键和开关以外的芯片等其它元器件。
,严禁带电操作,即所有接线、改线和拆线操作均应在不带电的状态下进行。
5.实验中若发生异常情况应立即切断电源,并向指导教师报告,检查原因,避免再次发生类似情况。
6.实验完毕,请整理好实验设备后再离开实验室。
三、实验报告要求实验报告必须使用实验报告专用纸,书写要工整、清楚,并在下一次实验时交给指导教师。
实验报告应包括以下内容:1.实验名称、实验人姓名、学号、班级、同组人姓名。
2.实验目的、任务(内容)。
3.各任务程序流程图、自编程序清单,对程序须给出适量注释(例如:变量和某些寄存器的作用,关键程序段的功能等)。
51单片机设计电子锁密码锁含代码
电子锁设计报告一,实验目的1. 学习8051定时器时间计时处理,键盘扫描及LED数码管显示的设计方法。
2. 设计任务及要求利用实验平台上8个LED数码管,设计带有报警功能的可掉电保存的电子密码锁。
3.通过本次实验,加强对所学知识的理解,增强编程能力及实践能力。
二,实验要求A.基本要求:1:用4×4矩阵键盘组成0-9数字键及确认键和删除键。
2:可以自行设定或删除8位密码,能够掉电保存。
3:用5位数码管组成显示电路提示信息,当输入密码时,只显示“8.”,当密码位数输入完毕按下确认键时,对输入的密码与设定的密码进行比较,若密码正确,则门开,此处用绿色led发光二极管亮一秒钟做为提示,若密码不正确,禁止按键输入3秒,同时用红色led发光二极管亮三秒钟做为提示;若在3秒之内仍有按键按下,则禁止按键输入3秒被重新禁止。
4:自由发挥其他功能.5:要求有单片机硬件系统框图,电路原理图,软件流程图B.拓展部分:无三,实验基本原理单片机密码锁是集计算机技术、电子技术、数字密码技术为一体的机电一体化高科技产品,具有安全性高,使用方便等优点。
本系统考虑到单片机密码锁成本及体积因素,在设计单片机密码锁部分时,以AT89S52单片机为核心,24C04、LED等构成外围电路。
本系统单片机密码锁硬件部分结构简单、成本低,软件部分使用电子加密提高锁的安全性,具有比较好的市场前景。
同时,由于本电子密码锁可以实现掉电保存,而且可以自行设计或者删除8位密码,所以具有较高的实用价值。
本密码锁采用5位数码管组成显示电路提示信息,当输入密码时,只显示“8.”,当密码位数输入完毕按下确认键时,对输入的密码与设定的密码进行比较,若密码正确,则门开,此处用绿色led 发光二极管亮一秒钟做为提示,若密码不正确,禁止按键输入3秒,同时用红色led 发光二极管亮三秒钟做为提示;若在3秒之内仍有按键按下,则禁止按键输入3秒被重新禁止。
此项功能方便用户使用。
矩阵式键盘实验报告
矩阵式键盘实验报告矩阵键盘设计实验报告南京林业大学实验报告基于AT89C51单片机4x4矩阵键盘接口电路设计课程院系班级学号姓名指导老师机电一体化设计基础机械电子工程学院杨雨图2013年9月26日一、实验目的1、掌握键盘接口的基本特点,了解独立键盘和矩阵键盘的应用方法。
2、掌握键盘接口的硬件设计方法,软件程序设计和贴士排错能力。
3、掌握利用Keil51软件对程序进行编译。
4、用Proteus软件绘制“矩阵键盘扫描”电路,并用测试程序进行仿真。
5、会根据实际功能,正确选择单片机功能接线,编制正确程序。
对实验结果能做出分析和解释,能写出符合规格的实验报告。
二、实验要求通过实训,学生应达到以下几方面的要求:素质要求1.以积极认真的态度对待本次实训,遵章守纪、团结协作。
2.善于发现数字电路中存在的问题、分析问题、解决问题,努力培养独立工作能力。
能力要求1.模拟电路的理论知识2.脉冲与数字电路的理念知识3.通过模拟、数字电路实验有一定的动手能力4.能熟练的编写8951单片机汇编程序5.能够熟练的运用仿真软件进行仿真三、实验工具1、软件:Proteus软件、keil51。
2、硬件:PC机,串口线,并口线,单片机开发板四、实验内容1、掌握并理解“矩阵键盘扫描”的原理及制作,了解各元器件的参数及格元器件的作用。
2、用keil51测试软件编写AT89C51单片机汇编程序3、用Proteus软件绘制“矩阵键盘扫描”电路原理图。
4、运用仿真软件对电路进行仿真。
五.实验基本步骤1、用Proteus绘制“矩阵键盘扫描”电路原理图。
2、编写程序使数码管显示当前闭合按键的键值。
3、利用Proteus软件的仿真功能对其进行仿真测试,观察数码管的显示状态和按键开关的对应关系。
4、用keil51软件编写程序,并生成HEX文件。
5、根据绘制“矩阵键盘扫描”电路原理图,搭建相关硬件电路。
6、用通用编程器或ISP下载HEX程序到MCU。
单片机经典长短按程序
新型的按键扫描程序不过我在网上游逛了很久,也看过不少源程序了,没有发现这种按键处理办法的踪迹,所以,我将他共享出来,和广大同僚们共勉。
我非常坚信这种按键处理办法的便捷和高效,你可以移植到任何一种嵌入式处理器上面,因为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; // 1Trg = ReadData & (ReadData ^ Cont); // 2Cont = ReadData; // 3}完了。
有没有一种不可思议的感觉?当然,没有想懂之前会那样,想懂之后就会惊叹于这算法的精妙!!下面是程序解释:Trg(triger)代表的是触发,Cont(continue)代表的是连续按下。
1:读PORTB的端口数据,取反,然后送到ReadData 临时变量里面保存起来。
2:算法1,用来计算触发变量的。
一个位与操作,一个异或操作,我想学过C 语言都应该懂吧?Trg为全局变量,其它程序可以直接引用。
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端口连接到矩阵键盘的列和行,通过扫描不同的列和检测行的状态来判断按键是否被按下。
单片机 矩阵键盘实验 实验报告
实验五矩阵键盘实验一、实验内容1、编写程序,做到在键盘上每按一个数字键(0-F)用发光二极管将该代码显示出来。
按其它键退出。
2、加法设计计算器,实验板上有12个按键,编写程序,实现一位整数加法运算功能。
可定义“A”键为“+”键,“B”键为“=”键。
二、实验目的1、学习独立式按键的查询识别方法。
2、非编码矩阵键盘的行反转法识别方法。
三、实验说明1、MCS51系列单片机的P0~P3口作为输入端口使用时必须先向端口写入“1”。
2、用查询方式检测按键时,要加入延时(通常采用软件延时10~20mS)以消除抖动。
3、识别键的闭合,通常采用行扫描法和行反转法。
行扫描法是使键盘上某一行线为低电平,而其余行接高电平,然后读取列值,如读列值中某位为低电平,表明有键按下,否则扫描下一行,直到扫完所有行。
行反转法识别闭合键时,要将行线接一并行口,先让它工作在输出方式,将列线也接到一个并行口,先让它工作于输入方式,程序使CPU通过输出端口在各行线上全部送低电平,然后读入列线值,如此时有某键被按下,则必定会使某一列线值为0。
然后,程序对两个并行端口进行方式设置,使行线工作于输入方式,列线工作于输出方式,并将刚才读得的列线值从列线所接的并行端口输出,再读取行线上输入值,那么,在闭合键所在行线上的值必定为0。
这样,当一个键被接下时,必定可以读得一对唯一的行线值和列线值。
由于51单片机的并口能够动态地改变输入输出方式,因此,矩阵键盘采用行反转法识别最为简便。
行反转法识别按键的过程是:首先,将4个行线作为输出,将其全部置0,4个列线作为输入,将其全部置1,也就是向P1口写入0xF0;假如此时没有人按键,从P1口读出的值应仍为0xF0;假如此时1、4、7、0四个键中有一个键被按下,则P1.6被拉低,从P1口读出的值为0xB0;为了确定是这四个键中哪一个被按下,可将刚才从P1口读出的数的低四位置1后再写入P1口,即将0xBF写入P1口,使P1.6为低,其余均为高,若此时被按下的键是“4”,则P1.1被拉低,从P1口读出的值为0xBE;这样,当只有一个键被按下时,每一个键只有唯一的反转码,事先为12个键的反转码建一个表,通过查表就可知道是哪个键被按下了。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
{
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
------------------------------------------------*/
void Display(unsigned char FirstBit,unsigned char Num)
{
static unsigned char i=0;
DataPort=0; //清空数据,防止有交替重影
return Val;
}
KeyPort=0xf7; //检测第四行
if(KeyPort!=0xf7)
{
Val=KeyPort&0xf0;
Val+=0x07;
while(KeyPort!=0xf7);
DelayMs(10); //去抖
while(KeyPort!=0xf7);
return Val;
}
}
if(KeyPort!=0xf0)//表示有按键按下
{
DelayMs(10); //去抖
if(KeyPort!=0xf0)
{ //表示有按键按下
KeyPort=0xfe; //检测第一行
if(KeyPort!=0xfe)
{
Val=KeyPort&0xf0;
Val+=0x0e;
while(KeyPort!=0xfe);
}
return 0xff;
}
/*------------------------------------------------
按键值处理函数,返回扫键值
------------------------------------------------*/
unsigned char KeyPro(void)
for(j=0;j<=i;j++)
TempData[7-i+j]=temp[j];
}
i++;
if(i==9)//多出一个按键输入为了清屏原本应该为8
{
i=0;
for(j=0;j<8;j++)ቤተ መጻሕፍቲ ባይዱ/清屏
TempData[j]=0;
}
}
//Display(0,8); //显示全部8位
//主循环中添加其他需要一直工作的程序
}
}
LATCH1=1; //段锁存
LATCH1=0;
DataPort=dofly_WeiMa[i+FirstBit]; //取位码
LATCH2=1; //位锁存
LATCH2=0;
DataPort=TempData[i]; //取显示数据,段码
LATCH1=1; //段锁存
LATCH1=0;
i++;
if(i==Num)
unsigned char是定义无符号字符变量,其值的范围是
0~255这里使用晶振12M,精确延时请使用汇编
------------------------------------------------*/
void DelayMs(unsigned char t)
{
while(t--)
{
//大致延时1mS
//TH0=0x00;//给定初值
//TL0=0x00;
EA=1; //总中断打开
ET0=1; //定时器中断打开
TR0=1; //定时器开关打开
}
/*------------------------------------------------
定时器中断子程序
------------------------------------------------*/
DelayUs2x(245);
DelayUs2x(245);
}
}
/*------------------------------------------------
显示函数,用于动态扫描数码管
输入参数FirstBit表示需要显示的第一位,如赋值2表示从第三个数码管开始显示
如输入0表示从第一个显示。
Num表示需要显示的位数,如需要显示99两位数值则该值输入2
i=0;
}
/*------------------------------------------------
定时器初始化子程序
------------------------------------------------*/
void Init_Timer0(void)
{
TMOD |= 0x01;//使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
while(KeyPort!=0xfd);
return Val;
}
KeyPort=0xfb; //检测第三行
if(KeyPort!=0xfb)
{
Val=KeyPort&0xf0;
Val+=0x0b;
while(KeyPort!=0xfb);
DelayMs(10); //去抖
while(KeyPort!=0xfb);
{
switch(KeyScan())
{
case 0x7e:return 0;break;//0按下相应的键显示相对应的码值
case 0x7d:return 1;break;//1
case 0x7b:return 2;break;//2
case 0x77:return 3;break;//3
case 0xbe:return 4;break;//4
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];
unsigned char TempData[8]; //存储显示值的全局变量
void DelayUs2x(unsigned char t);//us级延时函数声明
void DelayMs(unsigned char t); //ms级延时
void Display(unsigned char FirstBit,unsigned char Num);//数码管显示函数
DelayMs(10); //去抖
while(KeyPort!=0xfe);
return Val;
}
KeyPort=0xfd; //检测第二行
if(KeyPort!=0xfd)
{
Val=KeyPort&0xf0;
Val+=0x0d;
while(KeyPort!=0xfd);
DelayMs(10); //去抖
case 0xbd:return 5;break;//5
case 0xbb:return 6;break;//6
case 0xb7:return 7;break;//7
case 0xde:return 8;break;//8
case 0xdd:return 9;break;//9
case 0xdb:return 10;break;//a
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{
while(--t);
}
/*------------------------------------------------
mS延时函数,含有输入参数unsigned char t,无返回值
unsigned char KeyScan(void);//键盘扫描
unsigned char KeyPro(void);