基於C51單片機的智能計算器、矩陣鍵盤、lcd1602

目錄程序員

1緒論.............................................................................................................................. 1編程

1.1選題背景............................................................................................................. 1框架

1.2起源與發展.......................................................................................................... 1編程語言

1.3研究的目的和意義............................................................................................... 2模塊化

2項目整體設計框架......................................................................................................... 2函數

2.1芯片STC89C52.................................................................................................... 2工具

2.2採用矩陣式鍵盤做爲輸入模塊.............................................................................. 2佈局

2.3顯示模塊............................................................................................................. 3性能

2.4硬件資源分配...................................................................................................... 3學習

3計算器硬件設計............................................................................................................ 4

3.1系統組成及硬件框圖............................................................................................ 4

3.2元器件簡介.......................................................................................................... 4

3.2.1 STC89C52的特色........................................................................................ 4

3.2.2 LCD1602 液晶顯示屏.................................................................................. 5

4系統電路設計................................................................................................................ 6

4.1鍵盤電路設計...................................................................................................... 7

4.2顯示電路設計...................................................................................................... 8

4.3其餘電路部分...................................................................................................... 8

4.3.1 蜂鳴器模塊............................................................................................... 8

4.3.2 電源模塊................................................................................................... 9

4.3.3 單片機最小系統........................................................................................ 9

5計算器軟件設計........................................................................................................... 10

5.1總體設計結構..................................................................................................... 10

5.2液晶屏讀寫函數................................................................................................. 10

5.2.1 初始化函數.............................................................................................. 10

5.2.2 寫命令函數.............................................................................................. 11

5.2.3 寫數據函數.............................................................................................. 11

5.3接收矩陣鍵盤輸入函數....................................................................................... 12

5.4調試和運行程序................................................................................................. 13

5.4.1 Proteus仿真運行程序................................................................................ 13

5.4.2 在實驗箱上運行程序................................................................................ 13

6總結............................................................................................................................ 14

 

 

 

 

 


基於51單片機的簡易計算器

 

摘要:近幾年單片機技術的發展很快,其中,電子產品的更新速度迅猛。計算器是平常生活中比較常見的電子產品之一。如何才能使計算器技術更加的成熟,充分利用已有的硬件和軟件條件,設計出更出色的計算器。

本設計是以STC89C52單片機爲核心的計算器模擬系統設計,輸入採用4*4矩陣鍵盤,能夠進行加、減、乘、除帶符號數字運算(六位整數或兩位小數點點),並在液晶顯示屏LCD1602上靜態顯示操做過程及結果。對字符液晶顯示模塊的工做原理,如初始化、清屏、顯示、調用及外特性有較清楚的認識,並會使用LCD(液晶顯示模塊)實現計算結果的顯示;掌握液晶顯示模塊的驅動和編程,設計LCD和單片機的接口電路,以及利用單片機對液晶顯示模塊的驅動和操做;在充分分析內部邏輯的概念,進行軟件和調試,學會使用,並可以以其爲平臺設計出具備四則運算能力簡易計算器的硬件電路和軟件程序。

關鍵詞:單片機;液晶顯示器;計算器;矩陣鍵盤

 

1緒論

1.1選題背景

現現在,人們的平常生活中已經離不開計算器了,社會的各個角落都有它的身影,好比商店、辦公室、學校……所以設計一款簡單實用的計算器會有很大的實際意義[1]。本設計旨在進一步掌握單片機理論知識,理解單片機系統的硬軟件設計,增強對實際應用系統設計的能力。經過本設計的學習,使我掌握單片機程序設計的基本方法,並能綜合運用本科階段所學軟、硬件知識分析實際問題,提升解決畢業設計實際問題的能力,爲單片機應用和開發打下良好的基礎。

1.2起源與發展

計算器是最先的計算工具,例如:奇普(Quipu或khipu)是古代印加人的一種結繩記事的方法,用來計數或者記錄歷史。它是由許多顏色的繩結編成的。

還有古希臘人的安提凱希拉裝置,中國的算盤等。中國古代最先採用的一種計算工具叫籌策,又被叫作算籌。這種算籌多用竹子製成,也有用木頭,獸骨充當材料的。約二百七十枚一束,放在布袋裏可隨身攜帶。直到今天仍在使用的珠算盤,是中國古代計算工具領域中的另外一項發明,明代時的珠算盤已經與現代的珠算盤幾乎相同。

