您现在的位置是:首页 > 正文

蓝桥杯51小练习--简易计算器

2024-02-01 00:16:40阅读 2

0x00 前言

  有一段时间没写51的单片机了,实验室的学长留了个小练习,我就用来当“复健”了。一个极其简易的计算器,看起来很简单,但有些细节也是琢磨了一下的(俺还是菜),用的是蓝桥杯的板子,代码的质量着实堪忧。

0x01 题目

小练习:简易计算器

初始显示界面

使用16个按键每个按键对应的值为

0   1   2   3

4   5   6   7

8   9   +   -

*   /  清除  =

可以实现两位数的加减

前两个数码管显示第一位数,第三个数码管显示+、-、*、/(然后+、-、*、/分别用A,B,C,D来表示)。第四五个数码管显示第二位数,第六位显示等号,第七八位显示结果。

限制范围,第一个数和第二个数限制在0-30以内的数,结果的范围在0—99,将回到最初的状态(都是0).

举个列子:

假设我要计算12+13=25;首先我要按下对应键值为1的按键,这时第一个数码管显示1,然后继续按下对应键值为2的按键,这时第二个数码管显示2,然后按下键值为+号的按键,这时第三个数码管显示A,然后继续按下对应键值为1的按键,这时第四个数码管显示为1,然后继续按下对应键值为3的按键,这时第五个数码管显示为3,再次按键计算按钮,第六个数码管显示等于号,并且第78数码管显示运算结果25。

清除键可以直接清除数码管,让数码管清0。

0x02 思路

1.  初始化系统。

2.判断当前将要赋值的位选,启用对应的按键。

3.当当前位选赋值完毕后,进行下一个位选(向右)的赋值。

4.实现计算的操作和一些其他的限制。

0x03 代码

质量着实堪忧(菜鸡瑟瑟发抖)

#include <REGX52.H>
typedef unsigned char u8;
typedef unsigned int u16;

sfr P4 = 0xc0;//蓝桥杯比单纯的51多了一个p4,手动加上

sbit R1 = P3^0;
sbit R2 = P3^1;
sbit R3 = P3^2;
sbit R4 = P3^3;

sbit C4 = P3^4;
sbit C3 = P3^5;
sbit C2 = P4^2;
sbit C1 = P4^4;

unsigned char code SMC_duanxuan[]={                      
//   0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    =
    0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x48,
//black  -     H    J    K    L    N    o   P    U     t    G    Q    r   M    y
    0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
    0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46};    //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1

u8 SMC_weixuan[]={0,0,0,0,0,0,0,0};


Key_flag = 0;//状态,位选是否已被按键赋值
Key_Value = 0;
Key_count = 0;//计数器,用来表示是哪个位选
result = 0;//计算结果


//使能
void InitHc138(unsigned char n)
{
	switch (n)
	{
		case 4:
			P2 = (P2 & 0x1f) | 0x80;
		break;
		case 5:
			P2 = (P2 & 0x1f) | 0xa0;
		break;
		case 6:
			P2 = (P2 & 0x1f) | 0xc0;
		break;
		case 7:
			P2 = (P2 & 0x1f) | 0xe0;
		break;
	}
}

//延时
void DelaySMC(u16 t)
{
	while(t--);
	
}

//亮单个数码管
void SMC_Show(u8 dat, u8 poc)
{
	InitHc138(6);
	P0 = 0x01 << poc;
	InitHc138(7);
	P0 = ~dat;
}

//动态显示
void Display()
{
	SMC_Show(SMC_duanxuan[SMC_weixuan[0]], 0);
	DelaySMC(500);
	SMC_Show(SMC_duanxuan[SMC_weixuan[1]], 1);
	DelaySMC(500);
	SMC_Show(SMC_duanxuan[SMC_weixuan[2]], 2);
	DelaySMC(500);
	SMC_Show(SMC_duanxuan[SMC_weixuan[3]], 3);
	DelaySMC(500);
	SMC_Show(SMC_duanxuan[SMC_weixuan[4]], 4);
	DelaySMC(500);
	SMC_Show(SMC_duanxuan[SMC_weixuan[5]], 5);
	DelaySMC(500);
	SMC_Show(SMC_duanxuan[result / 10], 6);
	DelaySMC(500);
	SMC_Show(SMC_duanxuan[result % 10], 7);
	DelaySMC(500);
}

//出现错误时的显示和数据清除
void ERROR_Display()
{
	SMC_weixuan[0]=0;
	SMC_weixuan[1]=0;
	SMC_weixuan[2]=0;
	SMC_weixuan[3]=0;
	SMC_weixuan[4]=0;
	SMC_weixuan[5]=0;
	Key_count = 0;
	Key_flag  =0;
	Key_count = 0;
	result = 0;
	Key_flag  =0;
	Key_count = 0;
	result = 0;
}

