当前位置:网站首页>Matrix Keyboard & Calculator Small Project Based on 51 (UcosII)
Matrix Keyboard & Calculator Small Project Based on 51 (UcosII)
2022-08-10 13:21:00 【not enough】
矩阵键盘
I'm going to give it to a younger brother and a younger sister recently(应该没有)Training the matrix keyboard,Just to write about my thoughts on writing a matrix keyboard,By the way, I will share a based on what I did beforeucosiismall calculator project
原理
原理就不介绍了,CSDNThere is a lot to share,Two references are recommended:
参考:矩阵键盘_Danshan Qifeng's blog-CSDN博客_矩阵键盘
参考:This article will take you to explain the working principle of the matrix keyboard in detail_Z小旋的博客-CSDN博客_矩阵键盘工作原理
代码
行列扫描法:
原理:
我习惯用x,y轴,Abstract the matrix keyboard into a binary function
Scan the column first,The row port outputs a low level,The column port outputs a high level.Read column port(是否被拉低)获取列值;
Scan the line again,The column port outputs a low level,The row port outputs a high level.Read line port(是否被拉低)获取行值.
Finally, the key value is calculated from the row value and the column value.
PS:The relationship between the key value and the row and column values can be solved through the equation system,Refer to the diagram below to set up the equation:ax+by+c=key_num(a,b,c为系数,x和yfor the row and column values,key_num为键值,Remember to bring in the verification when you solve it)
PS:Row and column coordinates can be customized,Just solve the corresponding calculation formula
1 2 3 4 S7 S11 S15 S19
5 6 7 8 S6 S10 S14 S18
9 10 11 12 S5 S9 S13 S17
13 14 15 16 S4 S8 S12 S16
如下图:
S7: 1 * a + 4 * b + c = 1; S4: 1 * a + 1 * b + c = 13; S16: 4 * a + 1 * b + c = 16
解得: x + 4 * y - 16 = key_num

