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

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了,希望出题的学长看不到(狗头保命))。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章