找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 10312|回復: 2
打印 上一主題 下一主題
收起左側

基于單片機的計算器設計報告 只能計算加減乘除

[復制鏈接]
跳轉到指定樓層
樓主
ID:442355 發(fā)表于 2018-12-8 20:16 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
這是基于單片機的簡單計算器。只能計算加減乘除
目錄

1 前言
1.1 設計目的
2 方案論證              1
2.1 方案構思              1
3 系統(tǒng)硬件設計及說明              1
3.1系統(tǒng)組成及總體框圖              1
3.2元件簡介              2
3.2.1 AT89S52特點              2
3.2.2 LCD1602液晶顯示屏              4
4 設計原理分析              6
4.1  設計方案的確定              6
4.2計算器硬件方案及硬件資源分配              7
4.2.1 硬件資源分配              7
4.2.2 系統(tǒng)的硬件設計              7
4.2.3 鍵盤電路的設計              8
4.2.4 顯示電路的設計              9
5 計算器的軟件設計              10
5.1計算器的軟件規(guī)劃              10
5.2 匯編語言和C語言的特點及選擇              10
5.3 按鍵鍵掃描程序設計
5.4 算術運算程序設計              11
5.5 顯示程序設計              12
6 系統(tǒng)調試與存在的問題              14
6.1 硬件調試              14
6.2 軟件調試              14
參考文獻              15
附錄一:仿真原理圖              16
附錄二:源程序              17

1 前言
1.1 設計目的
本設計旨在進一步掌握單片機理論知識,理解嵌入式單片機系統(tǒng)的硬軟件設計,加強對實際應用系統(tǒng)設計的能力。通過本設計的學習,使我掌握單片機程序設計和微機接口應用的基本方法,并能綜合運用本科階段所學軟、硬件知識分析實際問題,提高解決畢業(yè)設計實際問題的能力,為單片機應用和開發(fā)打下良好的基礎。
1、對字符液晶顯示模塊的工作原理,如初始化、清屏、顯示、調用及外特性有較清楚的認識,并會使用LCD(液晶顯示模塊)實現(xiàn)計算結果的顯示;掌握液晶顯示模塊的驅動和編程,設計LCD和單片機的接口電路,以及利用單片機對液晶模塊的驅動和操作;
2、在充分分析內部邏輯的概念,進行軟件和調試,學會使用,并能夠以其為平臺設計出具有四則運算能力簡易計算器的硬件電路和軟件程序。
2方案論證
2.1 方案構思
采用AT89S52
單片機是單片微型機的簡稱,故又稱為微控制器MCU(Micro Control Unit)。通常由單塊集成電路芯片組成,內部包含有計算機的基本功能部件:中央處理器CPU,存儲器和I/O接口電路等。因此,單片機只要和適當?shù)能浖巴獠吭O備相結合,便可成為一個單片機控制系統(tǒng)。單片機廣泛用于智能產品,智能儀表,測控技術,智能接口等,具有操作簡單,實用方便,價格便宜等優(yōu)點,而其中AT89S52以MCS-51為內核,是單片機中最典型的代表,應用于各種控制領域。
3系統(tǒng)硬件設計及說明
3.1系統(tǒng)組成及總體框圖

圖3.1 系統(tǒng)組成及總體框圖

3.2元件簡介
3.2.1 AT89S52特點

圖3.2.1-1 單片機AT89S52

1、主要性能:
(1) ? 8031 CPU與MCS-51 兼容
  ? 8K字節(jié)可編程FLASH存儲器(壽命:1000寫/擦循環(huán))
  ? 全靜態(tài)工作:0Hz-33MHz
  ? 三級加密程序存儲器
  ? 128*8位內部RAM
  ? 32條可編程I/O線
  ? 三個16位定時器/計數(shù)器
  ? 八個中斷源
  ? 全雙工UART串行通道
? 低功耗的閑置和掉電模式
? 掉電后中斷可喚醒
? 看門狗定時器
? 雙數(shù)據(jù)指針
? 掉電標識符
? 片內振蕩器和時鐘電路
(2) 管腳說明:
  VCC:供電電壓。
GND:接地。