早期的計算器爲純手動式,如算盤、算籌等。算盤一般是以滑動的珠子製成。在西方,算盤在印度阿拉伯數字流行前使用了數個世紀,且在近代中國的記賬與商務上仍普遍使用。後來出現機械計算器。17世紀初,西方國家的計算工具備了較大的發展,英國數學家納皮爾發明的"納皮爾算籌",英國牧師奧卻德發明了計圓柱型對數算尺,這種計算尺不只能作加減乘除、乘方、開方運算,甚至能夠計算三角函數,指數函數和對數函數,這些計算工具不只帶動了計算器的發展,也爲現代計算器發展奠基了良好的基礎,成爲現代社會應用普遍的計算工具。

1.3研究的目的和意義

計算器使用的是固化的處理程序,只能完成特定的計算任務;而計算機藉助操做系統平臺和各種應用軟硬件,能夠無限擴展其應用領域。也就是說,是否具備擴展性是兩者的本質區別[2]

單片機又稱單片微控制器,它不是完成某一個邏輯功能的芯片,而是把一個計算機系統集成到一個芯片上。歸納的講:一塊芯片就成了一臺計算機。在計算機應用與智能化控制的科學家、工程師手中,它和計算機的本質相同,能夠開發出針對各種電子電氣產品的應用,例如洗衣機。但對於用戶來講,他們並不須要知道洗衣機裏的單片機的接口和編程語言,只要能操做洗衣服就行,所以單片機用於某個具體的電子產品上就須要配合簡潔方便的人機界面,用戶只使用它的特定功能。

2項目整體設計框架

2.1芯片STC89C52

單片機是單片微型機的簡稱,故又稱爲微控制器MCU(Micro Control Unit)。一般由單塊集成電路芯片組成,內部包含有計算機的基本功能部件:中央處理器CPU,存儲器和I/O接口電路等。所以,單片機只要和適當的軟件及外部設備相結合,即可成爲一個單片機控制系統。單片機普遍應用於智能產品,智能儀表,測控技術,智能接口等,具備操做簡單、實用方便、價格便宜等優勢[3]

而其中STC89C52是一種帶8K字節閃爍可編程可擦除只讀存儲器(FPEROM-Flash Programable and Erasable Read Only Memory)的低電壓,高性能COMOS8的微處理器。該器件與工業標準的MCS-51指令集和輸出管腳相兼容;且是單片機中最典型的表明,應用於各類控制領域[4]

2.2採用矩陣式鍵盤做爲輸入模塊

矩陣式按鍵輸入模塊,其特色是:電路和軟件稍複雜,但相比之下,當鍵數越多時,越節約I/O口,比較節省資源。其原理圖如圖1所示。

 

         圖1 矩陣鍵盤輸入

         Fig.1 Matrix keyboard input

2.3顯示模塊

採用LED數碼管的靜態顯示,其特色是:其亮度較高;這種顯示方式接口,編程容易且管理簡單;不足的是,佔用的I/O的線資源較多。若是採用單片機或CPLD/FPGA來控制的話,勢必存在浪費I/O口資源的問題[5]。採用LED數碼管的動態顯示,其特色是:其亮度比靜態顯示的亮度要差一些;但其電路比較簡單,適合於顯示位數較多的狀況。採用LCD1602液晶顯示,如圖2所示,其特色是:能夠調節其背光亮度,這種顯示方式接口,編程雖然有些麻煩,但管理較方便,佔用的I/O口資源線也很少。在計算器運算中,需顯示的數字、符號較多,按很據個方面的特色,然後能夠發現LCD液晶顯示,雖然在價格上的確是稍貴於LED數碼管;但數碼管在硬件設計電路中,會因線太多、線路複雜而過於繁瑣,則捨棄LED數碼管,選擇LCD液晶顯示[6]

 

         圖2 LCD 1602液晶顯示屏

         Fig.2 1602 liquid crystal display

2.4硬件資源分配

主要用到的硬件:單片機STC89C52 、液晶顯示屏LCD1602 、4*4按鍵鍵盤

硬件分配:

  1. P1口:做爲輸入口,與鍵盤鏈接,實現數據的輸入。
  2. P0、P2口:做爲輸出口(P2口爲高位,P0口爲低位),控制LCD液晶顯示屏顯示數據的結果。
  3. 液晶顯示屏LCD1602顯示輸出。

3計算器硬件設計

3.1系統組成及硬件框圖

 顯示模塊

 

 

蜂鳴器電路

 

矩陣鍵盤輸入模塊

 

 
   

 

 

 

 

 

 

圖3 系統組成及硬件框圖

Fig.3 System composition and hardware block diagram

3.2元器件簡介

3.2.1 STC89C52的特色

 

