导航:首页 > 操作系统 > 单片机矩阵运算

单片机矩阵运算

发布时间:2023-09-01 07:56:18

⑴ 谁能给我讲明白单片机的4x4矩阵键盘工作原理

给P1赋值0xf0,这时P1^4,P1^5,P1^6,P1^7为高电平,P1^0,P1^1,P1^2,P1^3为低电平。如果这时候有按键按下那么P1^4,P1^5,P1^6,P1^7就有一个会变成低电平。因此P1的值就不等于0xf0,这是就可以判断有按键按下。

4x4矩阵键盘的工作原理是在矩阵式键盘中,每条水平线和垂直线在交叉处不直接连通,而是通过一个按键加以连接。当按键没有按下时,所有的输入端都是高电平,代表无键按下。行线输出是低电平,一旦有键按下,则输入线就会被拉低,通过读入输入线的状态就可得知是否有键被按下。

(1)单片机矩阵运算扩展阅读:

在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式。在矩阵式键盘中,每条水平线和垂直线在交叉处不直接连通,而是通过一个按键加以连接。

这样,一个端口(如P1口)就可以构成4*4=16个按键,比之直接将端口线用于键盘多出了一倍,而且线数越多,区别越明显,比如再多加一条线就可以构成20键的键盘,而直接用端口线则只能多出一键(9键)。由此可见,在需要的键数比较多时,采用矩阵法来做键盘是合理的。

⑵ 单片机汇编矩阵键盘实验(扫描法)

关于扫描按键的原理,可以看下面这篇文章。

本文以循序渐进的思路,引导大家思考如何用最少的IO驱动更多的按键,并依次给出5种方案原理图提供参考。在实际项目中我们经常会遇到有按键输入的需求,但有的时候为了节省资源成本,我们都会选择在不增加硬件的情况下使用最少的控制器IO驱动更多的按键,那么具体是怎么做的呢,下面我们就以用5个IO引脚为例,讲下怎么设计可以实现更多的按键?共有5种设计思路,下面依次介绍。

思路一

首先通常想到的可能是下面这样的设计:

这样我们可以先识别K01、K02、K03、K04、K05,若没有按键按下然后再和思路四的设计一样去识别其他按键。但这样存在一个问题,如果IO1配置为0,IO5读到0,那么怎么知道是K51按下还是K05按下呢,这里只需要在程序里做下判断,先判断下是不是K05按下,若不是就是K51,因为按键K01、K02、K03、K04、K05在5个IO口都为读取的情况下,就可以识别,不需要扫描识别处理,相当于这5个按键优先级高与其他按键。

总结

综合上述,5个IO口最多可以识别25个按键,思路五程序上处理比较麻烦,若实际中只按思路四设计,也可识别20个按键,那么如果有N个IO口可识别多少按键呢?这里给出如下公式:

假设有N个IO口按照思路三可以识别N*(N-1)/2个;

按照思路四可识别N*(N-1)个;

按照思路5可以识别N*(N-1)+N个。

最后再说下,如果实际设计时,还是按思路四设计好,软件也没那么麻烦。如果是你的话你会选择哪种方法呢?你还有没有其他的设计方法呢?

⑶ 单片机矩阵键盘的键号=行首字+列号

这些,都是自定义的。

对于 4*4 的键盘,四个行首字,可以定为:0、4、8、12。
它们和行号的关系就是:4 * 行号。

四个列号,可以定为:0、1、2、3。

参考:
http://..com/question/298046533.html

其中检测按键的返回值就是:return (i + j * 4); //如果为0就返回按键值

⑷ 怎样用单片机实验板上的矩阵键盘和显示器编写一个简单的计算器,要求能一位数和两位数的加减乘除

#include <reg51.h>
#define uchar unsigned char
long First,End; //定义全局变量

void delay(int n) //***延时程序***//
{int i,j;
for(i=0;i<n;i++)
{for(j=0;j<50;j++)
;}
}

