| 51系列單片機C語言入門學習 文章長度[ ] 加入時間[ 2007/7/14] 更新時間[ 2025/6/25 2:15:48] 級別[ 0] [ 評論] [ 收藏]
|
|
學習單片機實在不是件易事,一來要購買高價格的編程器,仿真器,二來要學習編程語言,還有眾多種類的單片機選擇真是件讓人頭腦的事。在眾多單片機中51架構的芯片風行很久,學習資料也相對很多,是初學的較好的選擇之一。51的編程語言常用的有二種,一種是匯編語言,一種是C語言。匯編語言的機器代碼生成效率很高但可讀性卻并不強,復雜一點的程序就更是難讀懂,而C語言在大多數情況下其機器代碼生成效率和匯編語言相當,但可讀性和可移植性卻遠遠超過匯編語言,而且C語言還可以嵌入匯編來解決高時效性的代碼編寫問題。對于開發周期來說,中大型的軟件編寫用C語言的開發周期通常要小于匯編語言很多。綜合以上C語言的優點,我在學習時選擇了C語言。以后的教程也只是我在學習過程中的一些學習筆記和隨筆,在這里加以整理和修改,希望和大家一起分享,一起交流,一起學習,一起進步。 *注:可以肯定的說這個教程只是為初學或入門者準備的,筆者本人也只是菜鳥一只,有望各位大俠高手指點錯誤提出建議! |
單片機與電子制作網站為廣大網友提供無代碼限制的KEIL C6.2的軟件 |
第一課 建立您的第一個C項目 |
使用C語言肯定要使用到C編譯器,以便把寫好的C程序編譯為機器碼,這樣單片機才能執行編寫好的程序。KEIL uVISION2是眾多單片機應用開發軟件中優秀的軟件之一,它支持眾多不同公司的MCS51架構的芯片,它集編輯,編譯,仿真等于一體,同時還支持,PLM,匯編和C語言的程序設計,它的界面和常用的微軟VC++的界面相似,界面友好,易學易用,在調試程序,軟件仿真方面也有很強大的功能。因此很多開發51應用的工程師或普通的單片機愛好者,都對它十分喜歡。 以上簡單介紹了KEIL51軟件,要使用KEIL51軟件,必需先要安裝它。KEIL51是一個商業的軟件,對于我們這些普通愛好者可以到KEIL中國代理周立功公司的網站上下載一份能編譯2K的DEMO版軟件,基本可以滿足一般的個人學習和小型應用的開發。(安裝的方法和普通軟件相當這里就不做介紹了) 安裝好后,你是不是迫不及待的想建立自己的第一個C程序項目呢?下面就讓我們一起來建立一個小程序項目吧;蛟S你手中還沒有一塊實驗板,甚至沒有一塊單片機,不過沒有關系我們可以通過KEIL軟件仿真看到程序運行的結果。 首先當然是運行KEIL51軟件。怎么打開?噢,天!那你要從頭學電腦了。呵呵,開個玩笑,這個問題我想讀者們也不會提的了:P。運行幾秒后,出現如圖1-1的屏幕。 |
 圖1-1 啟動時的屏幕 |
接著按下面的步驟建立您的第一個項目: 。1)點擊Project菜單,選擇彈出的下拉式菜單中的New Project,如圖1-2。接著彈出一個標準Windows文件對話窗口,如圖1-3,這個東東想必大家是見了N次的了,用法技巧也不是這里要說的,以后的章節中出現類似情況將不再說明。在"文件名"中輸入您的第一個C程序項目名稱,這里我們用"test",這是筆者慣用的名稱,大家不必照搬就是了,只要符合Windows文件規則的文件名都行。"保存"后的文件擴展名為uv2,這是KEIL uVision2項目文件擴展名,以后我們可以直接點擊此文件以打開先前做的項目。 |
 圖1-2 New Project菜單 |
 圖1-3 文件窗口 |
。2)選擇所要的單片機,這里我們選擇常用的Ateml公司的AT89C51。此時屏幕如圖1-4所示。AT89C51有什么功能、特點呢?不用急,看圖中右邊有簡單的介紹,稍后的章節會作較詳細的介紹。完成上面步驟后,我們就可以進行程序的編寫了。 。3)首先我們要在項目中創建新的程序文件或加入舊程序文件。如果你沒有現成的程序,那么就要新建一個程序文件。在KEIL中有一些程序的Demo,在這里我們還是以一個C程序為例介紹如何新建一個C程序和如何加到您的第一個項目中吧。點擊圖1-5中1的新建文件的快捷按鈕,在2中出現一個新的文字編輯窗口,這個操作也可以通過菜單File-New或快捷鍵Ctrl+N來實現。好了,現在可以編寫程序了,光標已出現在文本編輯窗口中,等待我們的輸入了。第一程序嘛,寫個簡單明了的吧。下面是經典的一段程序,呵,如果你看過別的程序書也許也有類似的程序:
#include <AT89X51.H> #include <stdio.h>
void main(void) { SCON = 0x50; //串口方式1,允許接收 TMOD = 0x20; //定時器1定時方式2 TCON = 0x40; //設定時器1開始計數 TH1 = 0xE8; //11.0592MHz 1200波特率 TL1 = 0xE8; TI = 1; TR1 = 1; //啟動定時器
while(1) { printf ("Hello World!\n"); //顯示Hello World } } |
 圖1-4選取芯片  圖1-5新建程序文件 |
這段程序的功能是不斷從串口輸出"Hello World!"字符,我們先不管程序的語法和意思吧,先看看如何把它加入到項目中和如何編譯試運行。 。4)點擊圖1-5中的3保存新建的程序,也可以用菜單File-Save或快捷鍵Ctrl+S進行保存。因是新文件所以保存時會彈出類似圖1-3的文件操作窗口,我們把第一個程序命名為test1.c,保存在項目所在的目錄中,這時你會發現程序單詞有了不同的顏色,說明KEIL的C語法檢查生效了。如圖1-6鼠標在屏幕左邊的Source Group1文件夾圖標上右擊彈出菜單,在這里可以做在項目中增加減少文件等操作。我們?quot;Add File to Group 'Source Group 1'"彈出文件窗口,選擇剛剛保存的文件,按ADD按鈕,關閉文件窗,程序文件已加到項目中了。這時在Source Group1文件夾圖標左邊出現了一個小+號說明,文件組中有了文件,點擊它可以展開查看。 |
 圖1-6把文件加入到項目文件組中 |
。5)C程序文件已被我們加到了項目中了,下面就剩下編譯運行了。這個項目我們只是用做學習新建程序項目和編譯運行仿真的基本方法,所以使用軟件默認的編譯設置,它不會生成用于芯片燒寫的HEX文件,如何設置生成HEX文件就請看下面的第三課。我們先來看圖1-7吧,圖中1、2、3都是編譯按鈕,不同是1是用于編譯單個文件。2是編譯當前項目,如果先前編譯過一次之后文件沒有做動編輯改動,這時再點擊是不會再次重新編譯的。3是重新編譯,每點擊一次均會再次編譯鏈接一次,不管程序是否有改動。在3右邊的是停止編譯按鈕,只有點擊了前三個中的任一個,停止按鈕才會生效。5是菜單中的它們,我個人就不習慣用它了。嘿嘿,這個項目只有一個文件,你按123中的一個都可以編譯。按了?好快哦,呵呵。在4中可以看到編譯的錯誤信息和使用的系統資源情況等,以后我們要查錯就靠它了。6是有一個小放大鏡的按鈕,這就是開啟\關閉調試模式的按鈕,它也存在于菜單Debug-Start\Stop Debug Session,快捷鍵為Ctrl+F5。 |
 圖1-7編譯程序 |
