日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

51基于OLED的高精度计算器设计

發(fā)布時(shí)間:2024/1/1 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 51基于OLED的高精度计算器设计 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

首先,第一次發(fā)帖,請(qǐng)多多包含,有不妥的地方請(qǐng)指正。

51基于OLED顯示的高精度計(jì)算? 器設(shè)計(jì)

這個(gè)是我一個(gè)實(shí)訓(xùn)課作業(yè),我選的是矩陣鍵盤(pán)的應(yīng)用最后選了計(jì)算器。然后有要求精度至少達(dá)到小數(shù)點(diǎn)后6位(因?yàn)閕nt型最多可以到小數(shù)點(diǎn)后5位,老師為了給我們?cè)黾与y度!),且不使用浮點(diǎn)型(我用的long int 占4個(gè)Byte范圍0~+4 294 967 295),要求計(jì)算器有刪除撤銷刪除清除等功能按鍵。并且要通過(guò)OLED顯示實(shí)時(shí)操作

首先要用OLED,IIC協(xié)議必不可少,我也是邊學(xué)邊做,這里推薦看其他大佬的講解(很詳細(xì)的,侵刪)IIC原理超詳細(xì)講解---值得一看_Z小旋-CSDN博客_iic原理

OLED驅(qū)動(dòng)程序商家一般都給了,但是老師還是建議我們寫(xiě)一寫(xiě),因?yàn)槲覀儗I(yè)就是電子專業(yè),本來(lái)就是做電路設(shè)計(jì),看時(shí)序。這里也不詳講,放一張ssd1306的命令圖自己去參透吧!

?矩陣鍵盤(pán):

這個(gè)應(yīng)該不陌生吧,采用的4x4矩陣的按鍵,按鍵對(duì)應(yīng)值如圖

#include<reg52.h> //包含頭文件,一般情況不需要改動(dòng),頭文件包含特殊功能寄存器的定義 #include"keyboard.h" #include"delay.h"#define KeyPort P2/*------------------------------------------------ 按鍵掃描函數(shù),返回掃描鍵值 ------------------------------------------------*/ unsigned char KeyScan(void) //鍵盤(pán)掃描函數(shù),使用行列反轉(zhuǎn)掃描法 {unsigned char cord_h,cord_l;//行列值中間變量KeyPort=0x0f; //行線輸出全為0cord_h=KeyPort&0x0f; //讀入列線值if(cord_h!=0x0f) //先檢測(cè)有無(wú)按鍵按下{DelayMs(10); //去抖if((KeyPort&0x0f)!=0x0f){cord_h=KeyPort&0x0f; //讀入列線值KeyPort=cord_h|0xf0; //輸出當(dāng)前列線值cord_l=KeyPort&0xf0; //讀入行線值while((KeyPort&0xf0)!=0xf0);//等待松開(kāi)并輸出return(cord_h+cord_l);//鍵盤(pán)最后組合碼值}}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)的鍵顯示相對(duì)應(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;} }

重點(diǎn)來(lái)了,本次主講計(jì)算器常見(jiàn)加減乘除的思想

加法:

主要就是考慮小數(shù)部分,主要是將小數(shù)位數(shù)對(duì)齊。例如 a=4.52? b=8.9? 我們?cè)谳斎氲臅r(shí)候只會(huì)記錄小數(shù)點(diǎn)位置,并不會(huì)在存在臨時(shí)數(shù)組內(nèi)?。所以取的時(shí)候直接取的 452? 和??89 ,但是會(huì)記錄擴(kuò)大的倍數(shù),比如a擴(kuò)大了100倍,b擴(kuò)大了10倍。這是我們要將兩個(gè)數(shù)的小數(shù)位對(duì)其只需做

?a*(100/100)+b*(100/10)? ?即? 452+890=1342? ,之所以用100來(lái)除以100和10是因?yàn)?00是這兩個(gè)數(shù)擴(kuò)大倍數(shù)的最小公倍數(shù)。目的就是為了對(duì)齊小數(shù)位置。

//先將a,b乘以最小取整公倍數(shù),即a,b對(duì)其,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擴(kuò)大了多少倍

減法:

常見(jiàn)得需要考慮負(fù)數(shù)情況,負(fù)數(shù)我們就用b-a(原則就是大減小),不過(guò)這樣還得考慮小數(shù)部分問(wèn)題。比如當(dāng)減數(shù)的整數(shù)部分小于被減數(shù),而小數(shù)部分卻大于被減數(shù)。直接用b-a的話小數(shù)部分就會(huì)出問(wèn)題,因此在小數(shù)部分還得做一次大小的判斷。

case '-': //sign_fp存放的是小數(shù)位多的 那個(gè)數(shù)擴(kuò)大的倍數(shù) fp_a、fp_b分別存放a、b擴(kuò)大的倍數(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);//顯示一個(gè)負(fù)號(hào)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;

乘法:

乘法最簡(jiǎn)單,直接相乘,然后對(duì)這? 兩個(gè)數(shù)擴(kuò)大倍數(shù)之積? 取整取余即可

//a,b取的時(shí)候已經(jīng)取整了,直接運(yùn)算后對(duì)公倍數(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,之后擴(kuò)大10的6次方倍再除b? 即:((a%b)*1000000)/b(精確到小數(shù)點(diǎn)后6位)。

這里要做一個(gè)判斷,若除數(shù)小于被除數(shù),結(jié)果直接就取小數(shù)部分即可。

帶小數(shù)的除法:思路也是一樣的,先擴(kuò)大,把兩個(gè)數(shù)的小數(shù)位對(duì)齊。例 :98.25? ?/? ?65.234??

先乘以最小公倍數(shù)1000(不知道這樣說(shuō)有沒(méi)有問(wèn)題),處理成 98250? /? 65234剩余步驟和上面一樣

//除法考慮除不盡情況,小數(shù)部分算法即將a%b后擴(kuò)大百萬(wàn)倍在除b,精度即可達(dá)到小數(shù)點(diǎn)后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é):

????????第一次寫(xiě),瞎寫(xiě),主要是分享一下心得,也不知有沒(méi)有人愿意看兩眼。計(jì)算器的話,主要就是精度,然后小數(shù)運(yùn)算。涉及到小數(shù)就一個(gè)原則,小數(shù)對(duì)齊后再運(yùn)算。其實(shí)也大可直接用double來(lái)做,可能就沒(méi)有太多數(shù)據(jù)處理的步驟。但是? 老師規(guī)定了用整型!

吐槽一下,其實(shí)本來(lái)是想做《簡(jiǎn)易計(jì)算器》,結(jié)果老師說(shuō)不行,還夸我真會(huì)給自己省事^_^......!

工程源碼即仿真:鏈接:https://pan.baidu.com/s/1aybJBOirx-WRb1bFwLkMsw?
?????????????????????????????提取碼:brdn

總結(jié)

以上是生活随笔為你收集整理的51基于OLED的高精度计算器设计的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。