long add(long x,long y) //***加法程序***//
{long z;
z=x+y;
return(z);
}

long sub(long x,long y) //***减法程序***//
{long z;
if(x>=y)
z=x-y;
else
{z=y-x;
z=z+10e6;} //***最高位用1表示负数***//
return(z);
}

long mul(long x,long y) //***乘法程序***//
{long z;
z=x*y;
return(z);
}

long div(long x,long y) //***除法程序***//
{long z;
z=x/y;
return(z);
}

uchar kbscan(void) //***键盘扫描程序***//
{
uchar sccode;
P1=0xf0;
if((P1&0xf0)!=0xf0) //发全0行扫描码,列线输入
{ delay(222); //延时去抖
if((P1&0xf0)!=0xf0)
{sccode=0xfe; //逐行扫描初值
while((sccode&0x10)!=0)
{P1=sccode; //输出行扫描码
if((P1&0xf0)!=0xf0)
{
return(P1);} //如果检测到有键按下,返回键值
else
sccode=(sccode<<1)|0x01; //行扫描码左移一位
}
}
}
return(0); //无键按下,返回值为0
}

void display(void) //***显示程序***//
{int i;
uchar code rel[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe}; //数码管选通
uchar code led[]={0x7e,0x30,0x6d,0x79,0x33,0x5b,0x5f,0x70,0x7f,0x7b}; //定义0-9
uchar data num[8];
num[0]=First/10000000; //千万位
num[1]=First/1000000%10; //百万位
num[2]=First/100000%10; //十万位
num[3]=First/10000%10; //万位
num[4]=First/1000%10; //千位
num[5]=First/100%10; //百位
num[6]=First/10%10; //十位
num[7]=First%10; //个位
for(i=7;i>=0;i--)
{P3=rel[i]; //位选输出
P2=led[num[i]]; //数据输出
delay(2); //此延时必不可少?
}
}

void main(void) //***主程序***//
{ int k,n;
uchar f,g,key,gn1;
n=0;
f=0;
P0=0; //初始时指示灯灭
while(1) //不断查询是否有按键动作
{ key=kbscan(); //获取返回键值
if(key!=0)
{
switch(key) //译码,将对应按键返回值转换为相应数值
{
case 0xee: k=0;break;//0
case 0xde: k=1;break;//1
case 0xbe: k=2;break;//2
case 0x7e: k=3;break;//3
case 0xed: k=4;break;//4
case 0xdd: k=5;break;//5
case 0xbd: k=6;break;//6
case 0x7d: k=7;break;//7
case 0xeb: k=8;break;//8
case 0xdb: k=9;break;//9
case 0xbb: k=10;First=0;End=0;f=0;break;//清除
case 0x7b: k=11;break;//等于
case 0xe7: k=12;f=1;break;//加
case 0xd7: k=13;f=2;break;//减
case 0xb7: k=14;f=3;break;//乘
case 0x77: k=15;f=4;break;//除
}
P0=1;
delay(280); //有按键时,指示灯的显示时间
P0=0; //按键指示灭
if(k<10) //为数字键时(0-9)
{
if(f!=0) //为数字键时,如果已经有功能键按下
{
n++; //记录数字键所按次数
gn1=0; //清除标志,再次为功能键时进行运算
g=f; //保存运算标志
if(n==1) //输入为各位数时,直接赋值
First=k;
else if(n>1) //输入为多位数时,将它转化为10进制的多位数
First=First*10+k;
}
else //如果没有功能键按下
{
n++;
gn1=1; //定义标志,当下一次为功能键时,停止数据输入
if(n==1)
First=k;
else if(n>1)
First=First*10+k;
End=First; //将第一个数保存
}
}
else if(k>11) //为功能键时(+-*/)
{
if(gn1==1) //前一次数字键之后为功能键时
{
n=0; //清除计数标志
}
else //如果再次输入功能键,则进行运算
{n=0; //清除计数标志
switch(g)
{case 1: First=add(End,First);break;
case 2: First=sub(End,First);break;
case 3: First=mul(End,First);break;
case 4: First=div(End,First);break;}
}
End=First; //保存本次结果
}
else if(k==11) //为等于号时(=)
{n=0;
gn1=1; //接着输入为功能键时可以继续运算
switch(g)
{case 1: First=add(End,First);break;
case 2: First=sub(End,First);break;
case 3: First=mul(End,First);break;
case 4: First=div(End,First);break;
}
End=First; //保存最终运算结果
f=0; //清除运算标志
}
}
display(); //调用显示程序
}
}

