- 單片機技術及應用(C語言版)
- 周永東主編
- 400字
- 2019-01-09 13:43:52
第二單元 單片機系統的顯示界面
綜合教學目標
學習單片機編程常用軟件的操作;掌握單片機系統中常用顯示模塊的程序設計。
主要內容
項目2.1流水燈、項目2.2電子秒表、項目2.3電子鐘、項目2.4兩級菜單的顯示界面。分別介紹了發光二極管、數碼管、字符型液晶顯示器RTC1602、點陣型液晶顯示器TG12864。
崗位技能綜合職業素質要求:學會操作相關軟件,處理燒錄芯片時的問題。
單片機系統的顯示界面主要用于顯示系統的參數設置界面、輸出結果界面、系統運行中的報警界面等。友好的人機界面將使產品大受歡迎。
本教材中選用“YL-236型單片機控制功能實訓考核裝置”作為項目實訓平臺。
YL-236裝置將單片機系統中的常用顯示模塊集中在MCU04顯示模塊上,其照片如圖2-1所示。其中包含有:8個發光二極管LED0~LED7(左下)、8個數碼管顯示器(右下)、1個RTC1602液晶顯示器(左中)、1個TG12864液晶顯示器(左上)、點陣顯示器(右上)。

圖2-1 YL-236裝置中的MCU04顯示模塊
項目實訓中可以根據需要選擇其中某個或多個顯示器來使用。
項目2.1 流水燈
2.1.1 項目描述
本項目要求采用顯示模塊MCU04中的發光二極管(LED),完成下述任務。
任務2-1-1:點亮一個發光二極管。
① 了解發光二極管工作原理。
② 點亮第一個發光二極管。
③ 掌握51單片機仿真器的使用,以及MedWin軟件操作。
任務2-1-2:實現二極管閃爍。
① 了解ms級延時C51函數。
② 用單片機控制發光二極管閃爍。
③ 掌握雙龍下載器的使用。
任務2-1-3:實現流水燈。
2.1.2 項目分析
通過項目描述,實現本項目需完成以下兩方面工作。
①硬件電路的設計:以單片機為控制中心,通過其I/O口與MCU04顯示模塊中的發光二極管連接,構成單片機控制LED電路。
② 程序的設計:用C51語言編寫單片機控制LED程序。
2.1.3 任務2-1-1 點亮一個發光二極管
一、發光二極管的工作原理
在YL-236裝置的MCU04顯示模塊中,發光二極管部分的照片如圖2-2(a)所示。
LED顯示電路工作原理分析:如圖2-2(b)所示,當LED0端口為低電平時,發光二極管D1正向導通,有電流通過D1,D1發光;當LED0端口為高電平時,發光二極管D1無法導通,D1熄滅。將單片機某I/O口與LED0端口相連,通過軟件控制該I/O輸出高或低電平就可以使D1滅或亮。圖2-2(b)中,電阻R1起限流作用,調整R1阻值大小就可以調節LED的亮度。

圖2-2 MCU04顯示模塊中的發光二極管照片與電路原理圖
二、任務2-1-1的實施
1.硬件電路的設計
本任務需要使用YL-236裝置中的三個模塊:MCU01主機模塊、MCU02電源模塊、MCU04顯示模塊。模塊接線圖如圖2-3所示,其中主機模塊的P0.0~P0.7用排線接到顯示模塊的LED0~LED7;主機模塊、顯示模塊的+5V電源端子接到電源模塊的+5V端口;主機模塊、顯示模塊的GND端子接到電源模塊的GND端口。

圖2-3 單片機控制LED顯示的模塊接線圖
2.點亮LED0的程序設計
(1)單片機P0.0的輸出電平與LED0狀態關系表
由LED工作原理可知,單片機P0.0的輸出電平與LED0狀態關系見表2-1。
表2-1 P0.0的輸出電平與LED0狀態關系表