圖4 STC89C52 單片機

Fig.4 Single chip microcomputer STC89C52

  1. 主要性能:

與MCS-51單片機產品兼容;8K字節在系統可編程Flash存儲器;1000次擦寫週期;全靜態操做:0Hz-33Hz;三級加密程序存儲器;32個可編程I/O口線、三個16位定時器/計數器、8箇中斷源;全雙工UART串行通訊;低功耗空閒和掉電模式,掉電後中斷可喚醒;看門狗定時器;雙數據指針;掉電標識符[7]

  1. STC89C52的功能特性概述

STC89C52是一種低功耗、高性能CMOS 8位微控制器,具備8K在系統可編程Flash存儲器。使用高密度非易失性存儲器技術製造,與工業80C51產品指令和引腳徹底兼容。片上Flash容許程序存儲器在系統可編程,亦適於常規編程器。

3.2.2 LCD1602 液晶顯示屏

  1. 液晶顯示原理

液晶顯示的原理是利用液晶的物理特性,經過電壓對其顯示區域進行控制,有電就有顯示,這樣便可以顯示出圖形[8]。液晶顯示器有厚度薄、適用於大規模集成電路直接驅動、易於實現全綵色顯示的特色,目前已經被普遍應用在便攜式計算機、數字攝像機、PDA移動通訊工具等衆多領域。

  1. LCD1602的應用簡介

LCD1602液晶顯示器採用HD44780及其兼容芯片做爲點陣式LCD的控制器驅動器,還採用HD44100進行LCD的時分割驅動。HD44780的內部結構主要包括顯示數據RAM(DDRAM)、字符發生器ROM(CGROM)、字符發生器RAM(CGRAM)、指令寄存器IR、數據寄存器DR、地址計數器AC(Address Counter)和忙標誌BF(Busy Flag)等邏輯電路[9]

1602液晶模塊內部的控制器共有11條控制指令,豐富的指令能夠完成液晶的時序控制、工做方式設置和數據顯示等。

採用的LCD1602液晶模塊是標準16針插座,接口電路如圖5所示,及各引腳說明如表1所示。

 

圖5 LCD1602引腳接口電路圖

Fig.5 Pin interface circuit diagram of LCD1602

 

表1 LCD1602 引腳說明

Table.1 LCD1602 pin description

第1腳

Vss爲地電源

第2腳

VDD接5V正電源

第3腳

Vo爲液晶顯示器對比度調整端,接電源正極時對比度最弱,接地電源時對比度最高,對比度太高時會產生「鬼影」,使用時能夠經過一個10K的電位器調整對比度。

第4腳

Rs爲寄存器選擇,高電平選擇數據寄存器、低電平選擇指令寄存器。

第5腳

Rw爲讀寫信號線,高電平時進行讀操做,低電平時選擇指令寄存器。

第6腳

E端爲使能端,當E端由高電平跳變成低電平時,液晶模塊執行命令。

第7-14腳

D0-D7爲8位雙向數據線。

第15-16腳

背光陽極和背光陰極。

  1. 其餘方面介紹

DDRAM用來暫存顯示字符的代碼,共80個字節,DDRAM的各個單元對應着顯示屏上的各個字符位,如圖6所示。所以,DDRAM的地址也就意味着顯示字符的地址,顯示字符時首先要向LCD傳送顯示字符地址。

LCD

16字*2行

 

 

 

 

 

 

00

01

02

03

04

05

06

07

08

09

0A

0B

0C

0D

OE

OF

10

……

27

40

41

42

43

44

45

46

47

48

49

4A

4B

4C

4D

4E

4F

50

……

67

圖6 DDRAM單元地址與顯示屏字符位的對應關係

Fig.6 Correspondence between DDRAM unit address and display character bits

4系統電路設計

爲了更好地實現系統的功能,硬件電路的設計應該遵循如下原則:

  1. 優化硬件電路

採用軟件設計與硬件設計相結合的方法。儘管採用軟件來實現硬件系統的功能時,也許響應的時間會比單純使用硬件時長,並且還要佔用微處理器MCU的時間;可是,用軟件實現硬件的功能能夠簡化硬件結構,提升電路的可靠性。因此,在設計本系統的時候,在知足可靠性和實時性的前提下,儘量地經過軟件來實現硬件功能。

  1. 可靠性及抗干擾設計

根據可靠性設計理論,系統所用芯片數量越少,系統的平均無端障時間越長。並且,所用芯片數量越少,地址和數據總線在電路板上受干擾的可能性也就越小。所以,系統的設計思想是在知足功能的狀況下爭取較少數量的芯片。

  1. 靈活的功能擴展