⑸ 用89C51单片机设计4*4矩阵式键盘计算器程序 要汇编的

KEYBUF EQU 40H ;键号存放单元
ORG 0000H
LJMP MAIN
ORG 0030H
MAIN: MOV KEYBUF,#0 ;初始键号设位0,也可以为任意值
MOV R0,#30H ;显示首地址
MOV R2,#0CH ;计算数据存放单元个数
CLR A
QING: MOV @R0,A ;将数据存放单元清零
INC R0
DJNZ R2,QING
MOV P0,#8FH ;关闭显示
MOV R1,#30H ;将显示首地址存放R1里
;===============================================
;五位无符号显示子程序
DIS1: MOV R0,#30H ;把显示数据第一位放在R0里
MOV R2,#04H ;把显示的位码放在R2里
MOV R3,#05H ;把显示的长度放在R3里
DIS2: MOV A,@R0
ANL A,#0FH ;屏蔽显示数据的高四位
MOV B,A
MOV A,R2
ANL A,#0FH ;屏蔽位码的高四位
SWAP A
ORL A,B
MOV P0,A ;送总显示数据到P0显示
LCALL DELY4ms ;调用延时4ms
INC R0 ;取下一个显示数据
DEC R2
DJNZ R3,DIS2 ;四位显示晚后重新开始显示
;===================================================
;键盘扫描子程序
WAIT: MOV P1,#0FFH ;P1口送高电平
CLR P1.0 ;第一行清零
MOV A,P1 ;读P1口
ANL A,#0F0H ;低位屏蔽
XRL A,#0F0H ;判断低位是否有低电平 ,即判断是否有按键按下
JZ NOKEY1 ;地位有低电平继续扫描,否者跳到第而行去扫描
LCALL DELY10ms ;延时10ms去抖在进行判断是否有按键按下
MOV A,P1 ;继续读P1口
ANL A,#0F0H ;判断低位是否有低电平
CJNE A,#0E0H,NK1 ;如果扫描数据不为0E0H就转到NK1
MOV KEYBUF,#0 ;否者判断为0号键
AJMP DK ;转DK1查表程序
NK1: CJNE A,#0D0H,NK2 ;如果扫描数据不为0D0H就转到NK2
MOV KEYBUF,#1 ;否者判断为1号键
AJMP DK ;转DK2查表程序
NK2: CJNE A,#0B0H,NK3 ;如果扫描数据不为0B0H就转到NK3
MOV KEYBUF,#2 ;否者判断为2号键
AJMP DK ;转DK3查表程序
NK3: CJNE A,#70H,NK4 ;如果扫描数据不为70H就转到NK4
LJMP SAN_CHU
NK4: NOP
NOKEY1: MOV P1,#0FFH ;和上面相同
CLR P1.1
MOV A,P1
ANL A,#0F0H
XRL A,#0F0H
JZ NOKEY2
LCALL DELY10MS
MOV A,p1
ANL A,#0F0H
XRL A,#0F0H
JZ NOKEY2
MOV A,P1
ANL A,#0F0H
CJNE A,#0E0H,NK5
MOV KEYBUF,#3
AJMP DK
NK5: CJNE A,#0D0H,NK6
MOV KEYBUF,#4
AJMP DK
NK6: CJNE A,#0B0H,NK7
MOV KEYBUF,#5
AJMP DK
NK7: CJNE A,#70H,NK8
MOV KEYBUF,#10 ;否者判断为3号键
AJMP DK ;转DK4查表程序
NK8: NOP
NOKEY2: MOV P1,#0FFH
CLR P1.2
MOV A,P1
ANL A,#0F0H
XRL A,#0F0H
JZ NOKEY3
LCALL DELY10MS
MOV A,P1
ANL A,#0F0H
XRL A,#0F0H
JZ NOKEY3
MOV A,P1
ANL A,#0F0H
CJNE A,#0E0H,NK9
MOV KEYBUF,#6
AJMP DK
NK9: CJNE A,#0D0H,NK10
MOV KEYBUF,#7
AJMP DK
NK10: CJNE A,#0B0H,NK11
MOV KEYBUF,#8
AJMP DK
NK11: CJNE A,#70H,NK12
LJMP DENG_HAO
NK12: NOP
NOKEY3: MOV P1,#0FFH
CLR P1.3
MOV A,P1
ANL A,#0F0H
XRL A,#0F0H
JZ NOKEY4
LCALL DELY10MS
MOV A,P1
ANL A,#0F0H
XRL A,#0F0H
JZ NOKEY4
MOV A,P1
ANL A,#0F0H
CJNE A,#0E0H,NK13
LJMP CHU
NK13: CJNE A,#0D0H,NK14
LJMP CHENG
NK14: CJNE A,#0B0H,NK15
LJMP JIAN
NK15: CJNE A,#70H,NK16
LJMP JIA
NK16: NOP
;=======================================================
;查表求键值程序
DK: MOV B,#00H
MOV A,KEYBUF ;查表程序 查对应的键号数据
MOV DPTR,#TABLE ;把表头地址放入DPTR
MOVC A,@A+DPTR ;A里面存放的为键号,利用A和表头地址找到对应的键号数据
MOV B,A ;把查到的数据送往显示单元
INC R1 ;取下一个显示单元
MOV A,R1
CJNE A,#36H,DKA1 ;判断显示单元是否已满
MOV R1,#35H ;35H,36H单元用于更好的控制五位显示
AJMP DKA
DKA1: MOV 34H,33H ;按键代码按左移显示,先按先显示
MOV 33H,32H
MOV 32H,31H
MOV 31H,30H
MOV 30H,B
DKA: MOV A,P1 ;读P1口
ANL A,#0F0H ;屏蔽高四位
XRL A,#0F0H ;地位是有低电平
JNZ DKA ;如果有低电平继续读P1口,否者向下执行,查找第二行
NOKEY4: LJMP DIS1
;===================================
;功能按键功能设定
DENG_HAO:MOV DPTR,#JI_SUAN ;等号键功能通过加、减、乘、除设定的偏移量来调用子程序
MOV A,3CH ;3CH存放的为功能程序入口地址偏移量
JMP @A+DPTR ;转移到按键功能程序
JI_SUAN: AJMP JIA1 ;加计算子程序
AJMP JIAN1 ;减计算子程序
AJMP CHENG1 ;乘计算子程序
AJMP CHU ;除计算子程序
;=======删除键功能
SAN_CHU: ACALL QING_DIS
AJMP DKA
;=======加键功能
JIA: MOV 3CH,#00H
ACALL CUN_SHU
ACALL QING_DIS
AJMP DKA
;=======减键功能
JIAN: MOV 3CH,#02H
ACALL CUN_SHU
ACALL QING_DIS
AJMP DKA
;=======乘键功能
CHENG: MOV 3CH,#04H
ACALL CUN_SHU
ACALL QING_DIS
AJMP DKA
;=======除键功能
CHU: MOV 3DH,#06H
ACALL CUN_SHU
ACALL QING_DIS
AJMP DKA

