lcd1602 51單片機(jī)計算器 5*4鍵盤掃描,下面是制作出來的實物圖:

圖3.2 浮點(diǎn)數(shù)運(yùn)算
0.png (49.53 KB, 下載次數(shù): 99)
下載附件
2018-6-13 00:46 上傳
全部資料51hei下載地址:
計算器 5乘4.zip
(5.75 MB, 下載次數(shù): 640)
2018-6-12 15:05 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
單片機(jī)課程設(shè)計
設(shè)計課題 基于51單片機(jī)的多功能計算器設(shè)計
【摘要】 當(dāng)今社會,隨著人們物質(zhì)生活的不斷提高,電子產(chǎn)品已經(jīng)走進(jìn)了家家戶戶,無論是生活或?qū)W習(xí),還是娛樂和消遣幾乎樣樣都離不開電子產(chǎn)品,大型復(fù)雜的計算能力是人腦所不能勝任的,而且人腦比較容易出錯。計算器作為一種快速通用的計算工具方便了用戶的使用。計算器可謂是我們最親密的電子伙伴之一。本設(shè)計著重在于分析計算器設(shè)計開發(fā)過程中的環(huán)節(jié)和步驟,并從實踐經(jīng)驗出發(fā)對計算器設(shè)計做了詳細(xì)的分析和研究。
本設(shè)計是以STC89C52單片機(jī)為核心的計算器模擬系統(tǒng)設(shè)計,輸入采用5×8矩陣鍵盤,可以進(jìn)行加、減、乘、除等十幾種數(shù)字運(yùn)算,同時支持括號的嵌套使用級浮點(diǎn)數(shù)的運(yùn)算,并在LCD1602上顯示操作過程。
本次設(shè)計注重設(shè)計方法及流程,首先根據(jù)原理設(shè)計電路,利用keil編程,借助實驗開發(fā)平臺進(jìn)行仿真實驗,進(jìn)而利用altium designer 制作PCB,最后到焊接元器件,直至調(diào)試成功。在設(shè)計的同時,特別注重keil軟件和altium designer軟件的使用方法和技巧以及常用的LCD顯示器和矩陣鍵盤的設(shè)計和使用方法。
目錄
1 系統(tǒng)方案設(shè)計
1.1 設(shè)計目的及要求
1.1.1 設(shè)計目的
1.1.2 設(shè)計要求
1.2 方案論證及選擇
1.2.1 方案一 采用FPGA控制
1.2.2 方案二 采用STC89C52
1.2.3 方案比較及選擇
2 單元電路設(shè)計
2.1 工作原理
2.2 硬件電路設(shè)計
2.2.1 單片機(jī)電路設(shè)計
2.2.2 鍵盤模塊電路
2.2.3 蜂鳴器提示電路
2.2.4 液晶顯示電路
2.3 軟件設(shè)計
2.3.1 鍵盤掃描
2.3.2 表達(dá)式的處理
2.4 altium designer 原理圖設(shè)計及PCB制作
2.4.1 原理圖設(shè)計
2.4.2 PCB制作
2.4.3 設(shè)計結(jié)果
3系統(tǒng)測試
3.1 整數(shù)運(yùn)算
3.2 浮點(diǎn)數(shù)運(yùn)算
3.3 輸入出錯的情況
4 結(jié)論與心得體會
5 參考文獻(xiàn)
附錄1 元器件清單
附錄2 程序清單
1 系統(tǒng)方案設(shè)計
1.1 設(shè)計目的及要求
1.1.1 設(shè)計目的通過本次課題設(shè)計,應(yīng)用《單片機(jī)應(yīng)用基礎(chǔ)》、《數(shù)據(jù)結(jié)構(gòu)》等所學(xué)相關(guān)知識及查閱資料,完成實用計算器的設(shè)計,以達(dá)到理論與實踐更好的結(jié)合、進(jìn)一步提高綜合運(yùn)用所學(xué)知識和設(shè)計的能力的目的。 通過本次設(shè)計的訓(xùn)練,可以使我在基本思路和基本方法上對基于MCS-51單片機(jī)的嵌入式系統(tǒng)設(shè)計有一個比較感性的認(rèn)識,并具備一定程度的設(shè)計能力。 1.1.2 設(shè)計要求在本次課程設(shè)計中,主要完成如下方面的設(shè)計要求: 1、掌握MCS-51系列某種產(chǎn)品(例如8051)的最小電路及外圍擴(kuò)展電路的設(shè)計方法; 2、計算器能實現(xiàn)加、減、乘、除、平方、開方、N次方、開N次方、正弦函數(shù)、 余弦函數(shù)、正切函數(shù)、反正弦、反余弦、反正切、對數(shù)運(yùn)算、階乘(N<=34)、排列、 組合、累加等十九種功能。 3、支持浮點(diǎn)數(shù)運(yùn)算; 4、較為友好的界面顯示,對輸入實時顯示,對計算結(jié)果輸出顯示; 5、能夠具備比較完善的報錯系統(tǒng) 1.2 方案論證及選擇基于設(shè)計要求,笨設(shè)計考慮了兩種設(shè)計方案,他們均可以實現(xiàn)計算器的功能,但基于設(shè)計目的及微控制器的廣泛運(yùn)用,比較兩種方案的優(yōu)劣,最終選擇基于51單片機(jī)的計算器設(shè)計。 1.2.1 方案一 采用FPGA控制FPGA是一種高密度的可編程邏輯器件,自從Xilinx公司1985年推出第一片F(xiàn)PGA以來,FPGA的集成密度和性能提高很快,其集成密度最高達(dá)500萬門/片以上,系統(tǒng)性能可達(dá)200MHz。由于FPGA器件集成度高,方便易用,開發(fā)和上市周期短,在數(shù)字設(shè)計和電子生產(chǎn)中得到迅速普及和應(yīng)用,并一度在高密度的可編程邏輯器件領(lǐng)域中獨(dú)占鰲頭。 但是而基于 SRAM編程的FPGA,其編程信息需存放在外部存儲器上 ,需外部存儲器芯片 ,且使用方法復(fù)雜 ,保密性差,而其對于一個簡單的計算器而言,實用FPGA有點(diǎn)大材小用,成本太高。
1.2.2 方案二 采用STC89C52單片機(jī)是單片微型機(jī)的簡稱,故又稱為微控制器MCU(Micro Control Unit)。通常由單塊集成電路芯片組成,內(nèi)部包含有計算機(jī)的基本功能部件:中央處理器CPU,存儲器和I/O接口電路等。因此,單片機(jī)只要和適當(dāng)?shù)能浖巴獠吭O(shè)備相結(jié)合,便可成為一個單片機(jī)控制系統(tǒng)。單片機(jī)廣泛用于智能產(chǎn)品,智能儀表,測控技術(shù),智能接口等,具有操作簡單,實用方便,價格便宜等優(yōu)點(diǎn),而其中AT89S52以MCS-51為內(nèi)核,是單片機(jī)中最典型的代表,應(yīng)用于各種控制領(lǐng)域。 1.2.3 方案比較及選擇通過以上兩種方案論證和比較,從設(shè)計的實用性,方便性和成本出發(fā),選擇了以STC89C52單片機(jī)作為中央處理單元進(jìn)行計算器的設(shè)計,這樣設(shè)計能夠?qū)崿F(xiàn)對六位浮點(diǎn)數(shù)的加減和三位浮點(diǎn)數(shù)的乘除運(yùn)算。
2 單元電路設(shè)計
2.1 工作原理利用矩陣鍵盤進(jìn)行按鍵的輸入,通過對矩陣鍵盤的掃描,獲取用戶的輸入,并實時的顯示在1602液晶上,每次獲取到輸入時,根據(jù)軟件設(shè)計的相應(yīng)方法對輸入進(jìn)行處理、運(yùn)算,輸入結(jié)束后(以“=“為標(biāo)志),將最終的運(yùn)算結(jié)果輸出的液晶上。 系統(tǒng)組成及整體框圖如圖2.1所示。 圖2.1 系統(tǒng)組成及總體框圖(見附件)
2.2 硬件電路設(shè)計
2.2.1 單片機(jī)電路設(shè)計為使單片機(jī)正常工作,除電源供電部分外,還需提供晶振電路和復(fù)位電路。具體電路如下: 
圖2.2 單片機(jī)工作電路 由圖2.2可知,9腳外接的是按鍵復(fù)位電路,18,19腳外接的是晶振電路,這樣,就構(gòu)成了單片機(jī)正常工作的必備電路。同時,為使P0口正常工作,并增加其帶負(fù)載能力,P0口需接了上拉電阻。圖中EA為外部訪問允許,欲使CPU僅訪問外部程序存儲器(地址為0000H-FFFFH),EA端必須保持低電平(接地)。在這里,STC89C52單片機(jī)8k的程序存儲器已經(jīng)夠本設(shè)計使用,無需外部程序儲存器,故EA直接接高電平。
2.2.2 鍵盤模塊電路圖2.3是鍵盤電路,共20個按鍵,用來實現(xiàn)人機(jī)交互和運(yùn)算表達(dá)式的輸入,S0~S3、S5~S8、S10~S13、S15~S18共16個按鍵組成一組4*4的矩陣鍵盤,行線第一行到第四行分別接在P3.0~P3.3口,列線第一列到第四列分別接在P3.4~P3.7口,這樣P3口就完成了對4*4的矩陣鍵盤的接線。同時,注意到按鍵數(shù)量還達(dá)不到要求,故增加了四個獨(dú)立按鍵S4,S9,S14,S19。他們依次接在P20~P23口。可見,矩陣鍵盤相對來講更節(jié)省I/O口,但本著學(xué)習(xí)的目的,加之本設(shè)計并不需要太多的I/O口,故為充分學(xué)習(xí)和利用資源,在這里也設(shè)計了4個這樣的獨(dú)立按鍵。 
圖2.3 鍵盤模塊電路 2.2.3 蜂鳴器提示電路蜂鳴器主要用于按鍵時發(fā)出聲音,提示當(dāng)前的按鍵操作,電路如圖2.5所示,三極管主要用于驅(qū)動蜂鳴器,因為單片機(jī)I/O的驅(qū)動能力有限。同時單片機(jī)I/O口還在這里還起到開關(guān)作用,為‘0’時打開蜂鳴器通道,使蜂鳴器發(fā)聲。 
圖2.4 蜂鳴器提示電路 2.2.4 液晶顯示電路LCD也是本次設(shè)計的重要組成部分之一,主要用于顯示輸入和輸出。電路如圖2.5所示,LCD數(shù)據(jù)端與單片機(jī)P0口相連,控制端與P24~P26連接,電位器用于調(diào)節(jié)對比度。