功能擴展是否靈活是衡量一個系統優劣的重要指標。一次設計每每不能徹底考慮到系統的各個方面,系統須要不斷完善以及進行功能升級。進行功能擴展時,應該在原有設計的基礎上,經過修改軟件程序和少許硬件完成。對於本系統而言,就是要求在系統硬件不變的狀況下,可以經過修改軟件程序,完成功能的升級和擴展[10]

根據提出的系統設計方案,結合以上三條原則,肯定了系統硬件的設計。計算器主要由如下一些功能模塊組成:非編碼鍵盤模塊、運算模塊(單片機內部)、LCD液晶顯示模塊等。

該系統的硬件設計採用了模塊化的設計方法。STC89C52單片機與LCD液晶顯示屏顯示電路是整個電路的核心,它們能實現系統的功能要求。

簡易計算器主要包括:鍵盤電路、運算電路、輸出顯示電路。

前面說明了該系統的設計,系統採用了比較簡單的設計方案,因此該系統的硬件設計的總外圍電路不會產生過多的干擾。下面對系統的外圍電路分別做了說明。鍵盤部分採用4*4按鍵鍵盤,顯示部分採用LCD液晶顯示屏徹底可以很好地實現顯示方面的要求。

4.1鍵盤電路設計

鍵盤可分爲兩類:編碼鍵盤和非編碼鍵盤。編碼鍵盤是較多按鍵(20個以上)和專用驅動芯片的組合;當按下某個按鍵時,它可以處理按鍵抖動、連擊等問題,直接輸出按鍵的編碼,無需系統軟件干預。

通用計算機使用的鍵盤就是編碼鍵盤。在智能儀器中,使用並行接口芯片8279或串行接口HD7279都可以組成編碼鍵盤,同時還能夠兼顧數碼管的顯示驅動,其相關的接口電路和接口軟件都可在芯片資料中獲得。當系統功能比較複雜,按鍵數量不少時,採用編碼鍵盤能夠簡化軟件設計[11]

非編碼鍵盤成本低廉。從成本角度出發,本設計選用的是非編碼鍵盤。如圖7所示。

 

圖7 鍵盤電路設計     

Fig.7 Keyboard circuit design

4.2顯示電路設計

當系統須要顯示少許數據時,採用LCD液晶顯示屏進行顯示是一種經濟實用的方法。P0口做爲液晶顯示的數據端口,P2.0-P2.2口做爲其控制端口,控制LCD液晶顯示屏顯示輸出數據。最終顯示電路如圖8所示

 

圖8 液晶顯示電路設計

Fig.8 Liquid crystal display circuit design

4.3其餘電路部分

4.3.1 蜂鳴器模塊

蜂鳴器在電路中主要用來每按下一次按鍵後,蜂鳴器就發出一次聲響,以提示用戶已經按下了按鍵,其電路部分如圖9所示。

 

圖9 蜂鳴器模塊電路設計

Fig.9 Buzzer module circuit design

4.3.2 電源模塊

 

圖10 電源模塊電路設計

Fig.10 Power module circuit design

4.3.3 單片機最小系統

 

圖11單片機最小系統電路設計

Fig.11 Minimal system circuit design of single chip microcomputer

5計算器軟件設計

5.1總體設計結構

在軟件中主要定義了delay()延時函數、lcdwrc()寫命令、lcdwrd()寫數據、光標定位、lcdinit()初始化、keyscan()按鍵檢測、main()等幾個函數,其中最爲複雜的就是按鍵檢測函數,在主函數中只是調用是初始化函數,而後死循環keyscan()按鍵檢測函數,具體如圖12所示。

 

圖12總體設計結構

Fig.12 Overall design structure

5.2液晶屏讀寫函數

5.2.1 初始化函數

使用lcd1602液晶顯示模塊前,須要對其顯示模式,進行初始化設置,在初始化函數中,使用了lcd中的幾條命令:

寫入0x38:兩行顯示,5x7點陣,8位數據,執行空操做,給硬件反應時間。

寫入0x0f:開總體顯示,打開光標,打開光標閃爍,執行空操做,給硬件反應時間。

寫入0x05:寫入一個字符後,地址指針加一,光標左移,執行空操做,給硬件反應時間。

寫入0x01:清屏。

具體實現的代碼如圖13所示。

 

圖13初始化函數

Fig.13 Initialization function

5.2.2 寫命令函數