;=================================
;存被加(减、乘、除)数,存放在37H~3BH里
CUN_SHU: MOV 37H,30H ;36H存放的为最低位
MOV 38H,31H
MOV 39H,32H
MOV 3AH,33H
MOV 3BH,34H ;3AH存放的为最高位
RET
;================================
;清除显示单元
QING_DIS: MOV R1,#30H
QING1: MOV @R1,#00H
INC R1
MOV A,R1
CJNE A,#36H,QING1
MOV R1,#30H
LOP1: RET
;================================
;十进制加法子程序
JIA1:
MOV A,37H ;个位被加数
ADD A,30H ;个位被加数+加数
MOV B,#10 ;十六进制除10转换成BCD码
DIV AB
MOV 30H,B ;余数即个位存放在30H
MOV 37H,A ;商存放在37H
MOV A,38H ;十位被加数
ADD A,31H ;十位被加数+加数
ADD A,37H ;加上个位之和的进位
MOV 37H,#00H ;清除37H
MOV B,#10 ;十六进制除10转换成BCD码
DIV AB
MOV 31H,B ;余数即十位存放在31H
MOV 38H,A ;商存放在38H
MOV A,39H ;百位计算同十位
ADD A,32H
ADD A,38H
MOV 38H,#00H
MOV B,#10
DIV AB
MOV 32H,B
MOV 39H,A
MOV A,3AH ;千位计算同十位
ADD A,33H
ADD A,39H
MOV 39H,#00H
MOV B,#10
DIV AB
MOV 33H,B
MOV 3AH,A
MOV A,3BH ;万位计算同十位
ADD A,34H
ADD A,3AH
MOV 3AH,#00H
MOV B,#10
DIV AB
MOV 34H,B
MOV 3BH,#00H
AJMP DKA
;=====================
JIAN1: AJMP DKA
CHENG1: AJMP DKA
CHU1: AJMP DKA
;=============================================
;延时程序和查表表格
DELY4ms: MOV R6,#8 ;延时4毫秒
D1: MOV R7,#248
DJNZ R7,$
DJNZ R6,D1
RET
DELY10ms:MOV R6,#20 ;延时10毫秒
D2: MOV R7,#248
DJNZ R7,$
DJNZ R6,D2
RET
TABLE: DB 07H, 04H, 01H ; / 本表格是以键盘为参考 7 8 9 /
DB 08H, 05H, 02H ; * 4 5 6 *
DB 09H, 06H, 03H ; - 1 2 3 -
DB 00H, 00H ;= + 清除 0 = +
END

