键盘矩阵行反转法的讲解 有程序有注释 但是就是不明白它怎么实现的 我是单片机菜鸟 这是我看的第一个程序

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了键盘矩阵行反转法的讲解 有程序有注释 但是就是不明白它怎么实现的 我是单片机菜鸟 这是我看的第一个程序相关的知识,希望对你有一定的参考价值。

PA EQU 0CFA0H
PB EQU PA+1
PC0 EQU PB+1
PCTL EQU PC0+1
CSEG AT 0000H
LJMP START
CSEG AT 0100H
START: MOV 42H,#0FFH ;42H中放显示的字符码,初值为0FFH
STA1: MOV DPTR,#PCTL ;设置控制字,ABC口工作于方式0
;AC口输出而B口用于输入
MOV A,#82H
MOVX @DPTR,A
LINE: MOV DPTR,#PC0 ;将字符码从C口输出显示
MOV A,42H
CPL A
MOVX @DPTR,A
CLR A
MOV DPTR,#PA ;从A口输出全零到键盘的列线
MOVX @DPTR,A
MOV DPTR,#PB ;从B口读入键盘行线值
MOVX A,@DPTR
MOV 40H,A ;行线值存于40H中
CPL A ;取反后如为全零
;表示没有键闭合,继续扫描
JZ LINE
MOV R7,#10H ;有键按下,延时10MS去抖动
DL0: MOV R6,#0FFH
DL1: DJNZ R6,DL1
DJNZ R7,DL0
MOV DPTR,#PCTL ;重置控制字,让A为输入,BC为输出
MOV A,#90H
MOVX @DPTR,A
MOV A,40H
MOV DPTR,#PB ;刚才读入的行线值取出从B口送出
MOVX @DPTR,A
MOV DPTR,#PA ;从A口读入列线值
MOVX A,@DPTR
MOV 41H,A ;列线值存于41H中
CPL A ;取反后如为全零
JZ STA1 ;表示没有键按下
MOV DPTR,#TABLE ;TABLE表首地址送DPTR
MOV R7,#18H ;R7中置计数值16
MOV R6,#00H ;R6中放偏移量初值
TT:
MOV A,#00H
MOVC A,@A+DPTR ;从表中取键码前半段字节,行线值与实
CJNE A,40H,NN1 ;际输入的行线值相等吗?不等转NN1
INC DPTR ;相等,指针指向后半字节,即列线值
MOV A,#00H
MOVC A,@A+DPTR ;列线值与实际输入的列线值
CJNE A,41H,NN2 ;相等吗?不等转NN2

MOV DPTR,#CHAR ;相等,CHAR表基址和R6中的偏移量
MOV A,R6 ;取出相应的字符码
MOVC A,@A+DPTR
MOV 42H,A ;字符码存于42H
BBB: MOV DPTR,#PCTL ;重置控制字,让AC为输出,B为输入
MOV A,#82H
MOVX @DPTR,A
AAA: MOV A,42H ;将字符码从C口送到二极管显示
MOV DPTR,#PC0
CPL A
MOVX @DPTR,A
JMP STA1 ;转START
NN1: INC DPTR ;指针指向后半字节即列线值
NN2: INC DPTR ;指针指向下一键码前半字节即行线值
INC R6 ;CHAR表偏移量加一
DJNZ R7,TT ;计数值减一,不为零则转TT继续查找
JMP BBB
TABLE: DW 0FE06H,0FD06H,0FB06H,0F706H,0EF06H,0DF06H,0BF06H,07F06H ;TABLE为键值表,每个键位占
DW 0FE05H,0FD05H,0FB05H,0F705H,0EF05H,0DF05H,0BF05H,07F05H ;两个字节,第一个字节为行
DW 0FE03H,0FD03H,0FB03H,0F703H,0EF03H,0DF03H,0BF03H,07F03H ;线值,第二个为列线值

CHAR: DB 00H,01H,02H,03H,00H,00H,04H,05H,06H,07H,00H,00H,08H,09H ;字符码表
DB 0AH,0BH,00H,00H,0CH,0DH,0EH,0FH,00H,00H
END

参考技术A 1、行反转法的基本概念是:
行列线的交叉位置布置按键。所有行和列加上拉电阻。
所有行作输出先送低电平,然后读入列值。 如果有任意键按下,那么一定对应列值有0出现,也就知道了按下的键所在列。
反过来驱动这一列为0,其他列为1。把行作输入。就可以判断按下的键所在行。
2、掌握8255的接口。如何配置输入和输出。如何访问他们。
根据以上两点,和注释,你就能读懂程序的意图了。追问

多谢了 怎么确定行列线值明白了 可是底下table 和char是一一对应的 0fe06h 就代表11111110 00000110表示第一行第一列的那个键 也就是00h对吧 但是我不明白 程序中用这个table什么的干啥了 我主要不明白程序里的 。。恳请大哥指教。。

追答

1、这可能是8*3矩阵键盘。所以对应的行列值昏别放在两哥字节里面。
TABLE表示硬件键码,CHAR表示对应索引键码表示的用户键值。
2、程序简要说明
STA1:配置A、C输出。B输入。
LINE:送字符码到C显示。
列A全零,读B行
行值为零,跳LINE。保存行值到40H
DLx:去抖动。
列A输入,B输出送行值40H-----行反转
列值读入到41H。(如果41H、40H都不为零,有键按下)
无键STA1
TT: 开始查表。把40H和41H和TABLE进行两两字节逐个比对。
R6记录比对到第几个。通过R6再访问CHAR得到用户键值。
找到后, 字符码为CHAR中内容,送显示,跳到STA1