圖2.5 LCD顯示電路
至此,整個電容測量儀的硬件設(shè)計部分就基本設(shè)計完成,接下來,需要的就是與之相匹配的軟件支持了。
2.3 軟件設(shè)計軟件編程平臺選擇最常用的keil軟件。由于該程序并未涉及到底層的驅(qū)動問題,因此選擇方便快捷的C語言編程。在編程中,將該程序分為四個模塊:延時模塊、1602顯示模塊、用于處理計算表達(dá)式的對戰(zhàn)模塊及主函數(shù)模塊。采用模塊化設(shè)計,方便調(diào)試與理解。具體程序見附錄二。在這里重點(diǎn)介紹軟件核心的表達(dá)式處理程序算法。 2.3.1 鍵盤掃描獨(dú)立鍵盤很好實現(xiàn),只需不停的檢測即可,出現(xiàn)低電平即出現(xiàn)按鍵,在經(jīng)過一定的延時消抖,再確認(rèn)判斷即可。 矩陣鍵盤掃描程序,首先讀出P3的低四位,然后讀出P3口的高四位。然后確定鍵值并顯示緩存,最終將按鍵的值通過一個預(yù)先定義好的數(shù)組轉(zhuǎn)換為相應(yīng)的ASCII碼值送給LCD顯示和與表達(dá)式相應(yīng)的堆棧進(jìn)行處理,讀鍵程序使用的是反轉(zhuǎn)法讀鍵,不管鍵盤矩陣的規(guī)模大小,均進(jìn)行兩次讀鍵。第一次所有行線均輸出高電平,從P3口的值讀入鍵盤信息(行信息);第二次所有列線均輸出高電平,從P3口的值讀入鍵盤信息(列信息)。 2.3.2 表達(dá)式的處理表達(dá)式包含加、減、乘、除、括號等,必須按照相應(yīng)的優(yōu)先級運(yùn)算,才可能得出正確的結(jié)果。在這兒采用棧結(jié)構(gòu),可以有效的進(jìn)行表達(dá)式的處理。 棧結(jié)構(gòu)具有“后進(jìn)先出”的固有屬性,借助這個屬性我們可以隨時對剛輸入的元素進(jìn)行操作,從而實現(xiàn)邊輸入邊計算。 為了實現(xiàn)算符優(yōu)先算法。可以使用兩個工作棧。一個稱為OPTR,用以寄存運(yùn)算符,另一個稱做OPND,用以寄存操作數(shù)或運(yùn)算結(jié)果。 1.首先置操作數(shù)棧為空棧,表達(dá)式起始符”#”為運(yùn)算符棧的棧底元素; 2.依次讀入表達(dá)式,若是操作符即進(jìn)OPND棧,若是運(yùn)算符則和OPTR棧的棧頂運(yùn)算符比較優(yōu)先權(quán)后作相應(yīng)的操作,直至整個表達(dá)式求值完畢(即OPTR棧的棧頂元素和當(dāng)前讀入的字符均為”#”)。 在這里,相應(yīng)的處理指的是,如果當(dāng)前符號的優(yōu)先級比棧頂優(yōu)先級低,則將該符號繼續(xù)壓入堆棧,不做其它操作;如果當(dāng)前符號的優(yōu)先級比棧頂優(yōu)先級高,則依次取出操作數(shù)棧的棧頂兩個數(shù)據(jù)和符號棧的棧頂符號進(jìn)行這兩個數(shù)的運(yùn)算,運(yùn)算結(jié)果數(shù)據(jù)再壓入操作數(shù)棧中。若優(yōu)先級相等,則彈出符號棧棧頂符號。算符間的優(yōu)先關(guān)系如下(‘#‘表示開始和結(jié)束): 表2.1 運(yùn)算符優(yōu)先級表
2.4 altium designer 原理圖設(shè)計及PCB制作
2.4.1 原理圖設(shè)計
圖2.6 原理圖設(shè)計(1)——單片機(jī)部分 
圖2.7 原理圖設(shè)計(2)——鍵盤、蜂鳴器部分 2.4.2 PCB制作
圖2.8 PCB設(shè)計(1)——單片機(jī)部分 
圖2.9 原理圖設(shè)計(2)——鍵盤、蜂鳴器部分 注:在此并沒有布雙層板,紅色的線僅僅只是為了標(biāo)志出跳線或者本質(zhì)上實物已經(jīng)連接上了。
2.4.3 設(shè)計結(jié)果