⑹ 51单片机如何用矩阵按键输入多位数,比如输入6显示6,再输入7显示67,最好给个c的程序,谢了!

用数组啊,如果是指定位数的就比较简单

当第一次输入时i=0,第一个数6放a[0],i=1,第二个数7放a[1],显示就是

OUT=a[0]*10+a[1]*1


数组用之前初始化为0,a[2]={0}

//这个好用点,递推
if(key_data)//有按键按下
{
for(i=key_count;i>0;i--;)
{
a[i+1]=a[i];

}
a[0]=key_data;
key_count++;
}

//显示调用,根据你的输入最大数定数组的位数
Sprint=a[3]*1000+a[2]*100+a[1]*10+a[0]*1;
阅读全文

与单片机矩阵运算相关的资料

热点内容
活塞式压缩机原理图 浏览:842
水环式压缩机工作原理 浏览:713
阿里云服务器安装后怎么使用 浏览:931
去做APP开户有什么危险没得啊 浏览:696
8分之1乘58算法 浏览:170
php提交过滤 浏览:356
豪斯曼检验stata命令 浏览:769
云看地是什么APP 浏览:885
数学指南pdf 浏览:858
phpcurldll64位 浏览:982
程序员脱产一年半 浏览:851
hr招程序员有什么条件 浏览:589
android开源集合 浏览:872
华为云服务器登录密码和账号 浏览:155
中世纪java程序员 浏览:788
什么开发引擎使用python 浏览:177
sh脚本运行命令 浏览:318
广联达加密锁怎么看到期 浏览:174
cad轨迹命令 浏览:981
同事刷到女程序员自媒体视频 浏览:573