(2)用C51語言指令控制單片機I/O口輸出
在C51語言中,使單片機P0.0輸出低電平,只需要寫語句“P0^0=0;”;使單片機P0.0輸出高電平,只需要寫語句“P0^0=1;”。
任務2-1-1的程序清單
#include<at89x52.h> //頭文件包含 sbit LED0=P0^0; //定義符號LED0為單片機的P0.0引腳 void main() { LED0=0; //P0.0輸出低電平,燈亮;P0.0輸出高電平,燈熄滅 while(1); //死循環 }
【知識鏈接一】C程序的基礎知識
1.C程序的基本結構
(1)C程序是由函數構成的。一個C源程序至少且僅包含一個main函數,也可以包含一個main函數和若干其他函數。函數體的內容由一對{}括起來,{}必須成對出現。
(2)main為“主函數”,一個C程序總是從main函數開始執行,而且不論main函數在整個程序中的位置如何。
(3)C程序書寫格式自由,一行內可以寫幾條語句,一條語句可以分寫在多行上。
(4)每條語句和數據聲明的最后必須有一個分號,分號是C語句的必要組成部分,不可缺少。既使程序中最后一條語句也應包含分號。
2.文件包含
“文件包含”是指一個文件將另外一個文件的內容全部包含進來。其格式為:
① #include<文件名稱>
② #include"文件名稱"
兩者區別在于""和< >。< >表示頭文件在編譯器(KeilC51)的安裝目錄下,一般都是編譯器自帶的頭文件;""表示頭文件在當前工程的目錄下,一般都是自己寫的頭文件,編譯器將首先查找當前目錄,如果沒找到,則在由菜單選擇項所確定的目錄中查找。
任務2-1-1的程序中,文件at89x52.h在路徑“C:\Keil\C51\INC\Atmel”中,是編譯器自帶的頭文件,它主要定義了ATMEL公司的52單片機內部相關資源名稱,以方便使用。
3.KeilC51單片機集成開發環境
KeilC51是目前使用最廣泛的基于51單片機內核的開發平臺之一,其編譯器性能較好。
4.使用KeilC的關鍵字sbit來定義位變量
第一種方法:sbit位變量名=位地址值
第二種方法:sbit位變量名=字節名稱^序號
第三種方法:sbit位變量名=字節地址值^序號
例如:sbitOV=PSW^2。
三、單片機仿真器及其軟件的使用
YL-236裝置中配備的仿真器為南京萬利公司的“insight”51單片機仿真器。YL-236裝置的主機模塊與仿真器模塊的照片如圖2-4所示。先將主機模塊上的AT89S52芯片取下,將仿真頭的引腳插在主機模塊的卡座上并卡緊,注意仿真頭上的弧形標識對準卡座的上方,方向不能插反;然后按照圖2-3連接好系統接線,并接通仿真器的電源與USB線等。

圖2-4 主機模塊與仿真器模塊照片
“insight”51單片機仿真器的配套軟件為MedWin3.0,它是一個國產的中文界面單片機集成開發平臺,比KeilC51更好操作,但其自身不帶C51編譯器,需要調用KeilC編譯器。操作步驟如下。
(1)啟動MedWin3.0,創建項目,命名后保存。
啟動MedWin3.0后,在菜單“項目管理”中選擇“新建項目”,如圖2-5所示。

圖2-5 新建項目
彈出對話框如圖2-6所示。點擊其中“設備驅動程序名”后的下拉按鈕,出現若干選項:第一項“InsightME-52HUFamilyEmulator”為上述萬利仿真器,使用仿真器時應選此項;第二項“80C51SimlatorDriver”為軟件仿真,若不連接仿真器,只是使用MedWin編譯源程序產生機器碼,可以選此項。這里選中第一項,點擊“下一步”按鈕。

圖2-6 選擇驅動程序
在第2步的對話框中,選擇如圖2-7所示編譯工具,然后點擊“下一步”按鈕。

圖2-7 選擇編譯工具
然后,在圖2-8所示對話框中輸入項目名稱led0,然后點擊“下一步”按鈕。其存儲位置一般默認在計算機最后一個盤符根目錄的“WorkDir”文件夾下。也可點擊“瀏覽”按鈕自行設定存儲路徑。

圖2-8 輸入項目名稱
然后,在圖2-9所示對話框中,設置有關參數。點擊“片內RAM長度”選項后的下拉按鈕,選擇“256”,可以充分使用AT89S52的256字節RAM空間;若單片機為AT89S51,則選擇“128”。

圖2-9 設置有關參數
點擊“操作系統內核”選項后的下拉按鈕,出現3個選項:① None(無操作系統);② RTX_51Tiny(RTX_51操作系統精簡版);③ PTX_51Full(RTX_51操作系統完整版)。本項目沒有采用操作系統,因此選①。
在圖2-9中,點擊“完成”按鈕后,項目led0就創建完畢,如圖2-10所示。

圖2-10 新建項目完成
(2)創建源程序文件并命名保存。
選中菜單“文件/新建”,創建源程序文件,如圖2-11所示。

圖2-11 創建源程序文件
選中菜單“文件/另存為”,保存為C語言程序文件格式,如圖2-12所示。

圖2-12 另存為C語言程序文件格式
(3)導入/添加C文件到項目中。
用鼠標右鍵單擊源文件組,在彈出的菜單中選擇“導入/添加文件”,如圖2-13所示。