按照規定,RS和E必須同時爲0時,才能夠寫入命令,將命令寫入P0口中,寫命令時,E應爲正脈衝,即正跳變,因此前面先置E=0,而後給一點延時,等待機器反應,E由高電平變爲低電平,LCD開始執行命令;具體實現的代碼如圖14所示。

 

圖14寫命令函數

Fig.14 Write command function

5.2.3 寫數據函數

寫數據就是將要顯示字符的ACSⅡ碼寫入LCD 1602液晶顯示模塊中的顯示數據RAM(DDRAM);按照規定,寫數據時,E應爲正脈衝,首先先置E=0,其中RS=1和RW=0時,才能夠寫入數據,而後將數據從P0口輸入,即寫入LCD 1602液晶顯示模塊,當E有高電平變爲低電平,寫數據操做結束,具體實現代碼如圖15所示。

 

圖15寫數據函數

Fig.15 Write data function

5.3接收矩陣鍵盤輸入函數

接收舉證鍵盤輸入函數是整個程序中最主要的函數,在此函數中,經過八根 I/O 口線組成一個 4×4=16 的矩陣鍵盤,單片機對其進行掃描,把按下鍵的鍵值顯示在顯示屏上。

查看實驗箱上的電路圖(見圖16),可看到 16 個按鍵分別經過 4 根行線和 4 根列線交叉組成,其中 4 根行線分別接到了單片機的 P1.4~P1.7 口,4 根列線分別接到了單片機的 P1.0~P1.3 口,這樣一個 P1 端口就接了 16 個按鍵。

 

圖16矩陣鍵盤電路

Fig.16 Matrix keyboard circuit

矩陣式鍵盤的按鍵識別方法通常有三種,即:行掃描法、行列掃描法和行反轉法。在實際應用中,因爲行反轉法速度較快,因此應用較爲普遍,本例就採用這種方法;

行反轉法的基本原理是:將行線接一個數據端口,讓它先工做在輸出模式,將列線也接到一個數據端口,讓它先工做在輸入模式;讓 CPU 經過輸出端口向行線上所有送出低電平,而後讀入列線上的值,若是此時有鍵被按下,則一定會使某列線值爲低電平;接着對兩個端口進行模式改變,使接行線的端口改成輸入模式,接列線的端口改成輸出模式,而且將剛纔讀得的列值從列線所接端口輸出,再讀取行線的值, 那麼閉合健所在的行線值一定爲低電平;這樣,當一個按鍵被按下時, 一定能夠讀得一對惟一的行值和列值;

這樣咱們就能夠把獲得的值經過寫命令,把值寫入到液晶顯示屏中,並保存記錄下這個值,當輸入符號位時,進行清屏操做,並記錄下所按下符號的鍵值,最後當用戶按下等號時,根據所輸入的數據和運算符,得出相應的結果,並把結果輸出到顯示屏中,這樣就完成了一次運算;當按下清屏鍵時,lcd 1602執行清屏操做,又恢復到光標閃爍,初始化界面。

5.4調試和運行程序

5.4.1 Proteus仿真運行程序

首先在電腦上搭建Proteus仿真平臺,在平臺上繪製出本次設計的電路圖,把程序生產的hex文件下載到C52單片機中,而後啓動仿真,在仿真環境中就能夠測試程序設計是否符合要求,其效果如圖17所示。

圖17 Proteus仿真

Fig.17 Proteus simulation

5.4.2 在實驗箱上運行程序

首先將實驗箱ME850經過數據線與電腦鏈接,打開實驗箱開關,將實驗箱上的JP15(蜂鳴器)和JP25(背光)跳線帽接上,JP24跳線帽改接到NO上,4x4矩陣鍵盤的8個跳線帽也接上,試驗箱的主板電路佈局如圖18所示。

 

圖18 ME850硬件佈局

Fig.18 ME850 hardware layout

經過專用的燒寫工具MEFlash,將hex文件燒寫到ME850試驗箱中,就能夠運行程序了,燒寫完成之後實現的效果如圖19所示。

 

圖19 在開發板上的實現效果

Fig.19 Implementation effect on the development board

6總結

我認爲,學編程讀別人的程序很是重要,每一個人都有不一樣的思惟,相同的任務卻有不少不一樣的方法,在每一個程序裏都能找到些經典的段子,讓人回味。從中能夠學到不少的方法,而且有些能夠直接的引用。一個出色的程序員在編程時,並非從零開始,而應該是先找出相似的例子進行分析,參考,看看有沒有值得引用和借鑑的地方,加以修改,爲本身所用。實踐證實,這樣作是對的。

基本功要雜實,要有必定的數模電基礎。學單片機首先要搞清楚它的基本結構和存儲單元的分配。          