源码:
/*********4*4键盘扫描*********** 对应键值关系 1 2 3 4 S7 S11 S15 S19 5 6 7 8 S6 S10 S14 S18 9 10 11 12 S5 S9 S13 S17 13 14 15 16 S4 S8 S12 S16 在stc15上无P36 P37,对应的是P42 P44!!!!!!!! 函数返回值为0-16 ***************************/
unsigned char key_scanf()
{
uchar x=0,y=0;
//io口赋值
P30=0;P31=0;P32=0;P33=0;//Pull the row down
P34=1;P35=1;P42=1;P44=1;//Pull up the column
if(!(P34&P35&P42&P44))//Determine if it is pressed
{
Delay20us(); //消抖
if(!(P34&P35&P42&P44))//Check again whether it is pressed
{
if(!P34)
x=4;
if(!P35)
x=3;
if(!P42)
x=2;
if(!P44)
x=1;//Get column value
P30=1;P31=1;P32=1;P33=1;//Pull up the row
P34=0;P35=0;P42=0;P44=0;//Pull the column down
if(!P30)
y=1;
if(!P31)
y=2;
if(!P32)
y=3;
if(!P33)
y=4;//获取行值
while(!(P30&P31&P32&P33));//等待释放
return (x-4*y+16); //计算键值
}
}
return 0;//无按键按下返回0
}
计算方法2:
在使用Proteus仿真时,The previous calculation method does not work very well,不清楚原因,I found a way to use the simulation effect on the Internet.
源码:
unsigned char code a[]={
0xFE,0xFD,0xFB,0xF7};
//按键扫描函数
int Sacn_Key(void)
{
unsigned char row,col,i;
P1=0xf0;
if((P1&0xf0)!=0xf0)
{
//delay(10);
if((P1&0xf0)!=0xf0)
{
row=P1^0xf0; //确定行线
i=0;
P1=a[i]; //精确定位
while(i<4)
{
if((P1&0xf0)!=0xf0)
{
col=~(P1&0xff); //确定列线
break; //已定位后提前退出
}
else
{
i++;
P1=a[i];
}
}
}
else
{
return 0;
}
while((P1&0xf0)!=0xf0);
return (row|col); //行线与列线组合后返回
}
else return 0; //无键按下时返回0
}
This scanning method can be used with a parsing program to analyze the pressed keys,我用的是switch函数实现,Refer to the picture above for the button:
//Parse the value of the key scan function
char coding(int k)
{
char res;
switch (k)
{
case 0: res = 0; break;
case 17:res = '7';break;
case 18:res = '4';break;
case 20:res = '1';break;
case 24:res = ' ';break;
case 33:res = '8';break;
case 34:res = '5';break;
case 36:res = '2';break;
case 40:res = '0';break;
case 65:res = '9';break;
case 66:res = '6';break;
case 68:res = '3';break;
case 72:res = '=';break;
case 129:res = '/';break;
case 130:res = '*';break;
case 132:res = '-';break;
case 136:res = '+';break;
}
return res;
}
小项目:基于51的计算器:
简介:
基于Proteus仿真,51芯片,搭载ucosii.The complete simulation project and project code will be packaged and uploaded(will be at the end of the article).
PS:1. 小黑框Virtual Terminal 在菜单栏DebugOh the last one
2. The emulation should configure the serial port baud rate as 19200(Double-click the external black box on the schematic),点击ok
设计思路:
三个任务:计算任务,输出任务,按键任务
- 计算任务:Get the formula,传送结果
- 输出任务:The serial port outputs what needs to be displayed
- 按键任务:检测矩阵键盘,获取输入内容
结构体
Used to store input calculations,Posted by the key task to the calculation task
typedef struct { int num1;//数字1 int num2;//数字2 char cal;//运算符 }my_cal_t; my_cal_t my_cc;邮箱
Calculator struct mailbox:It is used for the key function to output the calculation task to the calculation task
Serial output data mailbox:Serial output data mailbox,Used to output content to the virtual serial port
OS_EVENT * Num_Box;//Calculator struct mailbox OS_EVENT * Mes_Box;//Serial port display data mailbox code implementation:
代码:
部分代码:
主函数
//初始化系统,初始化外设,初始化任务,启动调度 void main(void) { OSInit(); InitTimer0(); InitSerial(); InitSerialBuffer(); Num_Box = OSMboxCreate((void*)0); Mes_Box = OSMboxCreate((void*)0); //Matrix keyboard tasks OSTaskCreate(TaskStartyya, (void *)0, &TaskStartStkyya[0],4); //计算任务 OSTaskCreate(TaskStartyyb, (void *)0, &TaskStartStkyyb[0],3); //Serial display tasks OSTaskCreate(TaskStartyyc, (void *)0, &TaskStartStkyyc[0],2); OSStart(); }键盘任务
//Loop to get the calculation formula,Delivery to mailbox for(;;){ my_cc.num1 = 0; my_cc.num2 = 0; my_cc.cal = 0; PrintStr("\nPlease enter num1 (end by /,*,+,-):\n"); //Number one and operator input for(i = 0;i < 4;) { //Loop to get keys temp = 0; temp = Sacn_Key(); t = coding(temp); //判断是否为运算符 if(t == '/'||t == '*'||t == '+'||t == '-') { sprintf(txt, "%c", t); OSMboxPost(Mes_Box, txt); my_cc.cal = t; break; } //判断输入是否为数字 if(t <= '9'&&t >= '0') { num1[i] = t - 0x30; sprintf(txt, "%d", num1[i]); OSMboxPost(Mes_Box, txt); i++; if(i==4) { //输入满4bit exit,获取运算符号 PrintStr("\nPlease enter /,*,+,-\n"); //The loop waits for operator input while(1) { temp = Sacn_Key(); t = coding(temp); if(t == '/'||t == '*'||t == '+'||t == '-') { my_cc.cal = t; sprintf(txt, "%c", t); OSMboxPost(Mes_Box, txt); break; //是运算符,Exit digital one input } } } } OSTimeDlyHMSM(0,0,0,10); } //Calculate the number one for(temp=0;temp<i;temp++) { my_cc.num1*=10; my_cc.num1+=num1[temp]; } //输入数字二 PrintStr("\nPlease enter num2 (end by =):\n"); for(i = 0;i < 4;) { temp = 0; temp = Sacn_Key(); t = coding(temp); //判断是否输入等于号 if(t == '=') { break; } //判断是否输入数字 if(t <= '9'&&t >= '0') { num2[i] = t - 0x30; sprintf(txt, "%d", num2[i]); OSMboxPost(Mes_Box, txt); i++; } OSTimeDlyHMSM(0,0,0,10); } //Calculate the number two for(temp=0;temp<i;temp++) { my_cc.num2*=10; my_cc.num2+=num2[temp]; } //Put the struct into the mailbox OSMboxPost(Num_Box, &my_cc); }计算任务
//Hang up and wait for the key task to wake up,After the calculation is completed, the result is sent to the output task for(;;){ //等待邮箱 cc = OSMboxPend(Num_Box,0,&err); res = 0; //PrintStr("\nok\n"); //Calculate the result according to the operator switch (cc->cal) { case '/':if(cc->num2 == 0) { sprintf(txt,"\nillegal value!\n",res); OSMboxPost(Mes_Box, txt); continue; } else{ res=(float)cc->num1/(float)cc->num2;}break; case '*':res=cc->num1*cc->num2;break; case '+':res=cc->num1+cc->num2;break; case '-':res=cc->num1-cc->num2;break; } //输出结果 sprintf(txt,"\nresult is %.02f\n",res); OSMboxPost(Mes_Box, txt); }输出任务
//没啥实际意义,Simple encapsulated tasks void TaskStartyyc(void *yydata) reentrant { char *txt; int err; yydata=yydata; for(;;){ //接收邮件,And print with serial port txt = OSMboxPend(Mes_Box,0,&err); PrintStr(txt); } }
感想
Because it is written in a hurry,I feel the code is very crude myself,Many places may still need scrutiny;Of course because of the rush to write,Functionality is also limited,Only binocular calculations are possible.Consider using51系列芯片,还跑了ucosii,So it may be replaced later in the improvement32来仿真.This project I use is transplanted,Download it and use it,It is difficult to modify if it is not transplanted by yourself,Many files have permissions,So it is for reference.
My current ideas for improvement:
- Use stack instead of struct(Everything is a data structure)
- Optimize output tasks(还没想好,Generally speaking, it is possible to transplant digital tubes or other display methods)
- …
The simulation project and project source code are being packaged and uploaded,可以关注公众号,发送:计算器,Automatically reply to cloud disk links.欢迎留言讨论~
边栏推荐
- Reversing words in a string in LeetCode
- 大佬们有遇到过这个问题吗? MySQL 2.2 和 2.3-SNAPSHOT 都这样,貌似是
- Polygon zkEVM工具——PIL和CIRCOM
- R语言实战应用案例:论文篇(一)-特殊柱形图绘制
- C#WPF 图片在显示时没有问题,但在运行时图片显示不出来的解决
- 用低代码驱动IT现代化
- 燃炸!字节跳动成功上岸,只因刷爆LeetCode算法面试题
- 2022-08-09:以下go语言代码输出什么?A:否,会 panic;B:是,能正确运行;C:不清楚,看投票结果。 package main import ( “fmt“ “syn
- 没有接班人,格力只剩“明珠精选”
- 接口自动化测试基础篇
猜你喜欢

MySQL面试题整理

Reversing words in a string in LeetCode

BEVDet4D: Exploit Temporal Cues in Multi-camera 3D Object Detection 论文笔记

bgp双平面实验 路由策略控制流量

Solution for "Certificate not valid for requested usage" after Digicert EV certificate signing

wirshark 常用操作及 tcp 三次握手过程实例分析

【百度统计】用户行为分析

想通这点,治好 AI 打工人的精神内耗

燃炸!字节跳动成功上岸,只因刷爆LeetCode算法面试题

LeetCode中等题之比较版本号
随机推荐
BEVDet4D: Exploit Temporal Cues in Multi-camera 3D Object Detection 论文笔记
【iOS】Organization of interviews
MySQL索引的B+树到底有多高?
汉字检测和关键词检测
Educational Codeforces Round 41 (Rated for Div. 2) E. Tufurama
Jenkins修改默认主目录
Real-time data warehouse practice of Baidu user product flow and batch integration
Efficient and Robust 2D-to-BEV Representation Learning via Geometry-guided Kernel Transformer 论文笔记
Import other custom namespaces in C#
「网络架构」网络代理第一部分: 代理概述
C# error The 'xmins' attribute is not supported in this context
rpn:def concat_box_prediction_layers
A detailed explanation of implementation api embed
C# InitializeComponent() does not exist in the current context
想通这点,治好 AI 打工人的精神内耗
线代 | 秒杀方法与技巧
phpstrom 快速注释:
把相亲角搬到海外,不愧是咱爸妈
Reversing words in a string in LeetCode
Guidelines for Sending Overseas Mail (2)