(6)進入調試模式,軟件窗口樣式大致如圖1-8所示。圖中1為運行,當程序處于停止狀態時才有效,2為停止,程序處于運行狀態時才有效。3是復位,模擬芯片的復位,程序回到最開頭處執行。按4我們可以打開5中的串行調試窗口,這個窗口我們可以看到從51芯片的串行口輸入輸出的字符,這里的第一個項目也正是在這里看運行結果。這些在菜單中也有,這里不再一一介紹大家不妨找找看,其它的功能也會在后面的課程中慢慢介紹。首先按4打開串行調試窗口,再按運行鍵,這時就可以看到串行調試窗口中不斷的打?quot;Hello World!"。呵呵,是不是不難呀?這樣就完成了您的第一個C項目。最后我們要停止程序運行回到文件編輯模式中,就要先按停止按鈕再按開啟\關閉調試模式按鈕。然后我們就可以進行關閉KEIL等相關操作了。 到此為止,第一課已經完結了,初步學習了一些KEIL uVision2的項目文件創建、編譯、運行和軟件仿真的基本操作方法。其中一直有提到一些功能的快捷鍵的使用,的確在實際的開發應用中快捷鍵的運用可以大大提高工作的效率,建議大家多多使用,還有就是對這里所講的操作方法舉一反三用于類似的操作中。 |
 圖1-8調試運行程序 |