圖2.10 設(shè)計結(jié)果實物圖
如圖所示,各個按鍵功能如圖中文字說明,電源為5V直流電源。
3系統(tǒng)測試
測試主要測試其運(yùn)算是否正確,及檢錯能力。 3.1 整數(shù)運(yùn)算在此以整數(shù)運(yùn)算為例,介紹計算器的使用方法即流程。首先打開電源,看到LCD打開顯示,說明運(yùn)行正常,接著,輸入表達(dá)式:12*(56+23)*2,其結(jié)果本身應(yīng)為1896。 輸入結(jié)束后,點(diǎn)“=”按鍵,即可在第二行顯示出運(yùn)算結(jié)果,由圖可見運(yùn)算完全正確。在使用時,可以通過聲音開關(guān)按鈕控制按鍵音的打開和關(guān)閉,在LCD上也有顯示,如果再第二行第一個位置沒有顯示,則沒有打開聲音,可以通過按鈕打開。若有顯示,則聲音已經(jīng)打開,可以通過按鈕關(guān)閉聲音。如圖3.1所示,此時已經(jīng)打開聲音。 
圖3.1 整數(shù)運(yùn)算
3.2 浮點(diǎn)數(shù)運(yùn)算
由圖可以看出,可以進(jìn)行浮點(diǎn)數(shù)運(yùn)算,還可以從第二行第一個字符,蜂鳴器處于關(guān)閉狀態(tài)。
3.3 輸入出錯的情況
輸入一個錯誤的表達(dá)式,如圖3.3所示。 
圖3.3 輸入錯誤的情況下
再按“=”號,將會出現(xiàn)出錯畫面。如圖3.4所示。 
圖3.4 輸入錯誤的顯示
由以上測試可知,整個設(shè)計運(yùn)行正常,能夠正確的進(jìn)行運(yùn)算和出錯提示。由此可得,整個設(shè)計是成功的。
4 結(jié)論與心得體會
總之,通過一系列仿真和設(shè)計,基于單片機(jī)的計算器設(shè)計還是比較成功的做出來了。一路下來還是比較坎坷,從原理到實物,從調(diào)試到調(diào)試成功,遇到了很多問題,特別是在軟件編程時,開始以為既然單片機(jī)具有數(shù)據(jù)處理與運(yùn)算的能力,那么用它來做一個計算器應(yīng)該很簡單了,可是,后面實際操作才知道,當(dāng)計算表達(dá)式時,優(yōu)先級問題非常重要,一開始用了很多if語句來實現(xiàn),程序繁瑣復(fù)雜,且效果不是很好,很容易出錯,最后通過查閱相關(guān)資料,了解到利用數(shù)據(jù)結(jié)構(gòu)中棧的思想來解決這一問題就很方便。但在實際寫程序時也遇到了很多問題,但最終還是克服難關(guān),將整個軟件比較完善的實現(xiàn)了。 在硬件的原理圖及PCB設(shè)計中,也遇到了很多問題,先做模塊后做主板,導(dǎo)致我后面的布線就很麻煩,這也教會了我一些經(jīng)驗,在PCB分模塊設(shè)計中,模塊與模塊之間的連接也是必須考慮到的,從左端連接還是從右端連接,都直接影響到整個PCB板的設(shè)計。 總之,通過這次設(shè)計也收獲了很多,知識層面上,學(xué)得了很多新知識,解決問題的新方法,思考問題的新方向。實踐方面,提高了動手能力,提高了解決實際問題的能力等等。在思想上,更加明白的堅持不懈的重要性,學(xué)習(xí)探索的重要性,實踐動手的重要性。
5 參考文獻(xiàn)
【1】 《單片機(jī)基礎(chǔ)》第三版 李廣弟 朱月秀 冷祖祁 編著 北京航天大學(xué)出版社,2007 【2】 《數(shù)據(jù)結(jié)構(gòu)》嚴(yán)蔚敏 編著 清華大學(xué)出版社
附錄1 元器件清單
(1)晶振12M一個 (2)stc89c52芯片一片 (3)30pf 2個;10uf 1個; (4)40腳活動底座一個 (5)LCD液晶一個 (6)按鍵21個 (7)發(fā)光二極管1個 (8)9引腳排阻 1個 (9)680Ω 1個;10k 2個;1k 1個;10k滑動變阻器 1個; 10Ω 1個; (10) 開關(guān)1個 (11) 5V有源蜂鳴器1個 (12) 三極管S8550一個 (13)排針若干,杜邦線若干
單片機(jī)源程序如下:
- #include <REGX51.H>
- #include<intrins.h>
- #include<stdio.h>
- #include<string.h>
- #include<math.h>
- sbit RS = P2^5;
- sbit RW = P2^6;
- sbit E = P2^7;
- #define Data P0//數(shù)據(jù)端口
- //全局變量
- float num1;//第一操作數(shù)num1 (初始為零)
- float num2;//第二操作數(shù)num2 (初始為零)
- char yun_flag='+';//運(yùn)算符號 yun_flag (默認(rèn)為+ )
- char key_last;//上次按鍵狀態(tài)標(biāo)志 key_last
- char sqrt_flag;//開方鍵按下標(biāo)志 sqrt_flag
- unsigned long pos_flag=1;//小數(shù)位權(quán)pos_flag (默認(rèn)為1)
- char neg_flag;//正負(fù)標(biāo)志 neg_flag
- char data c_num1[15]=" ";//c_num1 字符型第一操作數(shù) (數(shù)組不定義大小與其他變量沖突)
- char data c_num2[15]=" ";//c_num2 字符型第二操作數(shù)
- char error;//運(yùn)算法則錯誤;
- char len;//小數(shù)點(diǎn)后位數(shù)
- /* 微秒延時函數(shù) */
- /******************************************************************/
- void DelayUs(unsigned char us)//delay us
- {
- unsigned char uscnt;
- uscnt=us>>1; /*12MHz頻率*/
- while(--uscnt);
- }
- /******************************************************************/
- /* 毫秒函數(shù)聲明 */
- /******************************************************************/
- void DelayMs(unsigned char ms)
- {
- while(--ms)
- {
- DelayUs(250);
- DelayUs(250);
- DelayUs(250);
- DelayUs(250);
- }
- }
- /******************************************************************/
- /* 寫入命令函數(shù) */
- /******************************************************************/
- void WriteCommand(unsigned char c)
- {
- DelayMs(5);//操作前短暫延時,保證信號穩(wěn)定
- E=0;
- RS=0;
- RW=0;
- _nop_();
- E=1;
- Data=c;
- E=0;
- }
- /******************************************************************/
- /* 寫入數(shù)據(jù)函數(shù) */
- /******************************************************************/
- void WriteData(unsigned char c)
- {
- DelayMs(5); //操作前短暫延時,保證信號穩(wěn)定
- E=0;
- RS=1;
- RW=0;
- _nop_();
- E=1;
- Data=c;
- E=0;
- RS=0;
- }
- /******************************************************************/
- /* 寫入字節(jié)函數(shù) */
- /******************************************************************/
- void ShowChar(unsigned char pos,unsigned char c)
- {
- unsigned char p;
- if (pos>=0x10)
- p=pos+0xb0; //是第二行則命令代碼高4位為0xc
- else
- p=pos+0x80; //是第二行則命令代碼高4位為0x8
- WriteCommand (p);//寫命令
- WriteData (c); //寫數(shù)據(jù)
- }
- /******************************************************************/
- /* 寫入字符串函數(shù) */
- /******************************************************************/
- void ShowString (unsigned char line,char *ptr)
- {
- unsigned char l,i;
- l=line<<4;
- for (i=0;*(ptr+i)!='\0';i++)
- ShowChar (l++,*(ptr+i));//循環(huán)顯示16個字符
- }
- /******************************************************************/
- /* 初始化函數(shù) */
- /******************************************************************/
- void InitLcd()
- {
- DelayMs(15);
- WriteCommand(0x38); //display mode
- WriteCommand(0x38); //display mode
- WriteCommand(0x38); //display mode
- WriteCommand(0x06); //顯示光標(biāo)移動位置
- WriteCommand(0x0c); //顯示開及光標(biāo)設(shè)置
- WriteCommand(0x01); //顯示清屏
- }
- /*************按鍵掃描****************************/
- char scan()
- {
- char h_data,l_data,i,key_num;
- P2=P2&0XE0;//P2低5位送0
- P1=P1|0X0F;//P1低4位送1
- while((P1|0xf0)==0xff)//判斷P1低4位是否全為1
- {
- while((P1|0xf0)==0xff);
- DelayMs(10);//延時10ms
- }
- l_data=~(P1|0xf0);//記入列標(biāo)志
- P2=P2|0X1F;//P2低五位送1
- P1=P1&0XF0;//P1低四位送0
- h_data=~(P2|0xe0);//記入行標(biāo)志
- for(i=0;i<=4;i++)//計算行號(0~4)
- {
- if(h_data==1)break;
- h_data=h_data>>1;
- }
- h_data=i;//行號
- for(i=1;i<=4;i++)//計算列號(1~4)
- {
- if(l_data==1)break;
- l_data=l_data>>1;
- }
- l_data=i;//列號
- key_num=h_data*4+l_data;
-
- P2=P2&0XE0;//P2低5位送0
- P1=P1|0X0F;//P1低4位送1
- while((P1|0xf0)!=0xff)//判斷P1低4位是否全為1
- {
- while((P1|0xf0)!=0xff);
- DelayMs(10);//延時10ms
- }
- return key_num;
- }
- void float_to_char(float a,char* p)
- {
- char i,flag,length;
- flag=0;
- sprintf(p,"%f",a);
- length=strlen (p);
- for(i=0;i<length;i++)
- {
- if(*(p+i)=='.')flag=1;
- }
- if(flag==1)
- for(i=length-1;i>=0;i--)
- {
- if(*(p+i)=='.'){*(p+i)='\0';break;}
- if(*(p+i)!='0'){*(p+i+1)='\0';break;}
- }
- }
- /**********************更新液晶*************************/
- void refresh()//更新液晶
- {
- char length,i,j;
- char dot;
- dot=0;
-
- float_to_char(num2,c_num2);//num2轉(zhuǎn)為字符型
- length=strlen(c_num2);
- for(i=0,j=0;i<length;i++)
- {
- if(c_num2[i]=='.')
- dot=1;
- if(dot==1)
- j++;
- }
- if(j<len)
- {
- if(dot==1)
- {
- for(i=length;i<(length+len-j);i++)
- {
- c_num2[i]='0';
-
- }
- c_num2[i]='\0';
- }
- else
- {
-
- c_num2[length]='.';
- if(len-j>1)
- {
- for(i=length+1;i<(length+len-j);i++)
- c_num2[i]='0';
- }
- c_num2[length+len-j]='\0';
- }
- }
- if(neg_flag==1)//'+/-'按下首位加‘-’
- {
- length=strlen(c_num2);//計算c_num2長度
- for(i=length-1;i>=0;i--)
- {
- c_num2[i+1]=c_num2[i];
- }
- c_num2[length+1]='\0';
- c_num2[0]='-';
- }
-
- if(sqrt_flag==1)
- {
- length=strlen(c_num2);//計算c_num2長度
- for(i=length-1;i>=0;i--)
- {
- c_num2[i+1]=c_num2[i];
- }
- c_num2[length+1]='\0';
- c_num2[0]=0xe8;//字符根號
- }
-
-
- if(error==0)
- {
- float_to_char(num1,c_num1);//num1轉(zhuǎn)為字符型
- WriteCommand(0x01); //顯示清屏
- ShowString(0,c_num1);
- ShowString(1,c_num2);
- ShowChar(15,yun_flag);
- }else
- {
- WriteCommand(0x01); //顯示清屏
- ShowString(0,"error!!!");
- }
- }
- //鍵值處理
- void operation1(char keynum)//按下 ’+、-、*、/處理
- {
- if(key_last==1)//上次按鍵為 數(shù)字、小數(shù)點(diǎn)、+/-、sqrt
- {
- if(neg_flag==1)num2=-num2;//'+/-'按下
- if(sqrt_flag==1)//sqrt按下
- {
- if(num2>=0)
- num2=sqrt(num2);
- else
- error=1;
- }
- if(yun_flag=='+')num1=num1+num2; //按下的是‘+’
- if(yun_flag=='-')num1=num1-num2;//按下的是‘-’
- if(yun_flag=='*')num1=num1*num2;//按下的是‘*’
- if(yun_flag=='/')//按下的是‘/’
- {
- if(num2!=0)
- num1=num1/num2;
- else
- error=1;
- }
- num2=0;//num2清零
- sqrt_flag=0;//sqrt_flag清零
- neg_flag=0;//neg_flag清零
- pos_flag=1;//pos_flag回1
- }
- if(keynum==4)yun_flag='+';//yun_flag更新
- if(keynum==8)yun_flag='-';
- if(keynum==12)yun_flag='*';
- if(keynum==16)yun_flag='/';
- len=0;
- key_last=0;//key_last更新
- refresh();
- }
- //////////////////////////////////////////////////////
- void operation2(char keynum)//輸入數(shù)字
- {
- float Data1;
-
- if(keynum==1)Data1=7;//分析輸入數(shù)字
- if(keynum==2)Data1=8;
- if(keynum==3)Data1=9;
- if(keynum==5)Data1=4;
- if(keynum==6)Data1=5;
- if(keynum==7)Data1=6;
- if(keynum==9)Data1=1;
- if(keynum==10)Data1=2;
- if(keynum==11)Data1=3;
- if(keynum==13)Data1=0;
- if(pos_flag==1)//更新num2
- num2=num2*10+Data1;
- else
- {
- num2=num2+(Data1/pos_flag);
- pos_flag=pos_flag*10;
- len++;
- }
- key_last=1;//更新key_last
- refresh();
- }
- ////////////////////////////////////////////////////////////
- void operation3()//輸入小數(shù)點(diǎn)
- {
- if(pos_flag==1)//首次出現(xiàn)小數(shù)點(diǎn)
- {
- pos_flag=pos_flag*10;//小數(shù)位權(quán)*10
- len++;
- }
- key_last=1;//更新key_last
- refresh();//更新液晶
- }
- /////////////////////////////////////////////////////
- void operation4()//輸入'='
- {
- if(neg_flag==1)num2=-num2;//'+/-'按下
- if(sqrt_flag==1)//sqrt按下
- {
- if(num2>=0)
- num2=sqrt(num2);
- else
- error=1;
- }
- if(yun_flag=='+')num1=num1+num2; //按下的是‘+’
- if(yun_flag=='-')num1=num1-num2;//按下的是‘-’
- if(yun_flag=='*')num1=num1*num2;//按下的是‘*’
- if(yun_flag=='/')//按下的是‘/’
- {
- if(num2!=0)
- num1=num1/num2;
- else
- error=1;
- }
- num2=0;//num2清零
- sqrt_flag=0;//sqrt_flag清零
- neg_flag=0;//neg_flag清零
- pos_flag=1;//pos_flag回1
- yun_flag='+';//yun_flag更新
- len=0;
- key_last=0;//key_last更新
- refresh();
- }
- ////////////////////////////////////////////////////
- void operation5()//輸入clear all
- {
- num1=0;// num1清零
- num2=0;//num2清零
- sqrt_flag=0;//清sqrt_flag
- neg_flag=0;// 清neg_flag
- pos_flag=1;// Pos_flag=1
- yun_flag='+';// yun_flag(為'+')
- error=0;//清error
- len=0;
- key_last=0;//更新key_flag
- refresh();//更新液晶
- }
- ///////////////////////////////////////////////////////
- void operation6()//輸入'C'
- {
- num2=0;//num2清零
- sqrt_flag=0;//清sqrt_flag
- neg_flag=0;//清neg_flag
- pos_flag=1;//pos_flag=1
- len=0;
- key_last=0;//key_last
- refresh();//更新液晶
- }
- ////////////////////////////////////////////////////////////
- void operation7()//輸入'+/-'
- {
- if(neg_flag==0)//neg_flag反轉(zhuǎn)
- neg_flag=1;
- else neg_flag=0;
- key_last=1;//key_last
- refresh();// 更新液晶
- }
- /////////////////////////////////////////////////////////////
- void operation8()//輸入'sqrt'
- {
- if(sqrt_flag==0)//sqrt_flag反轉(zhuǎn)
- sqrt_flag=1;
- else sqrt_flag=0;
- key_last=1;//更新key_last
- refresh();//更新液晶
- }
- //鍵值分析
- void key(char keynum)
- {
- switch(keynum)
- {
- case 4 :
- case 8 :
- case 12:
- case 16://+、-、*、/
- {
- if(error==0)
- operation1(keynum);
- break;}
-
- case 1 : //數(shù)字7
- case 2 : //數(shù)字8
- case 3 : //數(shù)字9
- case 5 : //數(shù)字4
- case 6 : //數(shù)字5
- case 7 : //數(shù)字6
- case 9 : //數(shù)字1
- case 10 : //數(shù)字2
- case 11 : //數(shù)字3
- case 13 : //數(shù)字0
- {
- if(error==0)
- operation2(keynum);
- …………
- …………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復(fù)制代碼
|