藍橋杯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了,希望出題的學長看不到(狗頭保命))。

 

 

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