当前位置:网站首页>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.欢迎留言讨论~
边栏推荐
- LeetCode·297.二叉树的序列化与反序列化·DFS·BFS
- Interface Automation Testing Basics
- Codeforces Round #276 (Div. 1) D. Kindergarten
- Requirements for the construction of Loudi stem cell preparation laboratory
- 金山云要飘到哪里?
- Polygon zkEVM工具——PIL和CIRCOM
- Loudi Center for Disease Control and Prevention Laboratory Design Concept Description
- Educational Codeforces Round 41 (Rated for Div. 2) E. Tufurama
- 22!Beijing Changping District notified catering service enterprises with food safety problems
- 娄底污水处理厂实验室建设管理
猜你喜欢
商汤自研机械臂,首款产品是AI下棋机器人:还请郭晶晶作代言
LeetCode·每日一题·640.求解方程·模拟构造
九宫格抽奖动效
在web页面播放rtsp流视频(webrtc)
Reversing words in a string in LeetCode
wirshark 常用操作及 tcp 三次握手过程实例分析
ArcMAP has a problem of -15 and cannot be accessed [Provide your license server administrator with the following information:Err-15]
Nanodlp v2.2/v3.0光固化电路板,机械开关/光电开关/接近开关的接法和系统状态电平设置
Jiugongge lottery animation
DNS欺骗-教程详解
随机推荐
神经网络可视化有3D版本了,美到沦陷!(已开源)
Loudi Center for Disease Control and Prevention Laboratory Design Concept Description
中科院深圳先进技术院合成所赵国屏院士组2022年招聘启事
bgp双平面实验 路由策略控制流量
一个 CRM One Order Application log 的单元测试报表
bgp dual plane experiment routing strategy to control traffic
BEVDet4D: Exploit Temporal Cues in Multi-camera 3D Object Detection Paper Notes
【jstack、jps命令使用】排查死锁
A unit test report for CRM One Order Application log
AtCoder Beginner Contest 077 D - Small Multiple
“68道 Redis+168道 MySQL”精品面试题(带解析)
es6-promise对象详解
商汤自研机械臂,首款产品是AI下棋机器人:还请郭晶晶作代言
一文详解 implementation api embed
Shell:数组
【iOS】Organization of interviews
[Advanced Digital IC Verification] Difference and focus analysis between SoC system verification and IP module verification
漏洞管理计划的未来趋势
DNS欺骗-教程详解
Loudi Sewage Treatment Plant Laboratory Construction Management