第二課 初步認識51芯片 |
上一課我們的第一個項目完成了,可能有懂C語言的朋友會說,"這和PC機上的C語言沒有多大的區別呀"。的確沒有太大的區別,C語言只是一種程序語言的統稱,針對不同的處理器相關的C語言都會有一些細節的改變。編寫PC機的C程序時,如要對硬件編程你就必須對硬件要有一定的認識,51單片機編程就更是如此,因它的開發應用是不可與硬件脫節的,所以我們先要來初步認識一下51苾片的結構和引腳功能。MSC51架構的芯片種類很多,具體特點和功能不盡相同(在以后編寫的附錄中會加入常用的一些51芯片的資料列表),在此后的教程中就以Atmel公司的AT89C51和AT89C2051為中心對象來進行學習,兩者是AT89系列的典型代表,在愛好者中使用相當的多,應用資料很多,價格便宜,是初學51的首選芯片。嘿嘿,口水多多有點賣廣告之嫌了。:P |
|
圖2-1 AT89C51和AT89C2051引腳功能圖
|
AT89C51 |
AT89C2051 |
4KB可編程Flash存儲器(可擦寫1000次) |
2KB可編程Flash存儲器(可擦寫1000次) |
三級程序存儲器保密 |
兩級程序存儲器保密 |
靜態工作頻率:0Hz-24MHz |
靜態工作頻率:0Hz-24MHz |
128字節內部RAM |
128字節內部RAM |
2個16位定時/計數器 |
2個16位定時/計數器 |
一個串行通訊口 |
一個串行通訊口 |
6個中斷源 |
6個中斷源 |
32條I/O引線 |
15條I/O引線 |
片內時種振蕩器 |
1個片內模擬比較器 | |
表2-1 AT89C51和AT89C2051主要性能表
|
圖2-1中是AT89C51和AT89C2051的引腳功能圖。而表2-1中則是它們的主要性能表。以上可以看出它們是大體相同的,由于AT89C2051的IO線很少,導致它無法外加RAM和程序ROM,片內Flash存儲器也少,但它的體積比AT89C51小很多,以后大家可根據實際需要來選用。它們各有其特點但其核心是一樣的,下面就來看看AT89C51的引腳具體功能。 1.電源引腳 Vcc 40 電源端 GND 20 接地端 。ぷ麟妷簽5V,另有AT89LV51工作電壓則是2.7-6V, 引腳功能一樣。
2.外接晶體引腳 |
|
圖2-2 外接晶體引腳
|
XTAL1 19 XTAL2 18 XTAL1是片內振蕩器的反相放大器輸入端,XTAL2則是輸出端,使用外部振蕩器時,外部振蕩信號應直接加到XTAL1,而XTAL2懸空。內部方式時,時鐘發生器對振蕩脈沖二分頻,如晶振為12MHz,時鐘頻率就為6MHz。晶振的頻率可以在1MHz-24MHz內選擇。電容取30PF左右。 。吞柾瑯訛锳T89C51的芯片,在其后面還有頻率編號,有12,16,20,24MHz可選。大家在購買和選用時要注意了。如AT89C51 24PC就是最高振蕩頻率為24MHz,40P6封裝的普通商用芯片。
3.復位 RST 9 在振蕩器運行時,有兩個機器周期(24個振蕩周期)以上的高電平出現在此引腿時,將使單片機復位,只要這個腳保持高電平,51芯片便循環復位。復位后P0-P3口均置1引腳表現為高電平,程序計數器和特殊功能寄存器SFR全部清零。當復位腳由高電平變為低電平時,芯片為ROM的00H處開始運行程序。常用的復位電路如圖2-3所示。 。獜臀徊僮鞑粫䦟炔縍AM有所影響。
|
|
圖2-3 常用復位電路
|
4.輸入輸出引腳 (1) P0端口[P0.0-P0.7] P0是一個8位漏極開路型雙向I/O端口,端口置1(對端口寫1)時作高阻抗輸入端。作為輸出口時能驅動8個TTL。 對內部Flash程序存儲器編程時,接收指令字節;校驗程序時輸出指令字節,要求外接上拉電阻。 在訪問外部程序和外部數據存儲器時,P0口是分時轉換的地址(低8位)/數據總線,訪問期間內部的上拉電阻起作用。 (2) P1端口[P1.0-P1.7] P1是一個帶有內部上拉電阻的8位雙向I/0端口。輸出時可驅動4個TTL。端口置1時,內部上拉電阻將端口拉到高電平,作輸入用。 對內部Flash程序存儲器編程時,接收低8位地址信息。 (3) P2端口[P2.0-P2.7] P2是一個帶有內部上拉電阻的8位雙向I/0端口。輸出時可驅動4個TTL。端口置1時,內部上拉電阻將端口拉到高電平,作輸入用。 對內部Flash程序存儲器編程時,接收高8位地址和控制信息。 在訪問外部程序和16位外部數據存儲器時,P2口送出高8位地址。而在訪問8位地址的外部數據存儲器時其引腳上的內容在此期間不會改變。 (4) P3端口[P3.0-P3.7] P2是一個帶有內部上拉電阻的8位雙向I/0端口。輸出時可驅動4個TTL。端口置1時,內部上拉電阻將端口拉到高電平,作輸入用。 對內部Flash程序存儲器編程時,接控制信息。除此之外P3端口還用于一些專門功能,具體請看 表2-2.。 。狿1-3端口在做輸入使用時,因內部有上接電阻,被外部拉低的引腳會輸出一定的電流。
|
P3引腳 |
兼用功能 |
P3.0 |
串行通訊輸入(RXD) |
P3.1 |
串行通訊輸出(TXD) |
P3.2 |
外部中斷0( INT0) |
P3.3 |
外部中斷1(INT1) |
P3.4 |
定時器0輸入(T0) |
P3.5 |
定時器1輸入(T1) |
P3.6 |
外部數據存儲器寫選通WR |
P3.7 |
外部數據存儲器寫選通RD | |
表2-2 P3端口引腳兼用功能表
|
呼!一口氣說了那么多,停一下吧。嗯,什么?什么叫上拉電阻?上拉電阻簡單來說就是把電平拉高,通常用4.7-10K的電阻接到Vcc電源,下拉電阻則是把電平拉低,電阻接到GND地線上。具體說明也不是這里要討論的,接下來還是接著看其它的引腳功能吧。 5.其它的控制或復用引腳 (1) ALE/PROG 30 訪問外部存儲器時,ALE(地址鎖存允許)的輸出用于鎖存地址的低位字節。即使不訪問外部存儲器,ALE端仍以不變的頻率輸出脈沖信號(此頻率是振蕩器頻率的1/6)。在訪問外部數據存儲器時,出現一個ALE脈沖。對Flash存儲器編程時,這個引腳用于輸入編程脈沖PROG (2) PSEN 29 該引是外部程序存儲器的選通信號輸出端。當AT89C51由外部程序存儲器取指令或常數時,每個機器周期輸出2個脈沖即兩次有效。但訪問外部數據存儲器時,將不會有脈沖輸出。 (3) EA/Vpp 31 外部訪問允許端。當該引腳訪問外部程序存儲器時,應輸入低電平。要使AT89C51只訪問外部程序存儲器(地址為0000H-FFFFH),這時該引腳必須保持低電平。對Flash存儲器編程時,用于施加Vpp編程電壓。Vpp電壓有兩種,類似芯片最大頻率值要根據附加的編號或芯片內的特征字決定。具體如表2-3所列。
|
|
Vpp = 12V |
Vpp = 5V |
印刷在芯片面上的型號 |
AT89C51
xxxx
YYWW |
AT89LV51
xxxx
YYWW |
AT89C51
xxxx-5
YYWW |
AT89LV51
xxxx-5
YYWW |
片內特征字 |
030H=1EH |
030H=1EH |
030H=1EH |
030H=1EH |
031H=51H |
031H=61H |
031H=51H |
031H=61H |
032H=FFH |
032H=FFH |
032H=05H |
032H=05H | |
表2-3 Vpp與芯片型號和片內特征字的關系
|
看到這您對AT89C51引腳的功能應該有了一定的了解了,引腳在編程和校驗時的時序我們在這里就不做詳細的探討,通常情況下我們也沒有必要去撐握它,除非你想自己開發編程器。下來的課程我們要開始以一些簡單的實例來講述C程序的語法和編寫方法技巧,中間穿插相關的硬件知識如串口,中斷的用法等等。
|
第三課 生成HEX文件和最小化系統 |
在開始C語言的主要內容時,我們先來看看如何用KEIL uVISION2來編譯生成用于燒寫芯片的HEX文件。HEX文件格式是Intel公司提出的按地址排列的數據信息,數據寬度為字節,所有數據使用16進制數字表示, 常用來保存單片機或其他處理器的目標程序代碼。它保存物理程序存儲區中的目標代碼映象。一般的編程器都支持這種格式。我們先來打開第一課做的第一項目,打開它的所在目錄,找到test.Uv2的文件就可以打開先前的項目了。然后右擊圖3-1中的1項目文件夾,彈出項目功能菜單,選Options for Target'Target1',彈出項目選項設置窗口,同樣先選中項目文件夾圖標,這時在Project菜單中也有一樣的菜單可選。打開項目選項窗口,轉到Output選項頁圖3-2所示,圖中1是選擇編譯輸出的路徑,2是設置編譯輸出生成的文件名,3則是決定是否要創建HEX文件,選中它就可以輸出HEX文件到指定的路徑中。選好了?好,我們再將它重新編譯一次,很快在編譯信息窗口中就顯示HEX文件創建到指定的路徑中了,如圖3-3。這樣我們就可用自己的編程器所附帶的軟件去讀取并燒到芯片了,再用實驗板看結果,至于編程器或仿真器品種繁多具體方法就看它的說明書了,這里也不做討論。 (技巧:一、在圖3-1中的1里的項目文件樹形目錄中,先選中對象,再單擊它就可對它進行重命名操作,雙擊文件圖標便可打開文件。二、在Project下拉菜單的最下方有最近編輯過的項目路徑保存,這里可以快速打開最近在編輯的項目。) |
 圖3-1項目功能菜單  圖3-2 項目選項窗口  圖3-3 編譯信息窗口 |
