键盘矩阵行反转法的讲解 有程序有注释 但是就是不明白它怎么实现的 我是单片机菜鸟 这是我看的第一个程序
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
行列线的交叉位置布置按键。所有行和列加上拉电阻。
所有行作输出先送低电平,然后读入列值。 如果有任意键按下,那么一定对应列值有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 }
以上是关于键盘矩阵行反转法的讲解 有程序有注释 但是就是不明白它怎么实现的 我是单片机菜鸟 这是我看的第一个程序的主要内容,如果未能解决你的问题,请参考以下文章