2、AT89S52的功能特性描述
AT89S52 是一種低功耗、高性能CMOS8位微控制器,具有 8K 在系統(tǒng)可編程Flash 存儲器。使用Atmel 公司高密度非 易失性存儲器技術制造,與工業(yè)80C51 產品指令和引腳完 全兼容。片上Flash允許程序存儲器在系統(tǒng)可編程,亦適于 常規(guī)編程器。在單芯片上,擁有靈巧的8 位CPU 和在系統(tǒng) 可編程Flash,使得AT89S52為眾多嵌入式控制應用系統(tǒng)提 供高靈活、超有效的解決方案。
AT89S52具有以下標準功能: 8k字節(jié)Flash,256字節(jié)RAM, 32 位I/O 口線,看門狗定時器,2 個數(shù)據(jù)指針,三個16 位 定時器/計數(shù)器,一個6向量2級中斷結構,全雙工串行口, 片內晶振及時鐘電路。
此外, AT89S52 可降至0Hz 靜態(tài)邏 輯操作,支持2種軟件可選擇節(jié)電模式�?臻e模式下,CPU 停止工作,允許RAM、定時器/計數(shù)器、串口、中斷繼續(xù)工 作。掉電保護方式下,RAM內容被保存,振蕩器被凍結, 單片機一切工作停止,直到下一個中斷或硬件復位為止。8 位微控制器 8K 字節(jié)在系統(tǒng)可編程 Flash。同時該芯片還具有PDIP、TQFP和PLCC等三種封裝形式,以適應不同產品的需求。

3、AT89S52引腳功能
AT89S52 單片機為40 引腳芯片見圖3.2.1-2和課本。
圖3.2.1-2 AT89S52引腳圖

3.2.2 LCD1602液晶顯示屏
1、應用簡介
模塊內部自帶字符發(fā)生存儲器(CGROM),字符有:阿拉伯數(shù)字、英文字母的大小寫、常用的符號、和日文假名等,每一個字符都有一個固定的代碼,比如大寫的英文字母“A”的代碼是(41H),顯示時模塊把代碼41H發(fā)給液晶模塊,我們就能在液晶上看到字母“A”。
1602液晶模塊內部的控制器共有11條控制指令,豐富的指令可以完成液晶的時序控制、工作方式式設置和數(shù)據(jù)顯示等。
采用的LCD1602液晶模塊是標準16針插座,接口電路如圖3.2.3所示:關于LCD1602的詳細資料見表3.2.3-1和表3.2.3-2。

圖3.2.3 LCD接口電路

表3.2.3-1 LCD1602引腳說明
第1腳
VSS為地電源
第2腳
VDD接5V正電源
第3腳
V0為液晶顯示器對比度調整端,接正電源時對比度最弱,接地電源時對比度最高,對比度過高時會產生“鬼影”,使用時可以通過一個10K的電位器調整對比度。
實際電路中采用2K電阻到地,比較理想。
第4腳
RS為寄存器選擇,高電平選擇數(shù)據(jù)寄存器、低電平選擇指令寄存器。
第5腳
RW為讀寫信號線,高電平時進行讀操作,低電平時進行寫操作。
當RS和RW共同為低電平時  (00)可以寫入指令或者顯示地址;
當RS為低電平RW為高電平時(01)可以讀入忙信號;
當RS為高電平RW為低電平時(10)可以寫入數(shù)據(jù)。
第6腳
E端為使能端,當E端由高電平跳變成低電平時,液晶模塊執(zhí)行命令。
第7~14腳
D0~D7為8位雙向數(shù)據(jù)線。
第15~16腳
背光陽極和背光陰極。


表3.2.3-2 LCD1602指令表
指令1
清顯示     指令碼01H, 光標復位到地址00H位置;
指令2
光標復位   指令碼02H, 光標返回到地址00H位置 ;
指令3
光標和顯示模式設置
I/D位 → 光標移動方向,高電平右移,低電平左移;
S  位 → 屏幕上所有文字是否左移或者右移,高電平有效,低電平無效;
指令4
顯示開關控制
D  位 → 控制整體顯示的開與關,高電平表示開顯示,低電平表示關顯示;
C  位 → 控制光標的開與關,高電平表示有光標,低電平表示無光標;   
    B  位 → 控制光標是否閃爍,高電平閃爍,低電平不閃爍 ;
指令5
光標或顯示移位
S/C位 → 高電平時移動顯示的文字,低電平時移動光標
指令6
功能命令設置
DL位---高電平時為4位數(shù)據(jù)總線,低電平時為8位總線;
N—位低電平時為單行顯示,高電平時為雙行顯示;
F—位低電平時顯示5x7的點陣字符,高電平時為5x10的點陣字符;
指令7
字符發(fā)生器RAM地址設置
指令8
DDRAM地址設置
指令9
讀忙信號和光標地址
BF位 → 為忙標志位,高電平表示忙,此時模塊不能接收命令或者數(shù)據(jù)
指令10
寫數(shù)據(jù)
指令11
讀數(shù)據(jù)