//数字位的按键
void ScanKeyMulet_num()
{
	R1 = 0;
	R2 = R3 = R4 = 1;
	C1 = C2 = C3 = C4 = 1;
	if (C1 == 0)
	{
		Key_Value = 0;
		Key_count++;
		Key_flag = 1;
		while(C1 == 0)
		{
		Display();
		}
	}
	else if(C2 == 0)
	{
		Key_Value = 1;
		Key_count++;
		Key_flag = 1;
		while(C2 == 0)
		{
		Display();
		}
		
	}
	else if(C3 == 0)
	{
		Key_Value = 2;
		Key_count++;
		Key_flag = 1;
		while(C3 == 0)
		{
		Display();
		}
		
	}
	else if(C4 == 0)
	{
		Key_Value = 3;
		Key_count++;
		Key_flag = 1;
		while(C4 == 0)
		{
		Display();
		}
		
	}
	R2 = 0;
	R1 = R3 = R4 = 1;
	C1 = C2 = C3 = C4 = 1;
	if (C1 == 0)
	{
		Key_Value = 4;
		Key_count++;
		Key_flag = 1;
		while(C1 == 0)
		{
		Display();
		}
		
	}
	else if(C2 == 0)
	{
		Key_Value = 5;
		Key_count++;
		Key_flag = 1;
		while(C2 == 0)
		{
		Display();
		}
	
	}
	else if(C3 == 0)
	{
		Key_Value = 6;
		Key_count++;
		Key_flag = 1;
		while(C3 == 0)
		{
		Display();
		}
		
	}
	else if(C4 == 0)
	{
		Key_Value = 7;
		Key_count++;
		Key_flag = 1;
		while(C4 == 0)
		{
		Display();
		}
		
	}
	R3 = 0;
	R2 = R1 = R4 = 1;
	C1 = C2 = C3 = C4 = 1;
	if (C1 == 0)
	{
		Key_Value = 8;
		Key_count++;
		Key_flag = 1;
		while(C1 == 0)
		{
		Display();
		}
		
	}
	else if(C2 == 0)
	{
		Key_Value = 9;
		Key_count++;
		Key_flag = 1;
		while(C2 == 0)
		{
		Display();
		}
	}
	R4 = 0;
	R2 = R3 = R1 = 1;
	C1 = C2 = C3 = C4 = 1;
	if(C3 == 0)
	{
		DelaySMC(100);
		if(C3 == 0)
		{
			
			ERROR_Display();
			while(C3 == 0)
			{
				Display();
			}
		}
		
	}
	
}

//符号位的按键
void ScanKeyMulet_sym()//·ûºÅλ
{
	R3 = 0;
	R2 = R1 = R4 = 1;
	C1 = C2 = C3 = C4 = 1;
	if(C3 == 0)
	{
		Key_Value = 10;
		Key_count++;
		Key_flag = 1;
		while(C3 == 0)
		{
		Display();
		}
		
	}
	else if(C4 == 0)
	{
		Key_Value = 11;
		Key_count++;
		Key_flag = 1;
		while(C4 == 0)
		{
		Display();
		}
		
	}
	R4 = 0;
	R2 = R3 = R1 = 1;
	C1 = C2 = C3 = C4 = 1;
	if (C1 == 0)
	{
		Key_Value = 12;
		Key_count++;
		Key_flag = 1;
		while(C1 == 0)
		{
		Display();
		}
		
	}
	else if(C2 == 0)
	{
		Key_Value = 13;
		Key_count++;
		Key_flag = 1;
		while(C2 == 0)
		{
		Display();
		}
		
	}
	R4 = 0;
	R2 = R3 = R1 = 1;
	C1 = C2 = C3 = C4 = 1;
	if(C3 == 0)
	{
		DelaySMC(100);
		if(C3 == 0)
		{
			
			ERROR_Display();
			while(C3 == 0)
			{
				Display();
			}
		}
	}
}

计算位的按键
void ScanKeyMulet_cal()//¼ÆËãλ
{
	R4 = 0;
	R2 = R3 = R1 = 1;
	C1 = C2 = C3 = C4 = 1;
	if(C3 == 0)
	{
		DelaySMC(100);
		if(C3 == 0)
		{
			
			ERROR_Display();
			while(C3 == 0)
			{
				Display();
			}
		}
		
	}
	else if(C4 == 0)
	{
		Key_Value = 15;
		
		Key_count++;
		Key_flag = 1;
		while(C4 == 0)
		{
		Display();
		}
	}
}

//判断当前的位选,从而对应相对的按键显示
void Wei_sel()
{
	if(Key_count == 2)
	{
		ScanKeyMulet_sym();
	}
	else if(Key_count !=2 &&Key_count !=5)
	{
		ScanKeyMulet_num();
	}
	else if(Key_count == 5)
	{
		ScanKeyMulet_cal();
	}
}

//系统初始化
void InitSystem()
{
	InitHc138(5);
	P0 = 0x00;
	InitHc138(4);
	P0 = 0xff;
}