圖2-13 導入C文件(一)
找到之前保存的C文件,并添加到項目工程的源文件組中去,如圖2-14所示。
導入源程序文件后,源文件組將出現該文件,如圖2-15所示。
(4)在剛導入的C文件中編寫C51程序。
在程序編輯區輸入C51源程序,如圖2-16所示。

圖2-14 導入C文件(二)

圖2-15 文件導入完成

圖2-16 輸入C51程序
(5)編譯C51程序。
由于MedWin3.0自身不帶編譯器,因此選中菜單“設置/設置編譯工具”,如圖2-17所示。

圖2-17 設置編譯工具(一)
在如圖2-18所示的對話框中,設置編譯工具及相關文件路徑后,點擊“確定”按鈕。

圖2-18 設置編譯工具(二)
選中菜單“項目管理/重新產生代碼并裝入”,如圖2-19所示。
用軟件編譯C51源程序,如果編譯鏈接無誤,將產生機器碼,并裝入仿真器;若編譯鏈接中發現錯誤(主要為語法錯誤),則會在構建窗口中提示錯誤種類,無法產生機器碼,此時應該改正程序中的錯誤,重新產生代碼并裝入,正確后,才能進行下一步。

圖2-19 重新產生代碼并裝入
(6)調試C51程序。
如圖2-20所示,點擊菜單“調試”后出現的下拉菜單中,可選擇以“單步”或“全速運行”等方式運行程序,并在系統中查看程序運行結果。若結果有錯(主要為邏輯錯誤),則應改正程序錯誤,重新編譯、調試,直至程序運行結果完全正確。

圖2-20 調試C51程序
本任務中,以“全速運行”方式運行程序后,將會看到LED0亮。在“調試”狀態下,選中菜單“調試/返回監控”,將退出“調試”狀態。
2.1.4 任務2-1-2 實現二極管閃爍
一、任務要求
本任務要求單片機控制LED0間隔1s閃爍,就是讓LED0燈亮1s,然后熄滅1s,反復循環不止。
二、任務2-1-2的實施
1.硬件電路的設計
硬件電路的設計與任務2-1-1相同。
2.程序的設計
(1)下面函數為ms級延時函數。
void delayms(uintx) //當晶振為12MHz,延時xms, { //用MedWin3.0的 “查看/工具欄/時間”功能測試結果: uchar i; //x小于500(ms)時,最大誤差為17μs; while(x--) //x為1000、2000、3000(ms)時,誤差分別為19、23、27μs。 for(i=0;i<123;i++); } //當晶振為11.0592MHz,延時12x/11ms。
(2)單片機控制LED0閃爍的程序流程圖如圖2-21所示。

圖2-21 單片機控制LED0閃爍的程序流程圖
任務2-1-2的程序清單
#include<at89x52.h> #define uintunsignedint //定義uint=unsignedint(無符號整型) #define ucharunsignedchar //定義uchar=unsignedchar(無符號字符型) sbit LED0=P0^0; //定義符號LED0為單片機的P0.0引腳 void delayms(uintx) //函數省略,請參考上文 void main() { while(1) //另一種解法 { LED0=0; //LED0亮1s delayms(922); //實際晶振11.0592MHz,1000*11.0592/12=922 LED0=1; //LED0滅1s delayms(922); } /* while(1) //另一種解法 { LED0=!LED0; //LED0亮1s,滅1s。效果同上 delayms(922); }*/ }
正確連接好仿真器,在MedWin3.0中建立名為led1項目,輸入上面的源程序,編譯、連接正確后,全速運行,可以看到發光二極管LED0亮1s、滅1s,不停閃爍。
【知識鏈接二】程序流程圖與程序的構成等
1.程序流程圖
程序流程圖是用一些圖框來表示各種操作,直觀形象,易于理解。美國國家標準化協會ANSI(AmericanNationalStandardInstitute)規定的一些常用的流程圖符號如知識鏈接圖2-1所示。