2 、LCD的特點:
(1)低壓微功耗;
(2)平板型結構;
(3)被動顯示型(無眩光,不刺激人眼,不會引起眼睛疲勞);
(4)顯示信息量大(因為像素可以做得很小);
(5)易于彩色化(在色譜上可以非常準確的復現(xiàn));
(6)無電磁輻射(對人體安全,利于信息保密);
(7)長壽命(這種器件幾乎沒有什么劣化問題,因此壽命極長,但是液晶背光壽命有限,不過背光部分可以更換)。
4 設計原理分析4.1  設計方案的確定
本設計需要使用LCD液晶顯示屏和編碼鍵盤。故選擇靜態(tài)顯示和用編碼鍵盤。使用LCD液晶顯示屏顯示運算結果。
    主程序進行初始化,其他的程序選擇模塊式的方式。首先對每個模塊進行調試, 當模塊調試成功后,逐一的加入主程序中,最后完成整個軟件部分的設計。
4.2計算器硬件方案及硬件資源分配4.2.1 硬件資源分配
主要用到的硬件:AT89S52   LCD液晶顯示屏  編碼鍵盤
硬件分配:
1、P1、P3口:做為輸出口,控制LCD液晶顯示屏顯示數(shù)據(jù)的結果。
2、P2口:做為輸入口,與鍵盤連接,實現(xiàn)數(shù)據(jù)的輸入。
3、LCD液晶顯示屏顯示輸出。
4.2.2 系統(tǒng)的硬件設計
為了更好的實現(xiàn)系統(tǒng)得功能,硬件電路的設計應該遵循以下原則:
1、優(yōu)化硬件電路
采用軟件設計與硬件設計相結合的方法;盡管采用軟件來實現(xiàn)硬件系統(tǒng)的功能時,也許響應時間會比單純使用硬件時長,而且還要占用微處理器(MCU)的時間;但是,用軟件實現(xiàn)硬件的功能可以簡化硬件結構,提高電路的可靠性。所以,在設計本系統(tǒng)得時候,在滿足可靠性和實時性的前提下,盡可能的通過軟件來實現(xiàn)硬件功能。
2、可靠性及抗干擾設計
根據(jù)可靠性設計理論,系統(tǒng)所用芯片數(shù)量越少,系統(tǒng)的平均無故障時間越長。而且,所用芯片數(shù)量越少,地址和數(shù)據(jù)總線在電路板上受干擾的可能性也就越小。因此,系統(tǒng)的設計思想是在滿足功能的情況下力爭使用較少數(shù)量的芯片。
3、靈活的功能擴展
功能擴展是否靈活是衡量一個系統(tǒng)優(yōu)劣的重要指標。一次設計往往不能完全考慮到系統(tǒng)的各個方面,系統(tǒng)需要不斷完善以及進行功能升級。進行功能擴展時,應該在原有設計的基礎上,通過修改軟件程序和少量硬件完成。對于本系統(tǒng)而言,就是要求在系統(tǒng)硬件不變的情況下,能夠通過修改軟件程序,完成功能的升級和擴展。
根據(jù)第提出的系統(tǒng)設計方案,結合以上三條原則,確定了系統(tǒng)硬件的設計。計算器主要由以下一些功能模塊構成:非編碼鍵盤模塊、LCD液晶顯示屏模塊等。
該系統(tǒng)的硬件設計采用了模塊化的設計方法。AT89S52 單片機與LCD液晶顯示屏顯示電路是整個電路的核心,它們實現(xiàn)系統(tǒng)的功能要求。
簡易計算器主要包括:鍵盤電路,顯示電路。
下圖為總體硬件結構。(如圖4.2.2 所示為整個系統(tǒng)的原理圖)
圖4.2.2 計算器原理圖
前面敘述了該系統(tǒng)的設計說明,系統(tǒng)采用了比較簡單的設計方案,所以該系統(tǒng)的硬件設計的總外圍電路不會產生過多的干擾。在下面的闡述中,對系統(tǒng)的外圍電路分別予以介紹。鍵盤部分采用編碼鍵盤,顯示部分采用LCD液晶顯示屏完全能夠很好的實現(xiàn)顯示方面的要求。
4.2.3 鍵盤電路的設計
鍵盤可分為兩類:編碼鍵盤和非編碼鍵盤。編碼鍵盤是較多按鍵(20個以上)和專用驅動芯片的組合,當按下某個按鍵時,它能夠處理按鍵抖動、連擊等問題,直接輸出按鍵的編碼,無需系統(tǒng)軟件干預。通用計算機使用的標準鍵盤就是編碼鍵盤。在智能儀器中,使用并行接口芯片8279或串行接口芯片HD7279均可以組成編碼鍵盤,同時還可以兼顧數(shù)碼管的顯示驅動,其相關的接口電路和接口軟件均可在芯片資料中得到。當系統(tǒng)功能比較復雜,按鍵數(shù)量很多時,采用編碼鍵盤可以簡化軟件設計。非編碼鍵盤成本低廉。
從成本角度出發(fā),本設計選用的是非編碼鍵盤。如圖4.2.3