多讀有表明性的程序,讀得多了天然就會學到不少的好方法。可買本單片機子程序集看看,也可網上下載程序分析。

我以爲以上幾點至關重要,由於它對我幫助很大,算是將我領進了單片機的大門,以致於我學起來不那麼吃力,沒有感受到 像你們說的那樣的難。我看過不少的程序,也調試過不少的程序,每一次收穫都不小。個人實驗室就是KEIL和PROTEUS。這使我作實驗很方便。雖是虛擬的,但調試程序仍是能夠的,省去了不少的時間提升了效率。最近我在學C51,由於學單片機掌握C語言是很是重要的,C語言的通用性對學習其它類型的單片機有很大的幫助。從此,我想作嵌入式系統工程師,想學ARM,想搞操做系統。因此我如今必須打好基礎,這樣才能進步。

經過這種途徑的實踐教學活動,咱們將前幾年所學的知識綜合起來了,將所學的知識應用於實踐中去了。這樣,到了社會上咱們就更有競爭力了。

實踐證實,經過該課程設計,不只提升了學生學習的興趣,加深了對專業知識的理解,開闊了視野,也爲之後畢業設計打下良好的基礎。單片機課程設計這一實踐教學環節的有效開展,有助於學生有效地掌握所學知識,縮短從理論知識到實際應用的過程,很好地培養了學生的專業興趣,加強了學生的創新意識,提升了學生的動手能力和實際應用能力。

 

 

結語

通過了兩個多星期的學習和工做,我終於完成了《基於51單片機的簡易計算器》的課程設計。從開始接到課程設計題目到系統的實現,再到課程設計文章的完成,每走一步對我來講都是新的嘗試與挑戰,這也是我在大學期間獨立完成的最大的項目。在這段時間裏,我學到了不少知識也有不少感覺,從對C52單片機的一無所知,對動態掃描,矩陣鍵盤等相關技術很不瞭解的狀態,我開始了獨立的學習和試驗,查看相關的資料和書籍,讓本身頭腦中模糊的概念逐漸清晰,使本身很是稚嫩做品一步步完善起來,每一次改進都是我學習的收穫,每一次試驗的成功都會讓我興奮好一段時間。從中我也充分認識到了單片機給咱們生活帶來的樂趣,在屬於本身的編程器件上,盡情宣泄本身的情感,表達本身的感覺,而且把本身的想法與他人分享,我也有了一個屬於本身可控制的單片機。

雖然個人課程設計做品不是很成熟,還有不少不足之處,但我能夠自豪的說,這裏面的每一段代碼,都有個人勞動。當看着本身的程序,本身整天相伴的系統可以健康的運行,真是莫大的幸福和欣慰。我相信其中的酸甜苦辣最終都會化爲甜美的甘泉。      

此次作課程設計的經歷也會使我終身受益,我感覺到作課程設計是要真真正正用心去作的一件事情,是真正的本身學習的過程和研究的過程,沒有學習就不可能有研究的能力,沒有本身的研究,就不會有所突破,那也就不叫課程設計了。但願此次的經歷能讓我在之後學習中激勵我繼續進步。

 

 

先上仿真圖

實測效果圖

 

源代碼:

#include<reg52.h> typedef unsigned char uint8; typedef unsigned int uint16; unsigned char dataw; sbit BEEP=P3^7; sbit rw=P2^1; sbit rs=P2^0; sbit e=P2^2; //sbit rw=P2^5; //sbit rs=P2^6; //sbit e=P2^7; //sbit BEEP=P1^5;
 uint8 key,num; uint8 fuhao;//定義具體的那個符號,是加減仍是乘除。
uint8 flag;    //定義有沒有按下符號鍵
long a,b,c,d;    //定義運算數據的第一個和第二個及等於的數變量
uint8 k; //定義小數點後面顯示的位數
uint8 biao; int bz=0; uint8 dat1[]={1,2,3,0x2b-0x30, 4,5,6,0x2d-0x30, 7,8,9,0x2a-0x30, 0,0x01-0x30,0x3d-0x30,0x2b-0x30 };//保存顯示的數據
const unsigned char str0[] = {" NUM INPUT "}; const unsigned char str1[] = {" NUM INPUT NEXT "}; const unsigned char str2[] = {" RESULT SHOW "}; //const unsigned char str3[] = {" "};

    
    