void main()
{	
	InitSystem();
	while(1)
	{
		Display();
		
		Wei_sel();
		if(Key_flag == 1)                    
                {                                 
			SMC_weixuan[Key_count%7 - 1]= Key_Value;    
		        Key_flag  =0;                                  
                 }
		
		
		if(Key_count == 6 && SMC_weixuan[5] == 15
			&&(SMC_weixuan[0]*10+SMC_weixuan[1])>0 && (SMC_weixuan[0]*10+SMC_weixuan[1])<30
		&&(SMC_weixuan[3]*10+SMC_weixuan[4])>0 && (SMC_weixuan[3]*10+SMC_weixuan[4])<30)
		{
			switch (SMC_weixuan[2])//计算
			{
				//¡°+¡±
				case 10:
					result=(SMC_weixuan[0]*10+SMC_weixuan[1]) +     (SMC_weixuan[3]*10+SMC_weixuan[4]);
				break;
				//"-"
				case 11:
					result=(SMC_weixuan[0]*10+SMC_weixuan[1]) - (SMC_weixuan[3]*10+SMC_weixuan[4]);
				break;
				//"*"
				case 12:
					result=(SMC_weixuan[0]*10+SMC_weixuan[1]) * (SMC_weixuan[3]*10+SMC_weixuan[4]);
				break;
				//"/"
				case 13:
					result=(SMC_weixuan[0]*10+SMC_weixuan[1]) / (SMC_weixuan[3]*10+SMC_weixuan[4]);
				break;
			}
		}
		
		if((SMC_weixuan[0]*10+SMC_weixuan[1])<0 || (SMC_weixuan[0]*10+SMC_weixuan[1])>30
		||(SMC_weixuan[3]*10+SMC_weixuan[4])<0 || (SMC_weixuan[3]*10+SMC_weixuan[4])>30
		||(result < 0) || (result >99))
		{
			
			ERROR_Display();
		}
		
	}
}

0x04 总结

  确实有些生疏了,程序比较简陋,一些代码其实还可以再封装,封装,命名不太规范,按键那块写的有些冗长。。。总之,作为“复健”确实让我意识到了自己的问题。有错误,希望路过的大佬斧正。(顺便吐槽一下,这个计算器也太low了,希望出题的学长看不到(狗头保命))。

 

 

网站文章

  • MD5算法-哈希算法

    MD5算法 哈希算法 MD5算法具有以下特点: 1、压缩性:任意长度的数据,算出的MD5值长度都是固定的。 2、容易计算:从原数据计算出MD5值很容易。 3、抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。 4、强抗碰撞:已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。 import java.security.Messa...

    2024-02-01 00:16:33
  • 基于Spring Boot的线程池监控方案

    基于Spring Boot的线程池监控方案

    前言这篇是推动大家异步编程的思想的线程池的准备篇,要做好监控,让大家使用无后顾之忧,敬畏生产。为什么需要对线程池进行监控Java线程池作为最常使用到的并发工具,相信大家都不陌生,但是你真的确定使用对了...

    2024-02-01 00:16:27
  • 简单选择排序

    选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大...

    2024-02-01 00:15:57
  • jdk8升级成jdk17报错 module java.base does not “opens java.lang“ to unnamed module @1941a8ff

    jdk8升级成jdk17报错 module java.base does not “opens java.lang“ to unnamed module @1941a8ff

    jdk8升级jdk17常见错误

    2024-02-01 00:15:48
  • 日志-apache的access_log与error_log 热门推荐

    日志-apache的access_log与error_log 热门推荐

    1. access_log 访问日志 access_log为访问日志,记录所有对apache服务器进行请求的访问,它的位置和内容由CustomLog指令控制,LogFormat指令可以用来简化该日志的内容和格式 2. error_log 错误日志 error_log为错误日志,记录下任何错误的处理请求,它的位置和内容由ErrorLog指令控制,通常服务器出现什么错误,首先对它进行查

    2024-02-01 00:15:42
  • Odrive打开报错 最新发布

    Traceback (most recent call last): File &quot;C:\Users\XLDWDS\AppData\Local\Temp\1m2eIZGTRxmt3FzYSWZ...

    2024-02-01 00:15:35
  • springboot整合minio上传文件

    springboot整合minio上传文件

    springboot整合minio上传文件

    2024-02-01 00:15:11
  • 2022年6月29日--使用C#迈出第一步--使用 C# 中的“if”、“else”和“else if”语句向代码添加决策逻辑

    C#

    2024-02-01 00:14:53
  • vue——filter过滤器

    vue——filter过滤器

    参数是10,显示是100效果如下:1、局部过滤器关键性代码2、全局过滤器附加:多个过滤器串联:{{ message | filterA | filterB }}说明:filterA被定义为接收单个参数的过滤器函数,表达式message的值将作为参数传入到函数中。然后继续调用同样被定义为接收单个参数的过滤器函数filterB,将filterA的结果传递到filterB中。...

    2024-02-01 00:14:46
  • C语言|深入浅出讲解int转换为float全过程(附2017年统考大题案例)

    C语言|深入浅出讲解int转换为float全过程(附2017年统考大题案例)

    int转换为float类型为什么会发生精度损失? 精度损失的详细过程究竟是什么样的? 什么样情况float会发生精度损失?没有弄懂2017年浮点数统考大题? 这一篇用2017年统考大题案例帮你更深的理解浮点数的存储规则。

    2024-02-01 00:14:15