51基于OLED的高精度计算器设计
首先,第一次發(fā)帖,請多多包含,有不妥的地方請指正。
51基于OLED顯示的高精度計算? 器設(shè)計
這個是我一個實訓(xùn)課作業(yè),我選的是矩陣鍵盤的應(yīng)用最后選了計算器。然后有要求精度至少達到小數(shù)點后6位(因為int型最多可以到小數(shù)點后5位,老師為了給我們增加難度!),且不使用浮點型(我用的long int 占4個Byte范圍0~+4 294 967 295),要求計算器有刪除,撤銷刪除和清除等功能按鍵。并且要通過OLED顯示實時操作。
首先要用OLED,IIC協(xié)議必不可少,我也是邊學(xué)邊做,這里推薦看其他大佬的講解(很詳細的,侵刪)IIC原理超詳細講解---值得一看_Z小旋-CSDN博客_iic原理
OLED驅(qū)動程序商家一般都給了,但是老師還是建議我們寫一寫,因為我們專業(yè)就是電子專業(yè),本來就是做電路設(shè)計,看時序。這里也不詳講,放一張ssd1306的命令圖自己去參透吧!
?矩陣鍵盤:
這個應(yīng)該不陌生吧,采用的4x4矩陣的按鍵,按鍵對應(yīng)值如圖
#include<reg52.h> //包含頭文件,一般情況不需要改動,頭文件包含特殊功能寄存器的定義 #include"keyboard.h" #include"delay.h"#define KeyPort P2/*------------------------------------------------ 按鍵掃描函數(shù),返回掃描鍵值 ------------------------------------------------*/ unsigned char KeyScan(void) //鍵盤掃描函數(shù),使用行列反轉(zhuǎn)掃描法 {unsigned char cord_h,cord_l;//行列值中間變量KeyPort=0x0f; //行線輸出全為0cord_h=KeyPort&0x0f; //讀入列線值if(cord_h!=0x0f) //先檢測有無按鍵按下{DelayMs(10); //去抖if((KeyPort&0x0f)!=0x0f){cord_h=KeyPort&0x0f; //讀入列線值KeyPort=cord_h|0xf0; //輸出當(dāng)前列線值cord_l=KeyPort&0xf0; //讀入行線值while((KeyPort&0xf0)!=0xf0);//等待松開并輸出return(cord_h+cord_l);//鍵盤最后組合碼值}}return(0xff); //返回該值 } /*------------------------------------------------按鍵值處理函數(shù),返回掃鍵值可以根據(jù)需要改變返回值| 1 | 2 | 3 | + | | 4 | 5 | 6 | - | | 7 | 8 | 9 | * | | 0 | . | = | / | ------------------------------------------------*/ unsigned char KeyPro(void) {switch(KeyScan()){case 0x7e:return '1';break;//0 按下相應(yīng)的鍵顯示相對應(yīng)的碼值case 0x7d:return '2';break;//1case 0x7b:return '3';break;//2case 0x77:return '+';break;//3case 0xbe:return '4';break;//4case 0xbd:return '5';break;//5case 0xbb:return '6';break;//6case 0xb7:return '-';break;//7case 0xde:return '7';break;//8case 0xdd:return '8';break;//9case 0xdb:return '9';break;//acase 0xd7:return 'x';break;//bcase 0xee:return '0';break;//ccase 0xed:return '.';break;//dcase 0xeb:return '=';break;//ecase 0xe7:return '/';break;//fdefault:return 0xff;break;} }重點來了,本次主講計算器常見加減乘除的思想
加法:
主要就是考慮小數(shù)部分,主要是將小數(shù)位數(shù)對齊。例如 a=4.52? b=8.9? 我們在輸入的時候只會記錄小數(shù)點位置,并不會在存在臨時數(shù)組內(nèi)?。所以取的時候直接取的 452? 和??89 ,但是會記錄擴大的倍數(shù),比如a擴大了100倍,b擴大了10倍。這是我們要將兩個數(shù)的小數(shù)位對其只需做
?a*(100/100)+b*(100/10)? ?即? 452+890=1342? ,之所以用100來除以100和10是因為100是這兩個數(shù)擴大倍數(shù)的最小公倍數(shù)。目的就是為了對齊小數(shù)位置。
//先將a,b乘以最小取整公倍數(shù),即a,b對其,Rsulat_z存整數(shù)部分,Rsulat_fp存小數(shù)部分 case '+': Resulat_z=(a*(sign_fp/fp_a) + b*(sign_fp/fp_b))/sign_fp; Resulat_fp=(a*(sign_fp/fp_a) + b*(sign_fp/fp_b))%sign_fp;break; //fp_a和fp_b分別存放a,b擴大了多少倍減法:
常見得需要考慮負數(shù)情況,負數(shù)我們就用b-a(原則就是大減小),不過這樣還得考慮小數(shù)部分問題。比如當(dāng)減數(shù)的整數(shù)部分小于被減數(shù),而小數(shù)部分卻大于被減數(shù)。直接用b-a的話小數(shù)部分就會出問題,因此在小數(shù)部分還得做一次大小的判斷。
case '-': //sign_fp存放的是小數(shù)位多的 那個數(shù)擴大的倍數(shù) fp_a、fp_b分別存放a、b擴大的倍數(shù) if(a*(sign_fp/fp_a) < b*(sign_fp/fp_b)) //判斷a,b大小{ // Resulat_z取結(jié)果的整數(shù)部分,_fp取小數(shù)部分Resulat_z=(b*(sign_fp/fp_b)-a*(sign_fp/fp_a))/sign_fp;if(((a*(sign_fp/fp_a))%sign_fp) > (b*(sign_fp/fp_b)))//判斷a , b的小數(shù)大小{Resulat_fp=(((a*(sign_fp/fp_a))%sign_fp) - (b*(sign_fp/fp_b))%sign_fp)%sign_fp;}else{Resulat_fp=((b*(sign_fp/fp_b))%sign_fp - (a*(sign_fp/fp_a))%sign_fp);OLED_ShowChar((lessk_Resulat+1)*8,OLED_Show_H+2,'-',16);//顯示一個負號lessk_Resulat++;//光標(biāo)+}}else{ Resulat_z=(a*(sign_fp/fp_a) - b*(sign_fp/fp_b))/sign_fp;Resulat_fp=(a*(sign_fp/fp_a) - b*(sign_fp/fp_b))%sign_fp;}break;乘法:
乘法最簡單,直接相乘,然后對這? 兩個數(shù)擴大倍數(shù)之積? 取整取余即可
//a,b取的時候已經(jīng)取整了,直接運算后對公倍數(shù)取整取余即可 case 'x': Resulat_z=(a * b)/(fp_a*fp_b); Resulat_fp=(a * b)%(fp_a*fp_b);break;除法:
首先整數(shù)相除,考慮除不盡得情況,整數(shù)可直接取 a/b,小數(shù)先取a%b,之后擴大10的6次方倍再除b? 即:((a%b)*1000000)/b(精確到小數(shù)點后6位)。
這里要做一個判斷,若除數(shù)小于被除數(shù),結(jié)果直接就取小數(shù)部分即可。
帶小數(shù)的除法:思路也是一樣的,先擴大,把兩個數(shù)的小數(shù)位對齊。例 :98.25? ?/? ?65.234??
先乘以最小公倍數(shù)1000(不知道這樣說有沒有問題),處理成 98250? /? 65234剩余步驟和上面一樣
//除法考慮除不盡情況,小數(shù)部分算法即將a%b后擴大百萬倍在除b,精度即可達到小數(shù)點后6位 case '/': if(a*(sign_fp/fp_a) > b*(sign_fp/fp_b)){Resulat_z=(a*(sign_fp/fp_a)) / (b*(sign_fp/fp_b)) ; Resulat_fp=((a*(sign_fp/fp_a) % b*(sign_fp/fp_b))*1000000)/b;}else {div_x=(a*(sign_fp/fp_a))*1000000/(b*(sign_fp/fp_b));}break;結(jié)果
?總結(jié):
????????第一次寫,瞎寫,主要是分享一下心得,也不知有沒有人愿意看兩眼。計算器的話,主要就是精度,然后小數(shù)運算。涉及到小數(shù)就一個原則,小數(shù)對齊后再運算。其實也大可直接用double來做,可能就沒有太多數(shù)據(jù)處理的步驟。但是? 老師規(guī)定了用整型!
吐槽一下,其實本來是想做《簡易計算器》,結(jié)果老師說不行,還夸我真會給自己省事^_^......!
工程源碼即仿真:鏈接:https://pan.baidu.com/s/1aybJBOirx-WRb1bFwLkMsw?
?????????????????????????????提取碼:brdn
總結(jié)
以上是生活随笔為你收集整理的51基于OLED的高精度计算器设计的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: EfficientNet-V2 论文以及
- 下一篇: Quick BI简要使用