或許您已把編譯好的文件燒到了芯片上,如果您購買或自制了帶串口輸出元件的學習實驗板,那您就可以把串口和PC機串口相聯用串口調試軟件或Windows的超級終端,將其波特率設為1200,就可以看到不停輸出的"Hello World!"字樣。也許您還沒有實驗板,那這里先說說AT89C51的最小化系統,再以一實例程序驗證最小化系統是否在運行,這個最小化系統也易于自制用于實驗。圖3-4便是AT89C51的最小化系統,不過為了讓我們可以看出它是在運行的,我加了一個電阻和一個LED,用以顯示它的狀態,晶振可以根據自己的情況使用,一般實驗板上是用11.0592MHz或12MHz,使用前者的好外是可以產生標準的串口波特率,后者則一個機器周期為1微秒,便于做精確定時。在自己做實驗里,注意的是VCC是+5V的,不能高于此值,否則將損壞單片機,太低則不能正常工作。在31腳要接高電平,這樣我們才能執行片內的程序,如接低電平則使用片外的程序存儲器。下面,我們建一個新的項目名為OneLED來驗證最小化系統是否可以工作(所有的例程都可在我的主頁下面下載到,網址:http://cdle.yeah.net 或http://cdle.126.com )。程序如下: #include <AT89X51.h> //預處理命令
void main(void) //主函數名 { //這是第一種注釋方式 unsigned int a; //定義變量a為int類型 /* 這是第二種注釋方式 */ do{ //do while組成循環 for (a=0; a<50000; a++); //這是一個循環 P1_0 = 0; //設P1.0口為低電平,點亮LED for (a=0; a<50000; a++); //這是一個循環 P1_0 = 1; //設P1.0口為高電平,熄滅LED } while(1); }
|
 圖3-4 AT89C51最小化系統 |
這里先講講KEIL C編譯器所支持的注釋語句。一種是以"http://"符號開始的語句,符號之后的語句都被視為注釋,直到有回車換行。另一種是在"/*"和"*/"符號之內的為注釋。注釋不會被C編譯器所編譯。一個C應用程序中應有一個main主函數,main函數可以調用別的功能函數,但其它功能函數不允許調用main函數。不論main函數放在程序中的那個位置,總是先被執行。用上面學到的知識編譯寫好的OneLED程序,并把它燒到剛做好的最小化系統中。上電,剛開始時LED是不亮的(因為上電復位后所有的IO口都置1引腳為高電平),然后延時一段時間(for (a=0; a<50000; a++)這句在運行),LED亮,再延時,LED熄滅,然后交替亮、滅。第一個真正的小應用就做完,呵呵,先不要管它是否實用哦。如果沒有這樣的效果那么您就要認真檢查一下電路或編譯燒寫的步驟了。 |
第四課 數據類型 |
先來簡單說說C語言的標識符和關鍵字。標識符是用來標識源程序中某個對象的名字的,這些對象可以是語句、數據類型、函數、變量、數組等等。C語言是大小字敏感的一種高級語言,如果我們要定義一個定時器1,可以寫做"Timer1",如果程序中有"TIMER1",那么這兩個是完全不同定義的標識符。標識符由字符串,數字和下劃線等組成,注意的是第一個字符必須是字母或下劃線,如"1Timer"是錯誤的,編譯時便會有錯誤提示。有些編譯系統專用的標識符是以下劃線開頭,所以一般不要以下劃線開頭命名標識符。標識符在命名時應當簡單,含義清晰,這樣有助于閱讀理解程序。在C51編譯器中,只支持標識符的前32位為有效標識,一般情況下也足夠用了,除非你要寫天書:P。 關鍵字則是編程語言保留的特殊標識符,它們具有固定名稱和含義,在程序編寫中不允許標識符與關鍵字相同。在KEIL uVision2中的關鍵字除了有ANSI C標準的32個關鍵字外還根據51單片機的特點擴展了相關的關鍵字。其實在KEIL uVision2的文本編輯器中編寫C程序,系統可以把保留字以不同顏色顯示,缺省顏色為天藍色。 先看表4-1,表中列出了KEIL uVision2 C51編譯器所支持的數據類型。在標準C語言中基本的數據類型為char,int,short,long,float和double,而在C51編譯器中int和short相同,float和double相同,這里就不列出說明了。下面來看看它們的具體定義:
|
數據類型 |
長 度 |
值 域 |
unsigned char |
單字節 |
0~255 |
signed char |
單字節 |
-128~+127 |
unsigned int |
雙字節 |
0~65535 |
signed int |
雙字節 |
-32768~+32767 |
unsigned long |
四字節 |
0~4294967295 |
signed long |
四字節 |
-2147483648~+2147483647 |
float |
四字節 |
±1.175494E-38~±3.402823E+38 |
* |
1~3字節 |
對象的地址 |
bit |
位 |
0或1 |
sfr |
單字節 |
0~255 |
sfr16 |
雙字節 |
0~65535 |
sbit |
位 |
0或1 |
表4-1 KEIL uVision2 C51編譯器所支持的數據類型
|
1. char字符類型 char類型的長度是一個字節,通常用于定義處理字符數據的變量或常量。分無符號字符類型unsigned char和有符號字符類型signed char,默認值為signed char類型。unsigned char類型用字節中所有的位來表示數值,所可以表達的數值范圍是0~255。signed char類型用字節中最高位字節表示數據的符號,"0"表示正數,"1"表示負數,負數用補碼表示。所能表示的數值范圍是-128~+127。unsigned char常用于處理ASCII字符或用于處理小于或等于255的整型數。 *正數的補碼與原碼相同,負二進制數的補碼等于它的絕對值按位取反后加1。
2. int整型 int整型長度為兩個字節,用于存放一個雙字節數據。分有符號int整型數signed int和無符號整型數unsigned int,默認值為signed int類型。signed int表示的數值范圍是-32768~+32767,字節中最高位表示數據的符號,"0"表示正數,"1"表示負數。unsigned int表示的數值范圍是0~65535。
好了,先停一下吧,我們來寫個小程序看看unsigned char和unsigned int用于延時的不同效果,說明它們的長度是不同的,呵,盡管它并沒有實際的應用意義,這里我們學習它們的用法就行。依舊用我們上一課的最小化系統做實驗,不過要加多一個電阻和LED,如圖4-1。實驗中用D1的點亮表明正在用unsigned int數值延時,用D2點亮表明正在用unsigned char數值延時。 |
 圖4-1 第4課實驗用電路 |
我們把這個項目稱為TwoLED,實驗程序如下: #include <AT89X51.h> //預處理命令
void main(void) //主函數名 { unsigned int a; //定義變量a為unsigned int類型 unsigned char b; //定義變量b為unsigned char類型
do { //do while組成循環 for (a=0; a<65535; a++) P1_0 = 0; //65535次設P1.0口為低電平,點亮LED P1_0 = 1; //設P1.0口為高電平,熄滅LED
for (a=0; a<30000; a++); //空循環
for (b=0; b<255; b++) P1_1 = 0; //255次設P1.1口為低電平,點亮LED P1_1 = 1; //設P1.1口為高電平,熄滅LED
for (a=0; a<30000; a++); //空循環 } while(1); }
同樣編譯燒寫,上電運行您就可以看到結果了。很明顯D1點亮的時間長于D2點亮的時間。程序中的循環延時時間并不是很好確定,并不太適合要求精確延時的場合,關于這方面我們以后也會做討論。這里必須要講的是,當定義一個變量為特定的數據類型時,在程序使用該變量不應使它的值超過數據類型的值域。如本例中的變量b不能賦超出0~255的值,如for (b=0; b<255; b++)改為for (b=0; b<256; b++),編譯是可以通過的,但運行時就會有問題出現,就是說b的值永遠都是小于256的,所以無法跳出循環執行下一句P1_1 = 1,從而造成死循環。同理a的值不應超出0~65535。大家可以燒片看看實驗的運行結果,同樣軟件仿真也是可以看到結果的。
3. long長整型 long長整型長度為四個字節,用于存放一個四字節數據。分有符號long長整型signed long和無符號長整型unsigned long,默認值為signed long類型。signed int表示的數值范圍是-2147483648~+2147483647,字節中最高位表示數據的符號,"0"表示正數,"1"表示負數。unsigned long表示的數值范圍是0~4294967295。
4. float浮點型 float浮點型在十進制中具有7位有效數字,是符合IEEE-754標準的單精度浮點型數據,占用四個字節。因浮點數的結構較復雜在以后的章節中再做詳細的討論。 5.* 指針型 指針型本身就是一個變量,在這個變量中存放的指向另一個數據的地址。這個指針變量要占據一定的內存單元,對不同的處理器長度也不盡相同,在C51中它的長度一般為1~3個字節。指針變量也具有類型,在以后的課程中有專門一課做探討,這里就不多說了。
6. bit位標量 bit位標量是C51編譯器的一種擴充數據類型,利用它可定義一個位標量,但不能定義位指針,也不能定義位數組。它的值是一個二進制位,不是0就是1,類似一些高級語言中的Boolean類型中的True和False。
7. sfr特殊功能寄存器 sfr也是一種擴充數據類型,點用一個內存單元,值域為0~255。利用它可以訪問51單片機內部的所有特殊功能寄存器。如用sfr P1 = 0x90這一句定P1為P1端口在片內的寄存器,在后面的語句中我們用以用P1 = 255(對P1端口的所有引腳置高電平)之類的語句來操作特殊功能寄存器。 *AT89C51的特殊功能寄存器表請看附錄二
8.sfr16 16位特殊功能寄存器 sfr16占用兩個內存單元,值域為0~65535。sfr16和sfr一樣用于操作特殊功能寄存器,所不同的是它用于操作占兩個字節的寄存器,好定時器T0和T1。
9. sbit可錄址位 sbit同位是C51中的一種擴充數據類型,利用它可以訪問芯片內部的RAM中的可尋址位或特殊功能寄存器中的可尋址位。如先前我們定義了 sfr P1 = 0x90; //因P1端口的寄存器是可位尋址的,所以我們可以定義 sbit P1_1 = P1^1; //P1_1為P1中的P1.1引腳 //同樣我們可以用P1.1的地址去寫,如sbit P1_1 = 0x91; 這樣我們在以后的程序語句中就可以用P1_1來對P1.1引腳進行讀寫操作了。通常這些可以直接使用系統提供的預處理文件,里面已定義好各特殊功能寄存器的簡單名字,直接引用可以省去一點時間,我自己是一直用的。當然您也可以自己寫自己的定義文件,用您認為好記的名字。
關于數據類型轉換等相關操作在后面的課程或程序實例中將有所提及。大家可以用所講到的數據類型改寫一下這課的實例程序,加深對各類型的認識。
|
|
附錄一 C51中的關鍵字 |
關鍵字 |
用 途 |
說 明 |
auto |
存儲種類說明 |
用以說明局部變量,缺省值為此 |
break |
程序語句 |
退出最內層循環 |
case |
程序語句 |
Switch語句中的選擇項 |
char |
數據類型說明 |
單字節整型數或字符型數據 |
const |
存儲類型說明 |
在程序執行過程中不可更改的常量值 |
continue |
程序語句 |
轉向下一次循環 |
default |
程序語句 |
Switch語句中的失敗選擇項 |
do |
程序語句 |
構成do..while循環結構 |
double |
數據類型說明 |
雙精度浮點數 |
else |
程序語句 |
構成if..else選擇結構 |
enum |
數據類型說明 |
枚舉 |
extern |
存儲種類說明 |
在其他程序模塊中說明了的全局變量 |
flost |
數據類型說明 |
單精度浮點數 |
for |
程序語句 |
構成for循環結構 |
goto |
程序語句 |
構成goto轉移結構 |
if |
程序語句 |
構成if..else選擇結構 |
int |
數據類型說明 |
基本整型數 |
long |
數據類型說明 |
長整型數 |
register |
存儲種類說明 |
使用CPU內部寄存的變量 |
return |
程序語句 |
函數返回 |
short |
數據類型說明 |
短整型數 |
signed |
數據類型說明 |
有符號數,二進制數據的最高位為符號位 |
sizeof |
運算符 |
計算表達式或數據類型的字節數 |
static |
存儲種類說明 |
靜態變量 |
struct |
數據類型說明 |
結構類型數據 |
swicth |
程序語句 |
構成switch選擇結構 |
typedef |
數據類型說明 |
重新進行數據類型定義 |
union |
數據類型說明 |
聯合類型數據 |
unsigned |
數據類型說明 |
無符號數數據 |
void |
數據類型說明 |
無類型數據 |
volatile |
數據類型說明 |
該變量在程序執行中可被隱含地改變 |
while |
程序語句 |
構成while和do..while循環結構 |
|
關鍵字 |
用 途 |
說 明 |
bit |
位標量聲明 |
聲明一個位標量或位類型的函數 |
sbit |
位標量聲明 |
聲明一個可位尋址變量 |
Sfr |
特殊功能寄存器聲明 |
聲明一個特殊功能寄存器 |
Sfr16 |
特殊功能寄存器聲明 |
聲明一個16位的特殊功能寄存器 |
data |
存儲器類型說明 |
直接尋址的內部數據存儲器 |
bdata |
存儲器類型說明 |
可位尋址的內部數據存儲器 |
idata |
存儲器類型說明 |
間接尋址的內部數據存儲器 |
pdata |
存儲器類型說明 |
分頁尋址的外部數據存儲器 |
xdata |
存儲器類型說明 |
外部數據存儲器 |
code |
存儲器類型說明 |
程序存儲器 |
interrupt |
中斷函數說明 |
定義一個中斷函數 |
reentrant |
再入函數說明 |
定義一個再入函數 |
using |
寄存器組定義 |
定義芯片的工作寄存器 |
|
附錄二 AT89C51特殊功能寄存器列表(適用于同一架構的芯片) |
符 號 |
地 址 |
注 釋 |
*ACC |
E0H |
累加器 |
*B |
F0H |
乘法寄存器 |
*PSW |
D0H |
程序狀態字 |
SP |
81H |
堆棧指針 |
DPL |
82H |
數據存儲器指針低8位 |
DPH |
83H |
數據存儲器指針高8位 |
*IE |
A8H |
中斷允許控制器 |
*IP |
D8H |
中斷優先控制器 |
*P0 |
80H |
端口0 |
*P1 |
90H |
端口1 |
*P2 |
A0H |
端口2 |
*P3 |
B0H |
端口3 |
PCON |
87H |
電源控制及波特率選擇 |
*SCON |
98H |
串行口控制器 |
SBUF |
99H |
串行數據緩沖器 |
*TCON |
88H |
定時器控制 |
TMOD |
89H |
定時器方式選擇 |
TL0 |
8AH |
定時器0低8位 |
TL1 |
8BH |
定時器1低8位 |
TH0 |
8CH |
定時器0低8位 |
TH1 |
8DH |
定時器1高8位 |
|
第五課 常量 |
上一節我們學習了KEIL C51編譯器所支持的數據類型。而這些數據類型又是怎么用在常量和變量的定義中的呢?又有什么要注意的嗎?下面就來看看吧。暈!你還區分不清楚什么是常量,什么是變量。常量是在程序運行過程中不能改變值的量,而變量是可以在程序運行過程中不斷變化的量。變量的定義可以使用所有C51編譯器支持的數據類型,而常量的數據類型只有整型、浮點型、字符型、字符串型和位標量。這一節我們學習常量定義和用法,而下一節則學習變量。 常量的數據類型說明是這樣的 1. 整型常量可以表示為十進制如123,0,-89等。十六進制則以0x開頭如0x34,-0x3B等。長整型就在數字后面加字母L,如104L,034L,0xF340等。 2. 浮點型常量可分為十進制和指數表示形式。十進制由數字和小數點組成,如0.888,3345.345,0.0等,整數或小數部分為0,可以省略但必須有小數點。指數表示形式為[±]數字[.數字]e[±]數字,[]中的內容為可選項,其中內容根據具體情況可有可無,但其余部分必須有,如125e3,7e9,-3.0e-3。 3. 字符型常量是單引號內的字符,如'a','d'等,不可以顯示的控制字符,可以在該字符前面加一個反斜杠"\"組成專用轉義字符。常用轉義字符表請看表5-1。 4. 字符串型常量由雙引號內的字符組成,如"test","OK"等。當引號內的沒有字符時,為空字符串。在使用特殊字符時同樣要使用轉義字符如雙引號。在C中字符串常量是做為字符類型數組來處理的,在存儲字符串時系統會在字符串尾部加上\o轉義字符以作為該字符串的結束符。字符串常量"A"和字符常量'A'是不同的,前者在存儲時多占用一個字節的字間。 5. 位標量,它的值是一個二進制。
|
轉義字符 |
含義 |
ASCII碼(16/10進制) |
\o |
空字符(NULL) |
00H/0 |
\n |
換行符(LF) |
0AH/10 |
\r |
回車符(CR) |
0DH/13 |
\t |
水平制表符(HT) |
09H/9 |
\b |
退格符(BS) |
08H/8 |
\f |
換頁符(FF) |
0CH/12 |
\' |
單引號 |
27H/39 |
\" |
雙引號 |
22H/34 |
\\ |
反斜杠 |
5CH/92 |
|
常量可用在不必改變值的場合,如固定的數據表,字庫等。常量的定義方式有幾種,下面來加以說明。 #difine False 0x0; //用預定義語句可以定義常量 #difine True 0x1; //這里定義False為0,True為1 //在程序中用到False編譯時自動用0替換,同理True替換為1 unsigned int code a=100; //這一句用code把a定義在程序存儲器中并賦值 const unsigned int c=100; //用const定義c為無符號int常量并賦值 以上兩句它們的值都保存在程序存儲器中,而程序存儲器在運行中是不允許被修改的,所以如果在這兩句后面用了類似a=110,a++這樣的賦值語句,編譯時將會出錯。 說了一通還不如寫個程序來實驗一下吧。寫什么程序呢?跑馬燈!對,就寫這個簡單易懂的吧,這個也好說明典型的常量用法。先來看看電路圖吧。它是在我們上一課的實驗電路的基礎上增加6個LED組成的,也就是用P1口的全部引腳分別驅動一個LED,電路如圖5-1所示。 新建一個RunLED的項目,主程序如下: #include <AT89X51.H> //預處理文件里面定義了特殊寄存器的名稱如P1口定義為P1 void main(void) { //定義花樣數據 cons tunsigned char design[32]={0xFF,0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F, 0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0xFE,0xFF, 0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x0, 0xE7,0xDB,0xBD,0x7E,0xFF}; unsigned int a; //定義循環用的變量 unsigned char b; //在C51編程中因內存有限盡可能注意變量類型的使用 //盡可能使用少字節的類型,在大型的程序中很受用 do{ for (b=0; b<32; b++) { for(a=0; a<30000; a++); //延時一段時間 P1 = design[b]; //讀已定義的花樣數據并寫花樣數據到P1口 } }while(1); } 程序中的花樣數據可以自以去定義,因這里我們的LED要AT89C51的P1引腳為低電平才會點亮,所以我們要向P1口的各引腳寫數據O對應連接的LED才會被點亮,P1口的八個引腳剛好對應P1口特殊寄存器的八個二進位,如向P1口定數據0xFE,轉成二進制就是11111110,最低位D0為0這里P1.0引腳輸出低電平,LED1被點亮。如此類推,大家不難算出自己想要做的效果了。大家編譯燒寫看看,效果就出來,顯示的速度您可以根據需要調整延時a的值,不要超過變量類型的值域就很行了。哦,您還沒有實驗板?那如何可以知道程序運行的結果呢?呵,不用急,這就來說說用KEIL uVision2的軟件仿真來調試IO口輸出輸入程序。
|
 圖5-1 八路跑馬燈電路 |
編譯運行上面的程序,然后按外部設備菜單Peripherals-I/O Ports-Port1就打開Port1的調試窗口了,如圖5-3中的2。這時程序運行了,但我們并不能在Port1調試窗口上看到有會什么效果,這時我們可以用鼠標左擊圖5-3中1旁邊綠色的方條,點一下就有一個小紅方格在點一下又沒有了,哪一句語句前有小方格程序運行到那一句時就停止了,就是設置調試斷點,同樣圖5-2中的1也是同樣功能,分別是增加/移除斷點、移除所有斷點、允許/禁止斷點、禁止所有斷點,菜單也有一樣的功能,另外菜單中還有Breakpoints可打開斷點設置窗口它的功能更強大,不過我們這里先不用它。我們?quot;P1 = design[b];"這一句設置一個斷點這時程序運行到這里就停住了,再留意一下Port1調試窗口,再按圖5-2中的2的運行鍵,程序又運行到設置斷點的地方停住了,這時Port1調試窗口的狀態又不同了。也就是說Port1調試窗口模擬了P1口的電平狀態,打勾為高電平,不打勾則為低電平,窗口中P1為P1寄存器的狀態,Pins為引腳的狀態,注意的是如果是讀引腳值必須把引腳對應的寄存器置1才能正確讀取。圖5-2中2旁邊的{}樣的按鈕分別為單步入,步越,步出和執行到當前行。圖中3為顯示下一句將要執行的語句。圖5-3中的3是Watches窗口可查看各變量的當前值,數組和字串是顯示其頭一個地址,如本例中的design數組是保存在code存儲區的首地址為D:0x08,可以在圖中4 Memory存儲器查看窗口中的Address地址中打入D:0x08就可以查看到design各數據和存放地址了。如果你的uVision2沒有顯示這些窗口,可以在View菜單中打開在圖5-2中3后面一欄的查看窗口快捷欄中打開。
|
 圖5-2 調試用快捷菜單欄 |
 圖5-3 各調試窗口 |
第六課 變量 |
上課所提到變量就是一種在程序執行過程中其值能不斷變化的量。要在程序中使用變量必須先用標識符作為變量名,并指出所用的數據類型和存儲模式,這樣編譯系統才能為變量分配相應的存儲空間。定義一個變量的格式如下: [存儲種類] 數據類型 [存儲器類型] 變量名表 在定義格式中除了數據類型和變量名表是必要的,其它都是可選項。存儲種類有四種:自動(auto),外部(extern),靜態(static)和寄存器(register),缺省類型為自動(auto)。這些存儲種類的具體含義和用法,將在第七課《變量的存儲》中進一步進行學習。 而這里的數據類型則是和我們在第四課中學習到的名種數據類型的定義是一樣的。說明了一個變量的數據類型后,還可選擇說明該變量的存儲器類型。存儲器類型的說明就是指定該變量在C51硬件系統中所使用的存儲區域,并在編譯時準確的定位。表6-1中是KEIL uVision2所能認別的存儲器類型。注意的是在AT89C51芯片中RAM只有低128位,位于80H到FFH的高128位則在52芯片中才有用,并和特殊寄存器地址重疊。特殊寄存器(SFR)的地址表請看附錄二 AT89C51特殊功能寄存器列表
|
存儲器類型 |
說 明 |
data |
直接訪問內部數據存儲器(128字節),訪問速度最快 |
bdata |
可位尋址內部數據存儲器(16字節),允許位與字節混合訪問 |
idata |
間接訪問內部數據存儲器(256字節),允許訪問全部內部地址 |
pdata |
分頁訪問外部數據存儲器(256字節),用MOVX @Ri指令訪問 |
xdata |
外部數據存儲器(64KB),用MOVX @DPTR指令訪問 |
code |
程序存儲器(64KB),用MOVC @A+DPTR指令訪問 |
表6-1 存儲器類型
|
如果省略存儲器類型,系統則會按編譯模式SMALL,COMPACT或LARGE所規定的默認存儲器類型去指定變量的存儲區域。無論什么存儲模式都可以聲明變量在任何的8051存儲區范圍,然而把最常用的命令如循環計數器和隊列索引放在內部數據區可以顯著的提高系統性能。還有要指出的就是變量的存儲種類與存儲器類型是完全無關的。 SMALL存儲模式把所有函數變量和局部數據段放在8051系統的內部數據存儲區這使訪問數據非?,但SMALL存儲模式的地址空間受限。在寫小型的應用程序時,變量和數據放在data內部數據存儲器中是很好的因為訪問速度快,但在較大的應用程序中data區最好只存放小的變量、數據或常用的變量(如循環計數、數據索引),而大的數據則放置在別的存儲區域。 COMPACT存儲模式中所有的函數和程序變量和局部數據段定位在8051系統的外部數據存儲區。外部數據存儲區可有最多256字節(一頁),在本模式中外部數據存儲區的短地址用@R0/R1。 LARGE存儲模式所有函數和過程的變量和局部數據段都定位在8051系統的外部數據區外部數據區最多可有64KB,這要求用DPTR數據指針訪問數據。 之前提到簡單提到sfr,sfr16,sbit定義變量的方法,下面我們再來仔細看看。 sfr和sfr16可以直接對51單片機的特殊寄存器進行定義,定義方法如下: sfr 特殊功能寄存器名= 特殊功能寄存器地址常數; sfr16 特殊功能寄存器名= 特殊功能寄存器地址常數; 我們可以這樣定義AT89C51的P1口 sfr P1 = 0x90; //定義P1 I/O口,其地址90H sfr關鍵定后面是一個要定義的名字,可任意選取,但要符合標識符的命名規則,名字最好有一定的含義如P1口可以用P1為名,這樣程序會變的好讀好多。等號后面必須是常數,不允許有帶運算符的表達式,而且該常數必須在特殊功能寄存器的地址范圍之內(80H-FFH),具體可查看附錄中的相關表。sfr是定義8位的特殊功能寄存器而sfr16則是用來定義16位特殊功能寄存器,如8052的T2定時器,可以定義為: sfr16 T2 = 0xCC; //這里定義8052定時器2,地址為T2L=CCH,T2H=CDH 用sfr16定義16位特殊功能寄存器時,等號后面是它的低位地址,高位地址一定要位于物理低位地址之上。注意的是不能用于定時器0和1的定義。 sbit可定義可位尋址對象。如訪問特殊功能寄存器中的某位。其實這樣應用是經常要用的如要訪問P1口中的第2個引腳P1.1。我們可以照以下的方法去定義: (1)sbit 位變量名=位地址 sbit P1_1 = Ox91; 這樣是把位的絕對地址賦給位變量。同sfr一樣sbit的位地址必須位于80H-FFH之間。 (2)Sbit 位變量名=特殊功能寄存器名^位位置 sft P1 = 0x90; sbit P1_1 = P1 ^ 1; //先定義一個特殊功能寄存器名再指定位變量名所在的位置 當可尋址位位于特殊功能寄存器中時可采用這種方法 (3)sbit 位變量名=字節地址^位位置 sbit P1_1 = 0x90 ^ 1; 這種方法其實和2是一樣的,只是把特殊功能寄存器的位址直接用常數表示。 在C51存儲器類型中提供有一個bdata的存儲器類型,這個是指可位尋址的數據存儲器,位于單片機的可位尋址區中,可以將要求可位錄址的數據定義為bdata,如: unsigned char bdata ib; //在可位錄址區定義ucsigned char類型的變量ib int bdata ab[2]; //在可位尋址區定義數組ab[2],這些也稱為可尋址位對象 sbit ib7=ib^7 //用關鍵字sbit定義位變量來獨立訪問可尋址位對象的其中一位 sbit ab12=ab[1]^12; 操作符"^"后面的位位置的最大值取決于指定的基址類型,char0-7,int0-15,long0-31。 下面我們用上一課的電路來實踐一下這一課的知識。同樣是做一下簡單的跑馬燈實驗,項目名為RunLED2。程序如下:
sfr P1 = 0x90; //這里沒有使用預定義文件, sbit P1_0 = P1 ^ 0; //而是自己定義特殊寄存器 sbit P1_7 = 0x90 ^ 7; //之前我們使用的預定義文件其實就是這個作用 sbit P1_1 = 0x91; //這里分別定義P1端口和P10,P11,P17引腳
void main(void) { unsigned int a; unsigned char b; do{ for (a=0;a<50000;a++) P1_0 = 0; //點亮P1_0 for (a=0;a<50000;a++) P1_7 = 0; //點亮P1_7 for (b=0;b<255;b++) { for (a=0;a<10000;a++) P1 = b; //用b的值來做跑馬燈的花樣 } P1 = 255; //熄滅P1上的LED for (b=0;b<255;b++) { for (a=0;a<10000;a++) //P1_1閃爍 P1_1 = 0; for (a=0;a<10000;a++) P1_1 = 1; } }while(1); } | |
第七課 運算符和表達式(1) |
上課到這一課相隔了好長一段時間,這些日子里收到不少網友的來信支持和鼓勵,要求盡快完成余下的部分。出門在外的人不得不先為吃飯而努力,似乎這也成為我的借口,以后每晚抽空打一些吧這樣大家也就可以不用隔太久就能看到一些新東西;蛟S我的筆記并不是很正確,但我盡量的保證每課的實驗都會親自做一次,包括硬件的部分,已求不會誤人子弟。 隨著訪問量不斷的增加,網站已啟用了www.cdle.net的國際域名,在這里我感謝各位一直支持磁動力工作室的朋友,更要感激身在遠方一直默默支持我的女友。 明浩 2003-7-14 晚 呵,費話少說了。上兩課說了常量和變量,先來補充一個用以重新定義數據類型的的語句吧。這個語句就是typedef,這是個很好用的語句,但我自己卻不常用它,通常我定義變量的數據類型時都是使用標準的關鍵字,這樣別人可以很方便的研讀你的程序。如果你是個DELPHI編程愛好者或是程序員,你對變量的定義也許習慣了DELPHI的關鍵字,如int類型常會用關鍵字Integer來定義,在用C51時你還想用回這個的話,你可以這樣寫: typedef int integer; integer a,b;
這兩句在編譯時,其實是先把integer定義為int,在以后的語句中遇到integer就用int置換,integer就等于int,所以a,b也就被定義為int。typedef不能直接用來定義變量,它只是對已有的數據類型作一個名字上的置換,并不是產生一個新的數據類型。下面兩句就是一個錯誤的例子: typedef int integer; integer = 100;
使用typedef可以有方便程序的移植和簡化較長的數據類型定義。用typedef還可以定義結構類型,這一點在后面詳細解說結構類型時再一并說明。typedef的語法是 typedef 已有的數據類型 新的數據類型名
運算符就是完成某種特定運算的符號。運算符按其表達式中與運算符的關系可分為單目運算符,雙目運算符和三目運算符。單目就是指需要有一個運算對象,雙目就要求有兩個運算對象,三目則要三個運算對象。表達式則是由運算及運算對象所組成的具有特定含義的式子。C是一種表達式語言,表達式后面加";"號就構成了一個表達式語句。
賦值運算符 對于"="這個符號大家不會陌生的,在C中它的功能是給變量賦值,稱之為賦值運算符。它的作用不用多說大家也明白,就是但數據賦給變量。如,x=10;由此可見利用賦值運算符將一個變量與一個表達式連接起來的式子為賦值表達式,在表達式后面加";"便構成了賦值語句。使用"="的賦值語句格式如下: 變量 = 表達式; 示例如下 a = 0xFF; //將常數十六進制數FF賦于變量a b = c = 33; //同時賦值給變量b,c d = e; //將變量e的值賦于變量d f = a+b; //將變量a+b的值賦于變量f
由上面的例子可以知道賦值語句的意義就是先計算出"="右邊的表達式的值,然后將得到的值賦給左邊的變量。而且右邊的表達式可以是一個賦值表達式。 在一些朋友的來信中會出現"=="與"="這兩個符號混淆的錯誤原碼,問為何編譯報錯,往往就是錯在if (a=x)之類的語句中,錯將"="用為"=="。"=="符號是用來進行相等關系運算。
算術,增減量運算符 對于a+b,a/b這樣的表達式大家都很熟悉,用在C語言中,+,/,就是算術運算符。C51中的算術運算符有如下幾個,其中只有取正值和取負值運算符是單目運算符,其它則都是雙目運算符: + 加或取正值運算符 - 減或取負值運算符 * 乘運算符 / 除運算符 % 取余運算符 算術表達式的形式: 表達式1 算術運算符 表達式2
如:a+b*(10-a), (x+9)/(y-a)
除法運算符和一般的算術運算規則有所不同,如是兩浮點數相除,其結果為浮點數,如10.0/20.0所得值為0.5,而兩個整數相除時,所得值就是整數,如7/3,值為2。像別的語言一樣C的運算符與有優先級和結合性,同樣可用用括號"()"來改變優先級。這些和我們小時候學的數學幾乎是一樣的,我也不必過多的說明了。 :( 還有這么多運算符呀!暫時停一停吧,我們先來做一個實驗吧。學習運算符和另外一些知識時,我們還是給我們的實驗板加個串行接口吧。借助電腦轉件直觀的看單片機的輸出結果,以后我還會用一些簡單的實例講解單片機和PC串口通訊的簡單應用和編程。如果你用的是成品實驗板或仿真器,那你就可以跳過這一段了。 在制作電路前我們先來看看要用的MAX232,這里我們不去具體討論它,只要知道它是TTL和RS232電平相互轉換的芯片和基本的引腳接線功能就行了。通常我會用兩個小功率晶體管加少量的電路去替換MAX232,可以省一點,效果也不錯(如有興趣可以查看http://www.cdle.net網站中的相關資料)。下圖就是MAX232的基本接線圖。
|
 圖7-1 MAX232
|
在上兩課的電路的基礎上按圖7-3加上MAX232就可以了。這大熱天的拿烙鐵焊焊,還真的是熱氣迫人來呀:P串口座用DB9的母頭,這樣就可以用買來的PC串口延長線進行和電腦相連接,也可以直接接到電腦com口上。
|
 圖7-2 DB9接頭 |
 圖7-3 加上了MAX232的實驗電路 |
做好后我們就> |
 圖7-3 加上了MAX232的實驗電路 |
做好后我們就先用回第一課的"Hello World!"程序,用它來和你的電腦說聲Hello!把程序燒到芯片上,把串口連接好。嘿嘿,這時要打開你的串口調試軟件,沒有就趕快到網上DOWN一個了。你會用Windows的超級中端也行,不過我從不用它。我用http://emouze.com的comdebug,它是個不錯的軟件,我喜歡它是因為它功能好而且還有"線路狀態"功能,這對我制作小玩意時很有用。串口號,波特率調好,打開串口,單片機上電,就可以在接收區看到不斷出現的"Hello World!"。一定要先打開軟件的串口,再把單片機上電,否則可能因字符不對齊而看到亂碼哦。
|
| 先用回第一課的"Hello World!"程序,用它來和你的電腦說聲Hello!把程序燒到芯片上,把串口連接好。嘿嘿,這時要打開你的串口調試軟件,沒有就趕快到網上DOWN一個了。你會用Windows的超級中端也行,不過我從不用它。我用http://emouze.com的comdebug,它是個不錯的軟件,我喜歡它是因為它功能好而且還有"線路狀態"功能,這對我制作小玩意時很有用。串口號,波特率調好,打開串口,單片機上電,就可以在接收區看到不斷出現的"Hello World!"。一定要先打開軟件的串口,再把單片機上電,否則可能因字符不對齊而看到亂碼哦。 |