void delay(uint16 i)//延時
{ while(i--); } void buzzer()//蜂鳴器
{ for(bz=490;bz>0;bz--){ BEEP=~BEEP; delay(10); } BEEP=1; } void lcdwrc(uint8 c)//寫入命令
{ delay(1000); rs=0; rw=0; e=0; P0=c; e=1; delay(1000); e=0; } void lcdwrd(unsigned char dataw)//寫入數據
{ delay(1000); rs=1; rw=0; e=0; P0=dataw; e=1; delay(1000); e=0; rs=0; } void ePutstr(unsigned char const *ptr) { unsigned char i,j = 0; lcdwrc(0x01); while(ptr[j] > 31) j++;    //ptr[j]>31 時爲 ASCII 碼,j 累加,計算出字符串長度
    for(i = 0; i < j; i++) { lcdwrd(ptr[i]); //顯示單個字符,同時x座標遞增
 } //lcdwrc(0x4f+0x80);
} void lcdinit()//初始化,復位過程
{ delay(1500); lcdwrc(0x38);//不檢測忙信號
    delay(500); lcdwrc(0x38);//不檢測忙信號
    delay(500); lcdwrc(0x38);//不檢測忙信號
    delay(500); lcdwrc(0x38);//不檢測忙信號
    lcdwrc(0x08);//顯示關閉
    lcdwrc(0x01);//顯示清屏
    lcdwrc(0x06);//顯示光標移動設置
 ePutstr(str0); lcdwrc(0x4f+0x80); lcdwrc(0x0f);//顯示開及光標設置
    key=0; num=0; flag=0; fuhao=0; a=0; b=0; c=0; d=0; biao=0; } void qingpin(){ lcdwrc(0x01); ePutstr(str1); lcdwrc(0x4f+0x80); lcdwrc(0x0f); } void zhongduan(void) interrupt 0 using 0 //外部中斷0中斷函數
{ lcdwrc(0x01); a=0; b=0; flag=0; fuhao=0; ePutstr(str0); lcdwrc(0x4f+0x80); lcdwrc(0x0f); } void keyscan()//按鍵檢測
{ P1=0xfe;   //令第一行爲0,而後判斷是哪一列按下
    if(P1!=0xfe) { buzzer(); delay(1000); if(P1!=0xfe) { key=P1&0xf0; switch(key) { case 0xe0: num=0;break;      //1
                case 0xd0: num=1;break;      //2
                case 0xb0: num=2;break;      //3
                case 0x70: num=3;break;      //
 } } while(P1!=0xfe); if(num==0||num==1||num==2)     //確認第一行的數1,2,3
 { if(flag==0)     //沒有按下符號鍵
 { a=a*10+dat1[num]; lcdwrc(0x0f);//光標閃爍
                lcdwrc(0x04);//設置光標左移,屏幕不移動
                lcdwrd(0x30+dat1[num]); //lcdwrc(0x1c); //ePutstr(str0);
 } else { b=b*10+dat1[num]; lcdwrc(0x0f);//光標閃爍
                lcdwrc(0x04);//設置光標左移,屏幕不移動
                lcdwrd(0x30+dat1[num]); //lcdwrc(0x1c); //ePutstr(str0); //lcdwrc(0x4f+0x80);
 } } if(num==3) { flag=1;//有符號鍵按下
            fuhao=1;//加號+ // ePutstr(0,1,str3); // lcdwrc(0x0c);
 qingpin(); } } P1=0xfd;        //令第二行爲0,判斷是哪一列按下
    if(P1!=0xfd) { buzzer(); delay(1000); if(P1!=0xfd) { key=P1&0xf0; switch(key) { case 0xe0: num=4;break;      //4
                case 0xd0: num=5;break;      //5
                case 0xb0: num=6;break;      //6
                case 0x70: num=7;break;      //減—
 } } while(P1!=0xfd); if(num==4||num==5||num==6) { if(flag==0)     //沒有按下符號鍵
 { a=a*10+dat1[num]; lcdwrc(0x0f);//光標閃爍
                lcdwrc(0x04);//設置光標左移,屏幕不移動
                lcdwrd(0x30+dat1[num]); } else { b=b*10+dat1[num]; lcdwrc(0x0f);//光標閃爍
                lcdwrc(0x04);//設置光標左移,屏幕不移動
                lcdwrd(0x30+dat1[num]); } } else { flag=1;//有符號鍵按下
            fuhao=2;//帶表減號 //ePutstr(0,1,str3); //lcdwrc(0xc);
 qingpin(); } } P1=0xfb;         //令第三行爲0,判斷哪一列按下
    if(P1!=0xfb) { buzzer(); delay(1000); if(P1!=0xfb) { key=P1&0xf0; switch(key) { case 0xe0: num=8;break;      //7
                case 0xd0: num=9;break;      //8
                case 0xb0: num=10;break;  //9
                case 0x70: num=11;break;  //乘*
 } } while(P1!=0xfb); if(num==8||num==9||num==10) { if(flag==0)     //沒有按下符號鍵
 { a=a*10+dat1[num]; lcdwrc(0x0f);//光標閃爍
                lcdwrc(0x04);//設置光標左移,屏幕不移動
                lcdwrd(0x30+dat1[num]); } else { b=b*10+dat1[num]; lcdwrc(0x0f);//光標閃爍
                lcdwrc(0x04);//設置光標左移,屏幕不移動
                lcdwrd(0x30+dat1[num]); } } else { flag=1; fuhao=3;//帶表乘號* //ePutstr(0,1,str3); //lcdwrc(0xc);
 qingpin(); } } P1=0xf7;         //令第四行爲0,判斷哪一列按下
    if(P1!=0xf7) { buzzer(); delay(1000); if(P1!=0xf7) { key=P1&0xf0; switch(key) { case 0xe0: num=12;break;  //0
                case 0xd0: num=13;break;  //清除rst
                case 0xb0: num=14;break;  //等號=
                case 0x70: num=15;break;  //除/
 } } while(P1!=0xf7); switch(num) { case 12: if(flag==0)     //沒有按下符號鍵
 { a=a*10+dat1[num]; lcdwrd(0x30); lcdwrc(0x0f);//光標閃爍
                        lcdwrc(0x04);//設置光標左移,屏幕不移動
 buzzer(); } else { b=b*10+dat1[num]; lcdwrc(0x0f);//光標閃爍
                        lcdwrc(0x04);//設置光標左移,屏幕不移動
                        lcdwrd(0x30); } break; case 13: lcdwrc(0x01);    //清屏指令 
                    a=0; b=0; flag=0; fuhao=0; ePutstr(str0); lcdwrc(0x4f+0x80); lcdwrc(0x0f);//光標閃爍
                    break; case 15: flag=1; fuhao=4; //ePutstr(0,1,str3);//除號/ //lcdwrc(0xc);
 qingpin(); break; case 14: lcdwrc(0xc); ePutstr(str2); lcdwrc(0x04);//設置光標左移,屏幕不移動 
                    if(fuhao==1)//
 { lcdwrc(0x4f+0x80); c=a+b; while(c!=0)     //一位一位顯示
 { lcdwrd(0x30+c%10);//顯示結果的最後一位在0x4f的位置
                            c=c/10;//取前面的結果數據 
 } lcdwrd(0x3d); //顯示等於號=
                        a=0; b=0; flag=0; fuhao=0;//所有清除爲0
 } if(fuhao==2)   //
 { lcdwrc(0x4f+0x80); if(a>b) c=a-b; else c=b-a; while(c!=0)     //一位一位顯示
 { lcdwrd(0x30+c%10);//顯示結果的最後一位在0x4f的位置
                            c=c/10;//取前面的結果數據 
 } if(a<b)    lcdwrd(0x2d); //顯示-號
                        lcdwrd(0x3d); //顯示等於號=
                        a=0; b=0; flag=0; fuhao=0;//所有清除爲0
 } if(fuhao==3)//乘法 
 { lcdwrc(0x4f+0x80); c=a*b; while(c!=0)     //一位一位顯示
 { lcdwrd(0x30+c%10);//顯示結果的最後一位在0x4f的位置
                            c=c/10;//取前面的結果數據 
 } lcdwrd(0x3d); //顯示等於號=
                        a=0; b=0; flag=0; fuhao=0;//所有清除爲0 
 } if(fuhao==4)//除法
 { lcdwrc(0x4f+0x80); k=0; c=(long)(((float)a/b)*1000);//強制轉換爲long。
                        while(c!=0)     //一位一位顯示
 { k++; lcdwrd(0x30+c%10);//顯示結果的最後一位在0x4f的位置
                            c=c/10;//取前面的結果數據
                            if(k==3) { lcdwrd(0x2e);//顯示點
                                k=0; } } if(a/b<1)      //若是a比b小的話那麼除的結果最高位是0
 { lcdwrd(0x30); } lcdwrd(0x3d); //顯示等號
                        a=0; b=0; flag=0; fuhao=0;//所有清除爲0
 } break; } } } void main() { EA=1;//總中斷容許
    EX0=1;//容許外部中斷0中斷
    IT0=1;//選擇外部中斷0爲觸發方式
 lcdinit(); while(1) { keyscan(); } }
相關文章
相關標籤/搜索