单片机89C52行列式键盘扫描程序(汇编)
STC89c52单片机 计算器C语言程序
STC89c52单片机计算器C语言程序STC89C52|/***************89C51单片机【计算器】C语言程序******************//**************** P2位选P0段选时钟12MHZ *********************/#include<reg52.h> /*包含的头文件*/#define uchar unsigned char /* 宏定义*/#define uint unsigned intuchar Led[17] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f,0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71, 0x00}; /* 数码管段选*/long float Number[]={0,0,0,0}; /* 数码管显示位控制寄存器*/uchar A[]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};long int D[] = {0,0,0,0,0,0,0,0}; //数码管显示内容寄存器uchar code C[] = {0x0, 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F}; /* 数码管位选*//* 列扫描控制LED 1位2位3位4位5位6位7位8位*/uchar k=16; /* 按键对外控制*/uchar b; /* 按键【+】【-】【*】【/】对外的控制*/long float Out_put; /* 定义变量【Out_put】作为结果*/uchar e=0; /* 数字的位存储递进的控制*/uchar g=0; /* 运算方式的控制变量*/uchar L=0; /* 运算方式的控制变量*/uchar g1=0; /* 运算方式的控制变量*/uchar g2=0; /* 运算方式的控制变量*/uchar g3=0; /* 运算方式的控制变量*/uchar g4=0; /* 运算方式的控制变量*/char j=-1; /* 与Number[]数组连用*/uchar m=0; /* 按键【=】的控制变量*/uchar n=0; /* 按键【.】的控制变量*/uchar x=0; /* 小数点个数的记录变量*/uchar xo=0; /* 控制开始计数小数点的变量*/long int result;void Delay(uint o) /* 延时函数delay() 的定义*/{uint i,j;for(i = 0; i < o; i++){for(j = 0; j < 121; j++) {;}}}void show(long float Out_put){ uchar r;uchar k;long int q,p;uchar s=0;uchar i;long int temp;temp=Out_put ;if( (Out_put-temp)!=0) {result=Out_put*10000; r=4;}else { result=Out_put; r=0; }p=result;if(m==1){if(result<0){ result=-result; p=result; q=result; for(i=1;i<=8;i++) { q=q/10; if(q==0) {k=i;i=9; } } P0=0x40; P2=C[8-k];Delay(1); } //负号的显示P0=0x80; P2=C[r]; Delay(1); P0=0x00;result=p;P0=Led[result%10]; P2=C[8]; result=result/10; Delay(1);if( (result%10==0)&&(result%100==0)&&(result%1000==0)&&(result%10000==0)&&(r esult%100000==0)&&(result%1000000==0) ) {P0=0x00;}else {P0=Led[result%10]; P2=C[7]; result=result/10; Delay(1);}if( (result%10==0)&&(result%100==0)&&(result%1000==0)&&(result%10000==0)&&(result%100000==0) ) {P0=0x00;}else {P0=Led[result%10]; P2=C[6]; result=result/10; Delay(1);}if( (result%10==0)&&(result%100==0)&&(result%1000==0)&&(result%10000==0) ) {P0=0x00;}else {P0=Led[result%10]; P2=C[5]; result=result/10; Delay(1);}if( (result%10==0)&&(result%100==0)&&(result%1000==0) ) {P0=0x00;}else {P0=Led[result%10]; P2=C[4]; result=result/10; Delay(1);}if( (result%10==0)&&(result%100==0) ) {P0=0x00;}else {P0=Led[result%10]; P2=C[3]; result=result/10; Delay(1);}if( (result%10==0) ) {P0=0x00;}else {P0=Led[result%10]; P2=C[2]; result=result/10; Delay(1);}if(result==0) {P0=0x00;}else {P0=Led[result%10]; P2=C[1]; result=result/10; Delay(1);}}}void In_put() // 输入函数输入小数加小数点{uchar i;if(k>=0&&k<=9)switch(e){case 8: D[7]=D[6];A[7]=A[6]; //用来存放数值case 7: D[6]=D[5];A[6]=A[5];case 6: D[5]=D[4];A[5]=A[4];case 5: D[4]=D[3];A[4]=A[3];case 4: D[3]=D[2];A[3]=A[2];case 3: D[2]=D[1];A[2]=A[1];case 2: D[1]=D[0];A[1]=A[0];case 1: if(n==0) { D[0]=k; A[0]=Led[k]; if(xo==1) x++; }if(n==1) { A[0]=Led[k]|0x80; xo=1; n=0;}}if(k>=11&&k<=15&&b==1){ switch(k){case 11: g1++;g++;if(g2==1) L=1; if(g3==1) L=2; if(g4==1) L=3;break; // +case 12: g2++;g++;if(g1==1) L=4; if(g3==1) L=5; if(g4==1) L=6;break; // -case 13: g3++;g++;if(g1==1) L=7; if(g2==1) L=8; if(g4==1) L=9;break; // *case 14: g4++;g++;if(g1==1) L=10;if(g2==1) L=11;if(g3==1) L=12;break; // /}j++;Number[j]=10000000*D[7]+1000000*D[6]+100000*D[5]+10000*D[4]+1000*D[3]+100*D [2]+10*D[1]+D[0];for(i=1;i<=x;i++) {Number[j]=(float)Number[j]/10;}x=0;for(i=0;i<=7;i++) // 数据存储器清零D[i]=0;for(i=0;i<=8;i++) // 数据显示清零{A[i]=0x00;}b=0;e=0;xo=0;}}void Key_scan() // 键盘扫描函数Key_scan(){unsigned char X,Y,Z;P3 = 0xff;P3 = 0x0f; //先对P2置数行扫描if(P3!=0x0f) //判断是否有键按下{Delay(20); //延时10ms,软件去干扰if(P3!=0x0f) //确认按键按下;{X=P3; //保存行扫描时有键按下时状态P3=0xf0; //列扫描Y=P3; //保存列扫描时有键按下时状态Z=X|Y; //取出键值while(P3!=0xf0); // 按键防止抖动switch ( Z ) //判断键值(那一个键按下){case 0xe7: k=0; e++; In_put(); break; //数字【0】case 0xd7: k=1; e++; In_put(); break; //数字【1】case 0xdb: k=2; e++; In_put(); break; //数字【2】case 0xdd: k=3; e++; In_put(); break; //数字【3】case 0xb7: k=4; e++; In_put(); break; //数字【4】case 0xbb: k=5; e++; In_put(); break; //数字【5】case 0xbd: k=6; e++; In_put(); break; //数字【6】case 0x77: k=7; e++; In_put(); break; //数字【7】case 0x7b: k=8; e++; In_put(); break; //数字【8】case 0x7d: k=9; e++; In_put(); break; //数字【9】case 0xeb: n=1; In_put(); break; //小数点【 .】case 0x7e: k=11;b=1; In_put(); break; //字符【B +】case 0xbe: k=12;b=1; In_put(); break; //字符【C -】case 0xde: k=13;b=1; In_put(); break; //字符【D *】case 0xee: k=14;b=1; In_put(); break; //字符【E /】case 0xed: k=15;m=1;b=1;In_put();break; //字符【F =】}}}}void Yun_suan(){if(g1==1&&g==1) Out_put=Number[0]+Number[1];if(g2==1&&g==1) Out_put=Number[0]-Number[1];if(g3==1&&g==1) Out_put=Number[0]*Number[1];if(g4==1&&g==1) Out_put=Number[0]/Number[1];if(g1==2&&g==2) Out_put=Number[0]+Number[1]+Number[2]; if(g2==2&&g==2) Out_put=Number[0]-Number[1]-Number[2]; if(g3==2&&g==2) Out_put=Number[0]*Number[1]*Number[2]; if(g4==2&&g==2) Out_put=Number[0]/Number[1]/Number[2];if(L==1) Out_put=Number[0]-Number[1]+Number[2];if(L==2) Out_put=Number[0]*Number[1]+Number[2];if(L==3) Out_put=Number[0]/Number[1]+Number[2];if(L==4) Out_put=Number[0]+Number[1]-Number[2];if(L==5) Out_put=Number[0]*Number[1]-Number[2];if(L==6) Out_put=Number[0]/Number[1]-Number[2]; if(L==7) Out_put=Number[0]+Number[1]*Number[2]; if(L==8) Out_put=Number[0]-Number[1]*Number[2]; if(L==9) Out_put=Number[0]/Number[1]*Number[2]; if(L==10) Out_put=Number[0]+Number[1]/Number[2]; if(L==11) Out_put=Number[0]-Number[1]/Number[2]; if(L==12) Out_put=Number[0]*Number[1]/Number[2]; }void Xian_shi(){if(m!=1){Key_scan();/* 显示函数与A[i]有关*/P0=A[0]; P2=C[8];Delay(1);P0=A[1]; P2=C[7];Delay(1);P0=A[2]; P2=C[6];Delay(1);P0=A[3]; P2=C[5];Delay(1);P0=A[4]; P2=C[4];Delay(1);P0=A[5]; P2=C[3];Delay(1);P0=A[6]; P2=C[2];Delay(1);P0=A[7]; P2=C[1];Delay(1);}}void main(){while(1){Xian_shi();Yun_suan();show( Out_put );}}//。
单片机矩阵键盘行列扫描程序学习资料
{
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();//调用键盘扫描,
//行列扫描程序,可以自己定义端口和扫描方式,这里做简单介绍
单片机实验--键盘扫描
实验4 键盘实验一、实验目的:1.掌握8255A编程原理。
2.了解键盘电路的工作原理。
3.掌握键盘接口电路的编程方法。
二、实验设备:CPU挂箱、8031CPU模块三、实验原理:1.识别键的闭合,通常采用行扫描法和行反转法。
行扫描法是使键盘上某一行线为低电平,而其余行接高电平,然后读取列值,如所读列值中某位为低电平,表明有键按下,否则扫描下一行,直到扫完所有行。
本实验例程采用的是行反转法。
行反转法识别键闭合时,要将行线接一并行口,先让它工作于输出方式,将列线也接到一个并行口,先让它工作于输入方式,程序使CPU通过输出端口往各行线上全部送低电平,然后读入列线值,如此时有某键被按下,则必定会使某一列线值为0。
然后,程序对两个并行端口进行方式设置,使行线工作于输入方式,列线工作于输出方式,并将刚才读得的列线值从列线所接的并行端口输出,再读取行线上的输入值,那么,在闭合键所在的行线上的值必定为0。
这样,当一个键被按下时,必定可以读得一对唯一的行线值和列线值。
2.程序设计时,要学会灵活地对8255A的各端口进行方式设置。
3.程序设计时,可将各键对应的键值(行线值、列线值)放在一个表中,将要显示的0~F字符放在另一个表中,通过查表来确定按下的是哪一个键并正确显示出来。
实验题目利用实验箱上的8255A可编程并行接口芯片和矩阵键盘,编写程序,做到在键盘上每按一个数字键(0~F),用发光二极管将该代码显示出来。
四、实验步骤:将键盘RL10~RL17接8255A的PB0~PB7;KA10~KA12接8255A的PA0~PA2;PC0~PC7接发光二极管的L1~L8;8255A芯片的片选信号8255CS接CS0。
五、实验电路:六、程序框图7.程序清单八、附:8251/8255扩展模块该模块由8251可编程串行口电路和8255可编程并行口电路两部分组成,其电源、数据总线、地址总线和片选信号均由接口挂箱上的接口插座提供。
一、8251可编程串行口电路(1)8251可编程串行接口芯片引脚及功能8251A是通用同步/异步收发器USART,适合作异步起止式数据格式和同步面向字符数据格式的接口,其功能很强。
矩阵键盘过程及扫描程序
键盘是单片机常用输入设备,在按键数量较多时,为了节省I/O口等单片机资源,一般采取扫描的方式来识别到底是哪一个键被按下。
即通过确定被按下的键处在哪一行哪一列来确定该键的位置,获取键值以启动相应的功能程序。
矩阵键盘的四列依次接到单片机的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中有一个为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左移一位}}}} //结束。
单片机AT89C52
单⽚机AT89C522总体⽅案设计2.1⽅案⽐较⽅案⼀设计的太阳能热⽔器控制系统以89C52单⽚机为检测控制中⼼单元,采⽤DSl2887实时时钟,不仅实现了时间、温度和⽔位三种参数实时显⽰功能,⽽且具有时间设定、温度设定与控制功能。
控制系统可以根据天⽓情况利⽤辅助加热装置(电加热器)使蓄⽔箱内的⽔温达到预先设定的温度,从⽽达到24⼩时供应热⽔的⽬的。
实际应⽤结果表明,该控制器和以往显⽰仪相⽐具有性价⽐⾼、温度控制与显⽰精度⾼、使⽤⽅便和性能稳定等优点。
AT89C52图2-1 系统硬件结构图⽅案⼆采⽤系统的温度采集选⽤PTl000铂电阻温度传感器,采集到的电压信号经集成运放LM324放⼤到2.O⼀5.0伏之间,送⼊串⾏加转换器11LCl543N,转换结果由单⽚机处理,其电路原理如图3所⽰.设计时将加转换器的参考电压设置为vREF+=5.0V,VREF=1.5V.LM324按照同相⽐例放⼤电路连接,则Vo=vi*(Rt/R+1)=0.5*(Rt/300+1).Rt 值的变化表⽰了PtlooO温度传感器温度的变化,每个温度值对应⼀定的转换结果。
可以在程序中建⽴⼀个查找表,表中每个元素的地址即为转换结果,元素值即为所对应的温度值。
图2-2 系统硬件结构图12.2⽅案选择⽅案⼀硬件电路简单,程序设计复杂⼀些,但是我已经使⽤开发⼯具KEIL⽤汇编语⾔对系统进⾏了程序设计,⽤仿真软件PROTEUS对系统进⾏了仿真,达到了预期的结果。
由此可见,该⽅案完成具有可⾏性,体现了技术的先进性,经济上也没有问题。
根据设计的要求,以及设计的便捷性,综上所述,本课题采⽤⽅案⼀对系统进⾏设计。
3.单元模块设计3.1各单元模块功能介绍及电路设计3.1.1单⽚机系统设计单⽚机系统由AT89C52和⼀定功能的外围电路组成,包括为单⽚机提供复位电压的复位电路,提供系统频率的晶振。
这部分电路主要负责程序的存储和运⾏。
上图中MCS-51内部时钟⽅式电路外接晶体以及电容C5和C6构成并联谐振电路,接在放⼤器的反馈回路中。
单片机键盘扫描程序与原理图
keydown(); //调用按键判断检测程序 P2 = LED7Code[dis_buf%16]&0x7f; P3= LED7Code[dis_buf1%16]&0x7f; //LED7 0x7f为小数点 和共阳此处也是不一样; %16表示输出16进制 d <reg51.h> #define uchar unsigned char //宏的定义变量类型 uchar 代替 unsigned char #define uint unsigned int //宏的定义变量类型 uint 代替 unsigned int uchar dis_buf,dis_buf1; //显示缓存 uchar temp; uchar l,h; //键顺序吗 void delay0(uchar x); //x*0.14MS
// 此表为 LED 的字模 0 1 2 3 4 5 6 7 8 9 a b c d e f unsigned char code LED7Code[] = {~0x3F,~0x06,~0x5B,~0x4F,~0x66,~0x6D,~0x7D,~0x07,~0x7F,~0x6F,~0x77,~0x7C,~0 /************************************************************* * * * 延时子程序 * * * *************************************************************/ void delay(uchar x) { uchar j; while((x--)!=0) //CPU执行x*12次,x=10 { for(j=0;j<125;j++) {;} } } /************************************************************* * * * 键扫描子程序 (4*3 的矩阵) P1.4 P1.5 P1.6 P1.7为行 * * P1.1 P1.2 P1.3为列 * * * *************************************************************/
单片机外围电路键盘扫描设计说明书
University of South China单片机课程设计总结报告设计题目:单片机最小系统及外围电路设计班级:学院: 机械工程学号:姓名:指导教师:袁锋伟蒋彦王玉林摘要【摘要】本次课程设计主要是关于单片机简易开发板的设计。
实现8位流水灯控制,按键扫描双位数码管显示。
本次设计主要采用89C52单片机芯片制作而成,包括流水灯电路,按键扫描电路,数码管显示电路,ISP及USB供电部分,单片机P1口控制数码管,P0口控制八位流水灯,P2控制扫描键盘,通过读写口进行ISP下载。
【关键词】流水灯、按键扫描、数码管显示、ISP下载目录1. 课程设计的目标与设计任务 ..........................1.1设计的任务...............................................2、硬件电路设计方案及功能分析...................2.1 原理图.................................................2.2 单元电路设计及分析.....................................2.2.189C52芯片简介....................................2.2.2 下载线电路........................................2.2.3 最小外围电路......................................3、程序的设计...................................3.1开发软件及编程语言简介...................................3.2软件程序的编写及调试.....................................4、电路板的制作.................................5、电路板的焊接与调试 ..........................6、课程设计总结.................................7、参考文献..................................... 附录1主要电子元件清单..........................1. 课程设计的设计任务1.1 设计任务图1 系统设计要求方框图根据题目要求,系统可以划分为最小外围电路,指示灯及流水电路,按键扫描,数码管显示电路,及ISP下载模块。
stc89c52单片机下的矩阵键盘程序
stc89c52单片机下的矩阵键盘程序
stc89c52单片机就是51 52 系列单片机,就和AT89C52 差不多,没有什么大的区别,可以直接替换,只是内部多了一个EEPROM 空间,可以串口下载程序,指令执行速度快一倍。
STC89C52是一种带8K字节闪烁可编程可檫除只读存储器(FPEROM-Flash Programable and Erasable Read Only Memory )的低电压,高性能COMOS8的微处理器,俗称单片机。
该器件采用ATMEL搞密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容。
下面是一个stc89c52单片机下的矩阵键盘程序,P0口接键盘,显示在P2口。
#include
#define uchar unsigned char
#define uint unsigned int
sbit key1=P3 ;
sbit key2=P3 ;
uchar code tab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00}; //定义八个灯的工作状态。
uchar code wep[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07};
void yanshi(uint t)
{
while(--t);
}
void main()
{
uchar han,lei,key;
while(1)
{。
基于STC89C52单片机的电子密码锁(完整版)-附-仿真图-原理图
目录1绪论 (1)1.1本设计的研究背景与研究目的 (1)1.2国内外研究现状 (2)2电子密码锁的总体设计方案 (3)2.1方案论证 (3)2.1.1方案一采用单片机控制方案 (3)2.1.2方案二采用数字电路控制方案 (4)2.1.3方案三采用EDA控制方案 (5)2.2方案比较以及可行性 (5)3电子密码锁硬件电路的设计 (6)3.1中央控制模块的设计 (6)3.1.1主控芯片STC89C52单片机的简介 (6)3.1.2时钟电路的设计 (7)3.1.3复位电路的设计 (8)3.2键盘输入模块的设计 (9)3.2.1矩阵键盘工作原理 (9)3.2.2单片机键盘扫描法 (10)3.3LCD显示密码模块的设计 (10)3.3.1LCD1602简介 (11)3.3.2LCD1602液晶显示模块与单片机连接电路 (12)3.4开锁模块的设计 (13)3.5报警模块的设计 (13)3.6硬件电路总体设计 (14)4电子密码锁的软件设计 (15)4.1主程序流程介绍 (15)4.2键盘模块流程图 (16)4.3显示模块流程图 (18)4.4修改密码流程图 (19)4.5开锁和报警模块流程图 (20)5电子密码锁的系统调试及分析 (22)5.1硬件电路调试及结果分析 (22)5.2软件调试及功能分析 (22)5.2.1调试过程 (22)5.2.2仿真结果分析 (24)5.3系统调试 (26)6结论及展望 (28)6.1结论 (28)6.2展望 (28)谢辞 (29)参考文献 (30)附录 (32)附1部分代码 (32)附2总电路图 (40)电子密码锁的设计与制作1绪论1.1本设计的研究背景与研究目的随着人们生活水平的提高和社会科技的进步,锁已发展到了密码锁、磁性锁、电子锁、激光锁、声控锁等等。
在传统钥匙的基础上,加了一组或多组密码,不同声音,不同磁场,不同声波,不同光束光波,不同图像。
(如指纹、眼底视网膜等)来控制锁的开启。
单片机89C52行列式键盘扫描程序(汇编)
实验八键盘扫描显示实验所需软硬件:KeilSTC-ISPMCS-51 89C52实验箱程序清单:基于汇编语言//连线P0接8列(同时也是数码管的位选线)高电平选中某位。
P3低两位接行P1接数码管(段选线)低电平选中某段亮。
ORG 0000HLJMP MAINMAIN:MOV 30H,#00HMOV 31H,#00HMOV 32H,#00HMOV 33H,#00HMOV 34H,#00HMOV 35H,#00HBEGIN:ACALL SCANACALL CHECKACALL DISPSJMP BEGIN//子程序SCAN 全扫描2次扫描去抖SCAN: ;全扫描MOV R0,#00H ;去抖,扫描2次计数标志MOV A,#00HMOV P0,A ;送列扫描码LOOP:MOV A,P3 ;回读行信号ANL A,#03H ;只取低两位INC R0CJNE A,#03H,K1CLR F0 ;无键,置标志位为0K1:NOPNOPCJNE R0,#02H,LOOP;去抖,扫描2次SETB F0 ;有键,置标志位为1RET//子程序CHECK 逐列扫描确定键码CHECK:MOV R1,#0FEH ;开始逐列扫描,从第0列开始MOV R4,#00H ;记录列号MOV R5,#00H ;记录行号MOV A,R1PUSH ACC ;压栈保留第0列扫描码LOOP1:MOV P0,A ;送列扫描码MOV A,P3ANL A,#03HCJNE A,#03H,K2 ;有键转K2确定为哪一行POP ACC ;无键扫描下一列RL AINC R4CJNE R4,#08H,LOOP1 ; 是否扫描进行到最后一列RETK2:DEC SP ;为保证堆栈平衡CJNE A,#02H,K3 ;分支判断,看是否为第一行SJMP OVERK3:INC R5 ;不是第一行,就是第二行,行码加1 OVER:MOV A,R4ADD A,R5 ;行码+列码=键码PUSH ACC ;键码入栈保护NOPNOPLCALL SCAN ;扫描看手是否松开CJNE A,#03H,OVER ;A=03H,表示手未松开,继续扫描POP ACC ;手松开,键码出栈RET//子程序DISP 键码分离送数码管显示DISP:JNB F0,LOOP3 ;无键不分离键码MOV B,#10 ;有键,要进行十位和个位的分离DIV ABMOV 34H,A ;A为十位MOV 35H,B ;B为个位MOV R0,#30H ;送显示缓冲首地址MOV R2,#01H ;送位选信号,从最低位开始亮LOOP3:MOV A,#0FFHMOV P1,A ;段选:送灭码MOV A,R2MOV P0,A ;送位选信号MOV A,@R0 ;送显示缓冲数据MOV DPTR,#TAB ;查表求字形码MOVC A,@A+DPTRMOV P0,A ;送段选ACALL DELAY1MS ;延时以保持稳定INC R0 ;取下一个数MOV A,R2JB ACC.5,EXIT ;判断位选是否送到最高位RL A ;左移选下一个位。
单片机部队式键盘扫描程序
单片机部队式键盘扫描程序单片机部队式键盘扫描程序一、部队扫描法矩阵式键盘的构造与作业原理:在键盘中按键数量较多时,为了削减I/O口的占用,一般将按键摆放成矩阵方法,如图1所示。
在矩阵式键盘中,每条水平线和笔直线在穿插处不直接连通,而是通过一个按键加以联接。
这么,一个端口(如P1口)就能够构成4*4=16个按键,比之直接将端口线用于键盘多出了一倍,并且线数越多,差异越显着,比方再多加一条线就能够构成20键的键盘,而直接用端口线则只能多出一键(9键)。
由此可见,在需求的键数比照多时,选用矩阵法来做键盘是合理的。
矩阵式构造的键盘显着比直接法要杂乱一些,辨认也要杂乱一些,上图中,列线通过电阻接正电源,并将行线所接的单片机的I/O 口作为输出端,而列线所接的I/O口则作为输入。
这么,当按键没有按下时,悉数的输出端都是高电平,代表无键按下。
行线输出是低电平,一旦有键按下,则输入线就会被拉低,这么,通过读入输入线的情况就可得知是不是有键按下了。
详细的辨认及编程方法如下所述。
矩阵式键盘的按键辨认方法断定矩阵式键盘上何键被按下介绍一种行扫描法。
行扫描法行扫描法又称为逐行(或列)扫描查询法,是一种最常用的按键辨认方法,如上图所示键盘,介绍进程如下。
差异键盘中有无键按下将悉数行线Y0-Y3置低电平,然后查看列线的情况。
只需有一列的电平为低,则标明键盘中有键被按下,并且闭合的键坐落低电平线与4根行线相穿插的4个按键傍边。
若悉数列线均为高电平,则键盘中无键按下。
差异闭合键地址的方位在供认有键按下后,即可进入断定详细闭合键的进程。
其方法是:顺次将行线置为低电平,即在置某根行线为低电往常,其它线为高电平。
在断定某根行线方位为低电平后,再逐行查看各列线的电平情况。
若某列为低,则该列线与置为低电平的行线穿插处的按键即是闭合的按键。
下面给出一个详细的比方:8031单片机的P1口用作键盘I/O口,键盘的列线接到P1口的低4位,键盘的行线接到P1口的高4位。
单片机矩阵键盘扫描步骤
2.判断是否有键按下//而不是直接进行逐行扫描可节省无按键按下时键盘扫描所占机时
3.若有键按下,为断按下的是哪个键,进行逐行扫描,获取P1口状态并转化为按键位置,一旦得到按键位置立即停止扫描
4.若没有键按下,则按键位置保持空状态
矩阵扫描程序89c51
源程序:;****************************************************************************** **;* 标题: 伟纳电子ME300B单片机开发系统演示程序 - 矩阵键盘数码管显示键值 * ;* 文件: WL031.asm *;* 日期: 2005-3-20 *;* 版本: 1.0 *;* 作者: gguoqing *;* 邮箱: gguoqing@ *;* 网站: ; *;****************************************************************************** **;* 描述: *;* 矩阵键盘数码管显示键值 *;* *;* 矩阵键盘定义: *;* P1.0-P1.3为列线,P1.4-P1.7为行线 *;* *;* *;****************************************************************************** **;* 【版权】 Copyright(C)伟纳电子 All Rights Reserved *;* 【声明】此程序仅用于学习与参考,引用请注明版权和作者信息! *;****************************************************************************** **RELAY EQU P1.3BEEP EQU P3.7;------------------------------------------------------ORG 0000HJMP MAIN;------------------------------------------------------MAIN: MOV SP,#60HMOV 30H,#00HLOOP1:CALL KEY_INCALL KEY_PLAERJMP LOOP1;-----------------------------------------------------KEY_IN: MOV P1,#0F0H ;置列线为0,行线为1MOV A,P1ANL A,#0F0HMOV B,AMOV P1,#0FH ;置列线为1,行线为0MOV A,P1ANL A,#0FHORL A,B ;高四位与低四位重新组合CJNE A,#0FFH,KEY_IN1 ;0FFH为末按键RETKEY_IN1: MOV B,AMOV DPTR,#KEYTABLEMOV R3,#0FFH ;KEY_IN2: INC R3MOV A,R3MOVC A,@A+DPTRCJNE A,B,KEY_IN3MOV A,R3 ;找到,取顺序码MOV 30H,ACALL BEEP_BLRETKEY_IN3: CJNE A,#0FFH,KEY_IN2 ;末完,继续查RET ;0FFH为结束码;----------------------------------------------;蜂鸣器响一声子程序;----------------------------------------------BEEP_BL:MOV R6,#100BL1: CALL DEX1CPL BEEPDJNZ R6,BL1MOV R5,#25CALL DELAYRETDEX1: MOV R7,#180DEX2: NOPDJNZ R7,DEX2RETDELAY: ;延时R5×10MSMOV R6,#50DELAY1: MOV R7,#100DJNZ R7,$DJNZ R6,DELAY1DJNZ R5,DELAYRET;----------------------------------------------------- KEYTABLE:DB 0EEH,0EDH,0EBH,0E7H,0DEH ;0,1,2,3,4, 顺序码DB 0DDH,0DBH,0D7H,0BEH,0BDH ;5,6,7,8,9,DB 0BBH,0B7H,07EH,07DH,07BH ;A,B,C,D,E,DB 077H,0FFH ;F 0FF为结束码;-----------------------------------------------------;键值显示子程序;使用一个数码管显示;-----------------------------------------------------KEY_PLAER:MOV A,30HMOV DPTR,#TAB ;取段码表地址MOVC A,@A+DPTR ;查显示数据对应段码 MOV P0,A ;段码放入P0口CLR P2.7 ;第一个数码管亮RET;-----------------------------------------------------TAB:DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8HDB 80H,90H,88h,83h,0c6h,0a1h,86h,8eh;-----------------------------------------------------END。
(5)AT89C52操作3X4矩阵键盘
unsigned char code TABLE[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0xFF}; //数字显示编码表:0 1 2 3 4 5 6 7 8 9 A b C d E F 空 //当 P4 输出相应的数值时,数码管就会按照上面的数字进行显示。例如:P4=0xB0,数码管就显示"3" //以上编码可以使用附赠目录下的 数码管段位计算小程序计算。方便又快捷。
{
bai=input/100;
//百位值
input=input%100;
shi=input/10;
//十位值
ge=input%10;
//个位值
p[0]=16;
//千位 空,不显示
p[1]=bai;
//百位
p[2]=shi;
//十位
p[3]=ge;
//个位
}
else if((input>=1000)&&(input<10000)) //如果输入值为 1000-9999
void update4094() { unsigned char i,j,tt; STR4094=0; for (j=HOWMANY4094;j>0;j--)
9
{ tt=*(&P4+j-1); for(i=0;i<8;i++) {
D4094=(tt&0x80)>0;//数据脚 CLK4094=0; CLK4094=1; tt<<=1; } } STR4094=1; }
在AT89S52 单片机上连接矩阵键盘-51单片机与4x4键盘
unsigned char Key_Scan(void)//键盘扫描函数 如果有键按下返回键 ASC 值 若无返回 0 {
P1=0XF0; if(P1!=0XF0)//先确定是否有键按下 {
Delay(5);//稍微延时 避开按键前期抖动 if(P1!=0xf0)//再次检测是否按下
{ //--------------1-----------------------------------P1=0XFE;//第一次把 P1^7 拉低 switch (P1)//测 P1^0~~~P1^3 有没有低的 { case 0xee: while(P1!=0xfe);return '0';//P1^3 低 while();是在等待松手
//-------------3-------------------------------------P1=0XFB;//第三次把 P1^5 拉低 switch (P1)//测 P1^0~~~P1^3 有没有低的 {
case 0xeb: return '8';//P1^3 低 返回‘8’ case 0xdb: return '9';//P1^2 低 返回‘9’ case 0xbb: return 'A';//P1^1 低 返回‘A’ case 0x7b: return 'B';//P1^0 低 返回‘B’ default: break;//没有本行的键按下 继续下面扫描 }
case 0xe7: return 'C';//P1^3 低 返回‘C’ case 0xd7: return 'D';//P1^2 低 返回‘D’ case 0xb7: return 'E';//P1^1 低 返回‘E’ case 0x77: return 'F';//P1^0 低 返回‘F’ default: break;//没有键按下 继续下面 } } return 0; } 希望新入行的兄弟上机试一下这段函数 可以配个 LCD 来做显示 也可以用串口发回电脑显 示 否则光是看看印象不会很深的 严重不建议简单电路使用软件仿真 还是要 搭板子 编程 烤片 试验的
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验八键盘扫描显示实验
所需软硬件:
Keil
STC-ISP
MCS-51 89C52实验箱
程序清单:
基于汇编语言
//连线P0接8列(同时也是数码管的位选线)高电平选中某位。
P3低两位接行P1接数码管(段选线)低电平选中某段亮。
ORG 0000H
LJMP MAIN
MAIN:
MOV 30H,#00H
MOV 31H,#00H
MOV 32H,#00H
MOV 33H,#00H
MOV 34H,#00H
MOV 35H,#00H
BEGIN:
ACALL SCAN
ACALL CHECK
ACALL DISP
SJMP BEGIN
//子程序SCAN 全扫描2次扫描去抖
SCAN:;全扫描
MOV R0,#00H;去抖,扫描2次计数标志
MOV A,#00H
MOV P0,A;送列扫描码
LOOP:
MOV A,P3;回读行信号
ANL A,#03H;只取低两位
INC R0
CJNE A,#03H,K1
CLR F0;无键,置标志位为0
K1:
NOP
NOP
CJNE R0,#02H,LOOP;去抖,扫描2次
SETB F0;有键,置标志位为1
RET
//子程序CHECK 逐列扫描确定键码
CHECK:
MOV R1,#0FEH ;开始逐列扫描,从第0列开始
MOV R4,#00H;记录列号
MOV R5,#00H;记录行号
MOV A,R1
PUSH ACC;压栈保留第0列扫描码
LOOP1:
MOV P0,A;送列扫描码
MOV A,P3
ANL A,#03H
CJNE A,#03H,K2;有键转K2确定为哪一行
POP ACC;无键扫描下一列
RL A
INC R4
CJNE R4,#08H,LOOP1 ; 是否扫描进行到最后一列
RET
K2:
DEC SP;为保证堆栈平衡
CJNE A,#00H,K3;分支判断,看是否为第一行
SJMP OVER
K3:
MOV A, R5
ADD A,#08H
MOV R5,A;不是第一行,就是第二行,行码加8 OVER:
MOV A,R4
ADD A,R5;行码+列码=键码
PUSH ACC;键码入栈保护
NOP
NOP
LCALL SCAN;扫描看手是否松开
CJNE A,#03H,OVER ;A=03H,表示手未松开,继续扫描
POP ACC;手松开,键码出栈
RET
//子程序DISP 键码分离送数码管显示
DISP:
JNB F0,LOOP3;无键不分离键码
MOV B,#10;有键,要进行十位和个位的分离
DIV AB
MOV 34H,A;A为十位
MOV 35H,B;B为个位
MOV R0,#30H;送显示缓冲首地址
MOV R2,#01H;送位选信号,从最低位开始亮
LOOP3:
MOV A,#0FFH
MOV P1,A;段选:送灭码
MOV A,R2
MOV P0,A;送位选信号
MOV A,@R0;送显示缓冲数据
MOV DPTR,#TAB;查表求字形码
MOVC A,@A+DPTR
MOV P0,A;送段选
ACALL DELAY1MS;延时以保持稳定
INC R0;取下一个数
MOV A,R2
JB ACC.5,EXIT;判断位选是否送到最高位
RL A ;左移选下一个位。
MOV R2,A;
AJMP LOOP3
EXIT:
RET
//子程序DELAY1MS
DELAY1MS:
MOV R7,#0FFH
DJNZ R7,$
RET
TAB:DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,88H,83H,0C6H,0AH,86H,8EH END。