圖4.2.3 編碼鍵盤電路

4.2.4 顯示電路的設計
當系統(tǒng)需要顯示少量數(shù)據(jù)時,采用LCD液晶顯示屏進行顯示是一種經濟實用的方法。P0口作為液晶顯示的數(shù)據(jù)端口,P3.5-P3.7口作為其控制端口,控制LCD液晶顯示屏顯示輸出數(shù)據(jù)。
最終電路如圖4.2.4所示:
圖4.2.4 LCD液晶顯示屏顯示

5  計算器的軟件設計5.1計算器的軟件規(guī)劃
簡易計算器的程序主要包括以下功能模塊:
1、定時查鍵模塊,分為讀鍵程序、判鍵程序段、運算操作子程序等部分;
2、基于LCD液晶顯示屏的顯示模塊;
3、主模塊,為系統(tǒng)的初始化。
5.2 匯編語言和C語言的特點及選擇

本設計是硬件電路和軟件編程相結合的設計方案,選擇合適的編程語言是一個重要的環(huán)節(jié)。在單片機的應用系統(tǒng)程序設計時,常用的是匯編語言和C語言。機硬件,程序可讀性和可移植性比較差。而C語言雖然執(zhí)行效率沒有匯編語言高,但語言簡潔,使用方便,靈活,運算豐富,表達化類型多樣化,數(shù)據(jù)結構類型豐富,具有結構化的控制語句,程序設計自由度大,有很好的可重用性,可移植性等特點。

由于現(xiàn)在單片機的發(fā)展已經達到了很高的水平,內部的各種資源相當?shù)呢S富,CPU的處理速度非常的快。用C語言來控制單片機無疑是一個理想的選擇。所以在本設計中采用C語言編寫軟件程序。主程序的設計詳見附錄三。

5.3 按鍵鍵掃描程序設

鍵掃程序的過程為:開始時,先判斷是否有鍵閉合,無鍵閉合時,返回繼續(xù)判斷,有鍵閉合時,先去抖動,然后確定是否有鍵按下,若無鍵按下,則返回繼續(xù)判斷是否有鍵閉合,若有鍵按下,則判斷鍵號,然后釋放,若釋放按鍵完畢,則返回,若沒有釋放按鍵,則返回繼續(xù)釋放。其流程圖如圖5.1所示。

圖5.1 鍵掃程序流程圖

5.4 算術運算程序設計

算術運算程序的過程為:先判斷輸入的運算符是+、-、*、/ 中的哪一個,若是+或-,則要判斷運算結果是否溢出,溢出則顯示錯誤信息,沒溢出就顯示運算結果,若是/,則要先判斷除數(shù)是否為零,為零就顯示錯誤信息,不為零則顯示運算結果,若是-,則直接顯示運算結果。其流程圖如圖5.2所示。


圖5.2 算術運算程序設計流程圖
5.5 顯示程序設計

顯示程序的過程為:顯示開始時,先進行LCD的初始化,判斷是否顯示漢字或ACSII碼或圖形,若不顯示,則返回,若顯示的是漢字或ACSII碼,則進行相應功能的設置,然后送地址和數(shù)據(jù),再判斷是否顯示完,顯示完則返回,沒有顯示完則繼續(xù)送地址,若顯示的是圖形,則先進行相應功能的設置,再送行地址和列地址,然后送數(shù)據(jù),最后判斷是否顯示完,顯示完則返回,沒有顯示完則繼續(xù)送行地址和列地址。其流程圖如圖5.3所示。