本回答被提问者采纳

高斯消元法的C++简单实现

高斯消元法

  首先,我们导入几个概念。

定义1: 一个矩阵称为阶梯形(行阶梯形),若它有以下三个性质:

  1.每一非零行在每一零行之上;

  2.某一行的先导元素所在的列位于前一行先导元素的后面;

  3.某一行先导元素所在列下方元素都是零。

  比如,

定义2:若一个阶梯形矩阵还满足以下性质,称它为简化阶梯形(简化行阶梯形):

  1.每一非零行的先导元素是1;

  2.每一先导元素1是该元素所在列的惟一非零元素。

  比如,

定理1:每个矩阵行等价于惟一的简化阶梯形矩阵。即简化阶梯形矩阵是惟一的。


   下面,我们用一个具体例子来说明高斯消元法的主要步骤。

  原矩阵:

  第一步,由最左的非零列开始,这是一个主元列。主元位置在该列顶端。

  第二步,在主元列中选取一个非零元作为主元。若有必要的话,对换两行使这个元素移到主元位置上。

  第三步,用倍加行变换将主元下面的元素变成0.

  第四步,暂时不管包含主元位置的行以及它上面的各行,对剩下的子矩阵使用上述的三个步骤直到没有非零行需要处理为止。

  对每一行重复上述步骤。

  第五步,由最右面的主元开始,把每个主元上方的各元素变成0.若某个主元不是1,用倍乘变换将它变成1.

  最后,我们就得到了原矩阵的简化阶梯形。

  其中,第1~4步称为行化简算法的向前步骤,产生唯一的简化阶梯形的第5步,称为向后步骤。

 


 

C++实现

  我们尝试用C++来实现以上步骤。这里只是简单的实现,也就是用代码描述了上述步骤,没有考虑过多的问题。欢迎大家在评论里指出问题,提出更好的建议,以便于日后改进。

  大概的实现思路就是先实现向前步骤:

  首先,我们对于每一行找到第一个不为零的元素,并且将这一行置为1 * * * *的形式,用这一行乘上倍数加到之后的每一行。

  再实现向后步骤:

  然后,我们从最后一行开始,选择主元,加到之前的每一行上,使得该列的元素都为零。

  最后,我们就完成了化简,得到了简化阶梯形。

  以上算法只是一个粗略实现,主要体现在:

  1.对于主元的选定不够最优;

  2.会出现精度问题;

  3.对于某些情况无法处理。

  先暂时贴上代码,之后有时间再进行优化。

 1 #include <iostream>
 2 #include <cstdio>
 3 
 4 using namespace std;
 5 
 6 int main()
 7 {
 8     double martix[100][100];
 9     int n, m; // n行m列
10 
11     scanf("%d %d", &n, &m);
12 
13     // 输入
14     for(int i = 0; i < n; i++)
15         for(int j = 0; j < m; j++)
16             scanf("%lf", &martix[i][j]);
17 
18     // 向前步骤
19     for(int i = 0; i < n - 1; i++)
20     {
21         // 找主元
22         int pos = 0;
23         for(int j = 0; j < m; j++)
24             if(martix[i][j])
25             {
26                 pos = j;
27                 break;
28             }
29 
30         if(martix[i][pos] != 1 && martix[i][pos] != 0)
31         {
32             double tmp = martix[i][pos];
33             for(int j = pos; j < m; j++)
34             {
35                 martix[i][j] = martix[i][j] / tmp;
36             }
37         }
38         for(int j = i + 1; j < n; j++)
39         {
40             if(!martix[j][pos])
41                 continue;
42             double tmp = martix[j][pos];
43             for(int k = pos; k < m; k++)
44             {
45                 martix[j][k] = martix[j][k] - martix[i][k] * tmp;
46             }
47         }
48     }
49 
50     // 向后步骤
51     for(int i = n - 1; i > 0; i--)
52     {
53         int pos = 0;
54         for(int j = 0; j < m; j++)
55             if(martix[i][j])
56             {
57                 pos = j;
58                 break;
59             }
60 
61         if(martix[i][pos] != 1 && martix[i][pos] != 0)
62         {
63             double tmp = martix[i][pos];
64             for(int j = pos; j < m; j++)
65             {
66                 martix[i][j] = martix[i][j] / tmp;
67             }
68         }
69 
70         for(int j = 0; j < i; j++)
71         {
72             if(!martix[j][pos])
73                 continue;
74             double tmp = martix[j][pos];
75             for(int k = pos; k < m; k++)
76             {
77                 martix[j][k] = martix[j][k] - martix[i][k] * tmp;
78             }
79         }
80     }
81 
82     // 输出
83     for(int i = 0; i < n; i++)
84     {
85         for(int j = 0; j < m; j++)
86             printf("%-10.2f", martix[i][j]);
87         printf("\\n");
88     }
89     return 0;
90 }

 

 

 

 

以上是关于键盘矩阵行反转法的讲解 有程序有注释 但是就是不明白它怎么实现的 我是单片机菜鸟 这是我看的第一个程序的主要内容,如果未能解决你的问题,请参考以下文章

进阶项目(11) 矩阵键盘程序设计讲解

设计一个3 行×4列的矩阵键盘,采用行扫描法编写程序,当有按键动作时,能够获得按键

4x4矩阵键盘

51单片机实现矩阵键盘行扫描

java注释讲解

蓝桥杯单片机必备知识-----矩阵按键