知識鏈接圖2-1
2.程序的構成
程序=數據結構+算法
① 對數據的描述,在程序中指定數據的類型和數據的組織形式,即數據結構。
② 對操作的描述,即操作步驟,也就是算法。
3.邏輯運算符“!”的作用
!為邏輯非運算符,其作用是將邏輯量或位變量的值取反,即原來為1的,變為0;原來為0的,變為1。
三、單片機程序的燒錄
程序調試成功后,下一步要把程序代碼下載(燒錄)到單片機芯片AT89S52中。
YL-236裝置中配備了雙龍ISP下載器。按照其光盤里產品說明書上的步驟,安裝好相關軟件后,第一次用USB線連接雙龍ISP下載器和計算機時,會在電腦屏幕上看到“已經找到新硬件”的提示,選擇“自動安裝軟件”,計算機會自動安裝好新增的設備。
單片機程序燒錄的操作步驟如下。
① 下載程序前,首先關閉系統電源,將仿真頭取下;然后將AT89S52的引腳插在主機模塊的卡座上并卡緊,注意單片機芯片上的弧形標識對準卡座的上方,方向不能插反。
② 用排線連接雙龍ISP下載器與主機模塊后,再接通雙龍ISP下載器的USB線。
③ 啟動雙龍ISP下載器軟件后,出現如圖2-22所示界面。

圖2-22 雙龍ISP下載器軟件界面
④ 如圖2-22所示,首先在界面上部各選項中,正確選擇“下載端口”、“下載速度”、“芯片型號”等,然后點擊“FLASH存貯器”選項右邊的“Flash”按鈕,添加要燒錄的機器碼文件(一般為HEX文件),如圖2-23所示。
⑤ 添加HEX文件后,點擊圖2-22中的“編程”按鈕,軟件會自動燒錄機器碼程序到AT89S52單片機中。但燒錄有時會失敗,可能是由于在設計的目標系統電路中,P1.5、P1.6、P1.7的電平被鉗制住(例如:作為輸入端口,而從外界輸入電平為0V等),ISP下載器無法通過這3個引腳下載程序,這時,可以將主機模塊上P1.5、P1.6、P1.7端子上的導線拔除,再下載程序。下載失敗,有時是因為目標系統自身電源未供應,這時可以通過ISP下載器給目標系統供電,然后再完成下載,相關設置操作如圖2-24所示。

圖2-23 添加機器碼文件

圖2-24 給目標系統供電
⑥ 本任務中,正確燒錄“LED0閃爍”的程序代碼后,先斷開雙龍ISP下載器的USB線,再斷開雙龍ISP下載器與主機模塊的排線,打開系統電源后,即可看到LED0不停閃爍。
2.1.5 任務2-1-3 實現流水燈
一、任務要求
單片機控制8個發光二極管從LED0到LED7間隔1s依次點亮(亮1s后熄滅,下一個LED點亮),當LED7亮1s后,又從LED0開始點亮,如此循環不止,視覺效果上像一個亮的燈從右到左流動。
二、任務2-1-3的實施
1.硬件電路的設計
硬件電路的設計與任務2-1-1相同。
2.程序的設計
(1)流水燈形成原理。
LED形成流水燈的效果實質是按順序依次點亮發光二極管,其發光過程見表2-2。
表2-2 流水燈發光過程表

注:表中數據0或1,表示該引腳輸入低或高電平,以使相應LED亮或滅。
(2)本教材提供兩種方法實現單片機控制LED流水燈的程序清單,方法二的流程圖如圖2-25所示。