圖5.3 顯示程序流程圖
6 系統(tǒng)調試與存在的問題6.1 硬件調試

常見故障:

1、邏輯錯誤:它是由設計錯誤或加工過程中的工藝性錯誤所造成的。這類錯誤包括錯線、開路、短路等。

2、元器件失效:有兩方面的原因:一是器件本身已損壞或性能不符合要求;二是組裝錯誤造成元件失效,如電解電容、集成電路安裝方向錯誤等。

3、可靠性差:因其可靠性差的原因很多,如金屬化孔、接插件接觸不良會造成系統(tǒng)時好時壞,經不起振動;走線和布局不合理也會引起系統(tǒng)可靠性差。

4、電源故障:若樣機由電源故障,則加電后很容易造成器件損壞。電源故障包括電壓值不符合設計要求,電源引線和插座不對,功率不足,負載能力差等。

調試方法:包括多級調試和聯(lián)機調試。在調試過程中要針對可能出現(xiàn)的故障認真分析,直至檢查出原因并排除。

本次硬件調試過程中,對所出現(xiàn)的問題進行了認真的分析和改正,最后能夠很好的達到設計要求的效果。

6.2 軟件調試

軟件調試一般分為以下四個階段:1、 編寫程序并查錯;2、在C語言的編譯系統(tǒng)中編譯源程序3、對程序進行編譯連接,并及時發(fā)現(xiàn)程序中存在的錯誤;4、改正錯誤。

在本次調試中出現(xiàn)的問題有:

1、在程序中有的函數(shù)名未定義;