圖2-25 單片機控制LED流水燈的程序流程圖
任務2-1-3的程序清單
#include<at89x52.h> #define uintunsignedint //定義uint=unsignedint(無符號整型) #define ucharunsignedchar //定義uchar=unsignedchar(無符號字符型) sbit LED0=P0^0; //定義符號LED0為單片機的P0.0引腳 sbit LED1=P0^1; //定義符號LED1為單片機的P0.1引腳 sbit LED2=P0^2; //定義符號LED2為單片機的P0.2引腳 sbit LED3=P0^3; //定義符號LED3為單片機的P0.3引腳 sbit LED4=P0^4; //定義符號LED4為單片機的P0.4引腳 sbit LED5=P0^5; //定義符號LED5為單片機的P0.5引腳 sbit LED6=P0^6; //定義符號LED6為單片機的P0.6引腳 sbit LED7=P0^7; //定義符號LED7為單片機的P0.7引腳 void delayms(uintx) //函數省略,請參考任務2-1-2 void main() //方法一 { while(1) //方法一比較容易想到 { P0=0xff; //熄滅所有的LED LED0=0; //點亮LED0 delayms(922); //實際晶振為11.0592MHz,延時1s P0=0xff; LED1=0; //點亮LED1 delayms(922); P0=0xff; LED2=0; //點亮LED2 delayms(922); P0=0xff; LED3=0; //點亮LED3 delayms(922); P0=0xff; LED4=0; //點亮LED4 delayms(922); P0=0xff; LED5=0; //點亮LED5 delayms(922); P0=0xff; LED6=0; //點亮LED6 delayms(922); P0=0xff; LED7=0; //點亮LED7 delayms(922); } } void main() //方法二 { uchar num,i; //定義2個變量 while(1) //方法二比較簡潔 { num=0xfe; //準備點亮第一個燈(LED0) for(i=0;i<8;i++) //8個LED,共循環8遍 { P0=num; //點亮某個LED delayms(922); //延時1s num=num<<1|0x01; //準備下一個LED } } } //0xfe:點亮LED0,0xfd:點亮LED1,0xfb:點亮LED2,0xf7:點亮LED3, //0xef:點亮LED4,0xdf:點亮LED5,0xbf:點亮LED6,0x7f:點亮LED7
正確連接好仿真器,在MedWin3.0中建立名為led2的項目,輸入上面的源程序(main函數在方法一與方法二中選一個),編譯、連接正確后,全速運行,可以看到一個亮的燈從右至左流動。關閉系統電源后,正確燒錄“流水燈”的程序代碼到單片機中,取下雙龍ISP下載器,打開系統電源后,即可看到同樣的結果。
在本書后面各任務中,請參考任務2-1-1~2-1-2中介紹的方法正確使用仿真器和雙龍ISP下載器調試和下載程序,只有程序下載到單片機中并運行正確后,方為任務完成。
【知識鏈接三】C51的數據結構
一、常量與變量
C語言的基本數據類型,按其取值是否可改變分為常量和變量兩種。在程序執行過程中,其值不發生改變的量稱為常量,取值可變的量稱為變量。
1.數值常量
數值常量也稱為常數,例如12、-5.3、′c′、′abc′等。其中12為整型常量,-5.3為浮點型常量,′c′為字符型常量,"abc"為字符串常量。
2.符號常量
在C語言中,可以用一個標識符(標識符的定義見下文)來表示一個常量,稱之為符號常量。符號常量在使用之前必須先定義,其一般形式為:“#define標識符 常量”。
其中,#define也是一條預處理命令,稱為宏定義命令,其功能是把該標識符定義為其后的常量值。一經定義,以后在程序中所有出現該標識符的地方均代之以該常量值。
二、變量
值可以改變的量稱為變量。一個變量應該有一個名字,在內存中占據一定的存儲單元,在該存儲單元中存放變量的值。請注意:變量名與變量值的區別如知識鏈接圖2-2所示。

知識鏈接圖2-2
在C語言中,要求對所有用到的變量做強制定義,也就是“先定義,后使用”。
在C語言中用來標識變量名、符號常量名、函數名、數組名、類型名等的有效字符序列稱為標識符。簡單地說,標識符就是一個名字。
C語言規定標識符只能由字母、數字和下劃線三種字符組成,且第一個字符必須為字母或下劃線。要注意的是,C語言中大寫字母與小寫字母被認為是兩個不同的字符,即Sum與sum是兩個不同的標識符。
1.整型變量
整型變量的基本類型符為int,在int之前可以根據需要分別加上修飾符。在KeilC中規定,基本整型數據在存儲器中占用2個字節(即16bit)、長整型占用4個字節的存儲空間。知識鏈接表2-1列出了各種整型數據的有關數據。
知識鏈接表2-1 整數類型的有關數據

2.字符型變量
字符型變量的基本類型符為char,其表達的范圍是-128~+127;字符型變量只有一個修飾符unsigned,即無符號數,而加上了unsigned后,其表達的范圍變為0~255。
3.浮點型變量
在8位單片機中,盡量不要用浮點型數據,這里不做介紹。
4.KeilC51特有的變量類型
(1)位型變量
位型變量是使用一個二進制位來存放數據,其值只有“0”和“1”兩種。位型變量的定義和其他數據類型一樣,關鍵字為bit。例如:
bita=0; //定義一個位變量,并賦初值為0
(2)sfr型變量
80C51內部有一些特殊功能寄存器(sfr)。為定義、存取這些特殊功能寄存器,C51增加了sfr型數據,相應也增加了sfr、sfr16和sbit這3個關鍵字。例如:
sfrP0=0x80; //定義8位特殊功能寄存器P0 sfr16DPTR=0x82; //定義16位特殊功能寄存器DPTR
三、變量的存儲類型
在變量前加一個修飾符可以指定變量的存儲器類型。
① data:片內RAM低128B,直接尋址訪問,存儲類型默認為data。② bata:片內RAM中20H~2FH,可以位尋址。
③ idata:片內RAM中256B,間接尋址訪問。
④ xata:片外RAM中或片外I/O口擴展。
⑤ code:ROM中一般為固定數據表格,用MOVC指令查表訪問。
例如:
unsignedcharbdataflag; sbit F0=flag∧0; sbit F1=flag∧1;