2、在抄錄程序時,少錄入一些字符,如:“;”、“{”、“-”等符號,而出現(xiàn)錯誤;

3、有一些函數(shù)名錄入時少寫一個字母或順序顛倒;

4、沒有注意函數(shù)名的調用及定義;

5、芯片引腳定義出錯而導致沒有實驗現(xiàn)象。

在軟件調試過程中,對出現(xiàn)的錯誤進行了認真的分析和修改,多次調試成功后,能夠很好的達到既定的設計效果。


附錄附錄一:仿真原理圖


單片機源程序如下:
  1. ----------------------------------*/
  2. |  1  |  2  |  3  |  +  |
  3. - - - - - - - - - - - - -
  4. |  4  |  5  |  6  |  -  |
  5. - - - - - - - - - - - - -
  6. |  7  |  8  |  9  |  *  |
  7. - - - - - - - - - - - - -
  8. | C   |  0  |  =  |  /  |
  9. ----------------------------------*/
  10. 只能實現(xiàn)基本加減運算,無法實現(xiàn)小數(shù)運算。
  11. // 加最大9999+9999=19998
  12. // 減最大9999-0   =9999
  13. // 乘最大9999*9999=99980001
  14. // 除 1/9=0.1111 保留小數(shù)點后4位
  15. #include<reg51.h>
  16. #define uint unsigned int
  17. #define uchar unsigned char
  18. //--------LCD1602-------------------
  19. //P10-17==== D0-7
  20. sbit rs=P3^0;                         //指令or數(shù)據(jù)
  21. sbit wela=P3^1;                       //讀or寫
  22. sbit lcden=P3^2;                                 //使能信號
  23. //--------LCD1602-------------------
  24. //--------KEY-----------------------
  25. //P2口
  26. //--------KEY-----------------------
  27. uchar code table[]= "                ";

  28. long  int data_a,data_b;                           //第一個數(shù)和第二個數(shù)
  29. long  int data_c;                                                      //計算結果

  30. uchar dispaly[10];                    //顯示緩沖

  31. // 描述: 延時t us函數(shù)
  32. void LCD_Delay_us(unsigned int t)
  33. {
  34.               while(t--);                         //t=0,退出
  35. }
  36. // 描述: 延時t ms函數(shù)
  37. void LCD_Delay_ms(unsigned int t)
  38. {
  39.               unsigned int i,j;
  40.               for(i=0;i<t;i++)                                               //執(zhí)行t次循環(huán)
  41.               for(j=0;j<113;j++)                                             //執(zhí)行113次循環(huán)
  42.               ;
  43. }
  44. // 描述: 1602液晶寫指令
  45. void write_com(uchar com)                              //1602液晶寫指令
  46. {
  47.               rs=0;                               //寫指令
  48.               lcden=0;                            //使能1602
  49.               P1=com;                             //寫入指令com
  50.               LCD_Delay_ms(1);                     //延時1ms
  51.               lcden=1;                             //使能1602
  52.               LCD_Delay_ms(2);                    //延時2ms
  53.               lcden=0;                                          //使能1602
  54. }
  55. // 描述:1602液晶寫數(shù)據(jù)
  56. void write_date(uchar date)                 //1602液晶寫數(shù)據(jù)
  57. {
  58.               rs=1;                                //寫數(shù)據(jù)
  59.               lcden=0;                             //使能1602
  60.               P1=date;                              //寫入數(shù)據(jù)date
  61.               LCD_Delay_ms(1);                      //延時1ms
  62.               lcden=1;                         //使能1602
  63.               LCD_Delay_ms(2);                //延時2ms
  64.               lcden=0;                                      //使能1602
  65. }
  66. // 描述:指定x,y寫入字符函數(shù)
  67. void W_lcd(unsigned char x,unsigned char y,unsigned char Data)
  68. {   
  69.               if (y == 0){write_com(0x80 + x);}      //第一行
  70.               else{write_com(0xc0 + x);}           //第二行
  71.               write_date( Data);                   //寫入數(shù)據(jù)
  72. }
  73. //指定x,y寫入字符串函數(shù)
  74. void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)
  75. {   
  76. if (y == 0){write_com(0x80 + x);}                                //第一行
  77. else{write_com(0xC0 + x);}                                       //第二行
  78. while (*s)                                    
  79.               {write_date( *s); s++;}                                     //寫入數(shù)據(jù)
  80. }
  81. // 描述:初始化液晶,及畫面初始化
  82. void init_lcd(void)                        //初始化液晶,及畫面初始化
  83. {
  84.               wela=0;                            //寫液晶
  85.               lcden=0;                           //使能1602
  86.               write_com(0x38);                   //8 位總線,雙行顯示,5X7 的點陣字符
  87.               LCD_Delay_us(100);                //延時100us
  88.               write_com(0x0c);                    //開顯示,無光標,光標不閃爍
  89.               write_com(0x06);                    //光標右移動
  90.               write_com(0x01);                     //清屏
  91.               write_com(0x80);                      //DDRAM 地址歸0
  92. }
  93. // 描述: 反轉法鍵盤掃描
  94. short keycheckdown()                                                               /* 反轉法鍵盤掃描 */
  95. {

  96.               short temp1,temp2,temp,a=0xff;
  97.               P2=0xf0;                                                                                /* 輸入行值(或列值) */
  98.               LCD_Delay_ms(20);                                                           /* 延時 */
  99.               temp1=P2;                                                                                        /* 讀列值(或行值) */
  100.               P2=0xff;
  101.               LCD_Delay_ms(20);                                                            /* 延時 */
  102.               P2=0x0f;                                                                                          /* 輸入列值(或行值) */
  103.               LCD_Delay_ms(20);                                                           /* 延時 */            
  104.               temp2=P2;                                                                                       /* 讀行值(或列值) */
  105.               P2=0xff;
  106.               temp=(temp1&0xf0)|(temp2&0xf);                /* 將兩次讀入數(shù)據(jù)組合 */
  107.               switch(temp)                                                                          /* 通過讀入數(shù)據(jù)組合判斷按鍵位置 */
  108.               {


  109.                             case 0x77 :a=0x0d;break;            //  按鍵/  
  110.                             case 0x7b :a=0x0e; break;           // 按鍵=            
  111.                             case 0x7d :a=0;                 break;        / / 按鍵0
  112.                             case 0x7e :a=0x0f; break;            // 按鍵CE

  113.                             case 0xb7 :a=0x0c;break;            //               按鍵*
  114.                             case 0xbb :a=0x9;break;            //  按鍵9
  115.                             case 0xbd :a=0x8;break;               //  按鍵8
  116.                             case 0xbe :a=0x7;break;             //               按鍵7

  117.                             case 0xd7 :a=0x0b;break;            //  按鍵-
  118.                             case 0xdb :a=0x6;break;              //               按鍵6
  119.                             case 0xdd :a=0x5;break;              //               按鍵5
  120.                             case 0xde :a=0x4;break;              //               按鍵4

  121.                             case 0xe7 :a=0x0a; break;             // 按鍵+
  122.                             case 0xeb :a=3;break;                            //  按鍵3
  123.                             case 0xed :a=2;break;                            //  按鍵2
  124.                             case 0xee :a=1;break;                           //  按鍵1

  125.                             default :a=0xff;
  126.               }
  127.               return a;                                                                                              /* 返回按鍵值 */
  128. }
  129. void display_a() //顯示數(shù)據(jù)a
  130. {
  131.               dispaly[3]=data_a%10000/1000;              //千
  132.               dispaly[2]=data_a%1000/100;                   //百
  133.               dispaly[1]=data_a%100/10;                    //十
  134.               dispaly[0]=data_a%10;                       //個

  135.               write_com(0x80+0);                            //顯示數(shù)據(jù)a
  136.               if(data_a>999){              write_date('0'+dispaly[3]);}      //顯示千位
  137.               if(data_a>99){              write_date('0'+dispaly[2]);}                            //顯示百位
  138.               if(data_a>9){              write_date('0'+dispaly[1]);}     //顯示十位
  139.                                           write_date('0'+dispaly[0]);      //顯示個位
  140. }

  141. void display_b()                             //顯示數(shù)據(jù)b
  142. {
  143.               write_com(0x80+7);                     //第一行
  144.               dispaly[3]=data_b%10000/1000;               //千
  145.               dispaly[2]=data_b%1000/100;                //百
  146.               dispaly[1]=data_b%100/10;                 //十
  147.               dispaly[0]=data_b%10;                          //個

  148. if(data_b>999){              write_date('0'+dispaly[3]); }     //顯示千位  
  149. if(data_b>99) {              write_date('0'+dispaly[2]); }    //顯示百位
  150. if(data_b>9)  {              write_date('0'+dispaly[1]); }     //顯示十位
  151.                                                 write_date('0'+dispaly[0]);      //顯示個位
  152. }

  153. //計算結果
  154. void display_c(x)
  155. {

  156.               if(data_c<100000000&&data_c>-1)           //溢出時顯示錯誤
  157.               {            

  158.                             dispaly[8]=data_c%1000000000/100000000;                  //萬萬
  159.                             dispaly[7]=data_c%100000000/10000000;                  //千萬
  160.                             dispaly[6]=data_c%10000000/1000000;                                //百萬
  161.                             dispaly[5]=data_c%1000000/100000;                                //十萬
  162.                             dispaly[4]=data_c%100000/10000;                                              //萬
  163.                             dispaly[3]=data_c%10000/1000;                                              //千
  164.                             dispaly[2]=data_c%1000/100;                                                //百
  165.                             dispaly[1]=data_c%100/10;                                                  //十
  166.                             dispaly[0]=data_c%10;                                                      //個
  167.                             write_com(0x80+6+0x40);                  //第一行
  168.                             if(x==4)
  169.                             {   
  170.                             if(data_c>99999999)              {              write_date('0'+dispaly[8]);}    //顯示萬萬
  171.                             if(data_c>9999999)              {              write_date('0'+dispaly[7]);}   //千萬
  172.                             if(data_c>999999)              {              write_date('0'+dispaly[6]);}    //百萬
  173.                             if(data_c>99999)              {              write_date('0'+dispaly[5]);}    //十萬
  174.                                                                                                                 write_date('0'+dispaly[4]);    //萬
  175.                                                                                                                 write_date('.');
  176.                                                                                                                 write_date('0'+dispaly[3]);    //千
  177.                                                                                                                 write_date('0'+dispaly[2]);    //百
  178.                                                                                                                 write_date('0'+dispaly[1]);    //十
  179.                                                                                                                 write_date('0'+dispaly[0]);    //個
  180.                             }
  181.               else{
  182.                             if(data_c>99999999)              {              write_date('0'+dispaly[8]);}    //顯示萬萬
  183.                             if(data_c>9999999)              {              write_date('0'+dispaly[7]);}    //千萬
  184.                             if(data_c>999999)              {              write_date('0'+dispaly[6]);}    //百萬
  185.                             if(data_c>99999)              {              write_date('0'+dispaly[5]);}    //十萬
  186.                             if(data_c>9999)                            {              write_date('0'+dispaly[4]);}    //萬
  187.                             if(data_c>999)                            {              write_date('0'+dispaly[3]);}    //千
  188.                             if(data_c>99)                            {              write_date('0'+dispaly[2]);}    //百
  189.                             if(data_c>9)                            {              write_date('0'+dispaly[1]);}    //十
  190.                                                                                                                 write_date('0'+dispaly[0]);    //個
  191.                             }
  192.               }
  193.               else                                               //溢出時顯示錯誤
  194.               {
  195.                             write_com(0x80+11+0x40); //第一行
  196.                             write_date('E');         //顯示 E
  197.                             write_date('r');         //顯示R
  198.                             write_date('r');                            //顯示R
  199.                             write_date('o');                            //顯示O
  200.                             write_date('r');                            //顯示E
  201.               }
  202. }

  203. void eql(uchar x)//加減乘除運算
  204. {
  205.               switch(x)                            /*功能鍵選擇*/
  206.                                           {  
  207.                                                         case 1:data_c=data_a+data_b;break;                               //加  /* + S=1 */ /* 數(shù)值轉換函數(shù) */                                                                                                                             
  208.                                                         case 2:if(data_a>=data_b){data_c=data_a-data_b;} /* - S=2 *///減
  209.                        else{data_c=data_b-data_a;W_lcd(5,1,'-');} //負數(shù)符號
  210.                                                                          break;               
  211.                                                         case 3:data_c=(data_a*data_b);break;                              /* * S=3 *///乘
  212.                                                         case 4:if(data_b==0){LCD_Write_String(0,1,"Error !");}else{data_c=(data_a*10000)/data_b;}break;                              /* / S=4       *///除//溢出時顯示錯誤
  213.                                                         case 0:break;
  214.                                           }               
  215. }
  216. void main()
  217. {
  218.               uchar   key=0xff;               //鍵值初始化
  219.               uchar   n=0;                                                                      //第1個數(shù)可以按1-4次
  220.               uchar   m=5;                                                                       //第2個數(shù)可以按1-4次
  221.               uchar   x=0;
  222.               data_a=0;                       //前一個數(shù)
  223.               data_b=0;                       //后一個數(shù)
  224.               data_c=0;                       //結果
  225.               init_lcd();                                                                        //1602液晶初始化
  226.               display_a();
  227.     while(1)
  228.                 {
  229.                               key=keycheckdown();                                          /*動態(tài)掃描鍵盤,返回按鍵對應值,賦給j        key=0到f */
  230.                             if(0xff!=key)                                                        /*若返回值有效,進入內部處理程序*/
  231.                             {
  232.                               if(key<10)
  233.                               {
  234.                       if(n<4){data_a=data_a*10+key;m=5;display_a();}n++;  //首先輸入第一個數(shù)
  235.                                 if(m<4){data_b=data_b*10+key;n=5;display_b();}m++;  //必須按了+-*/才能輸入第二個數(shù)                           
  236.                               }
  237.           else
  238.           {              switch(key)                            /*功能鍵選擇*/
  239.                                                                       {
  240.                                                                                     case 0xa:n=5;m=0;x=1;W_lcd(5,0,'+');break; //加  /* + S=1 */ /* 數(shù)值轉換函數(shù) */                                                                                                                             
  241.                                                                                     case 0xb:n=5;m=0;x=2;W_lcd(5,0,'-');break;                              /* - S=2 *///減
  242.                                                                                     case 0xc:n=5;m=0;x=3;W_lcd(5,0,'*');break;                              /* * S=3 *///乘
  243.                                                                                     case 0xd:n=5;m=0;x=4;W_lcd(5,0,'/');break;                              /* / S=4 *///除
  244.                                                                                     case 0xe:n=5;m=5;eql(x);W_lcd(12,0,'=');display_c(x);break;                 /* = */
  245.                                                                                     case 0xf:n=0;x=0;m=5; data_a=0;data_b=0;data_c=0;LCD_Write_String(0,0,table);LCD_Write_String(0,1,table);W_lcd(0,0,'0');break; /*     C*/
  246.                                                                       }                                             
  247.                               }
  248.                                           do{P2=0xf0;}while(P2!=0xf0);                            /*等待按鍵松開*/
  249.                               }//(0xff!=key)               
  250. ……………………

  251. …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼

所有資料51hei提供下載:
單片機簡單計算器.doc (292 KB, 下載次數(shù): 69)


評分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏4 分享淘帖 頂1 踩
回復

使用道具 舉報

沙發(fā)
ID:485799 發(fā)表于 2019-7-5 11:59 | 只看該作者
請問184行的if語句x=4是什么效果,我沒看懂,溢出時的error顯示好像也不大對
回復

使用道具 舉報

板凳
ID:649892 發(fā)表于 2019-11-26 14:06 | 只看該作者
有沒有原理圖啊
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表