版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
第3章
單片機C51程序設(shè)計基礎(chǔ)主要結(jié)合MCS-51單片機特點介紹C51的基本知識,重點講述與單片機軟件編程密切相關(guān)的內(nèi)容。第3章
單片機C51程序設(shè)計基礎(chǔ)C51概述3.1C51的編譯和編譯預(yù)處理3.2C51的基本語法3.3C51的程序結(jié)構(gòu)3.4C51的函數(shù)3.5C51的數(shù)組3.6
讀寫I/O端口的C51編程3.8C51的指針3.73.1C51概述-程序結(jié)構(gòu)概述#include<reg51.h> //預(yù)處理命令//全局變量定義//函數(shù)聲明charfun() //功能函數(shù)定義{ …… //功能函數(shù)體}void函數(shù)名()interruptx//中斷函數(shù)定義{ …… //中斷函數(shù)體}voidmain() //主函數(shù){//局部變量定義//單片機寄存器初始化函數(shù)
while(1) { …… //主函數(shù)體 }}一個C51源程序必須包括一個main函數(shù)?!?include<xxx.h>”語句是包含庫函數(shù)。全局變量在程序的所有地方都可以賦值和讀出,包括中斷函數(shù)、主函數(shù)。用戶自定義函數(shù)是用戶自己定義、自己調(diào)用的函數(shù)。如果使用中斷、定時器、串口等功能,則單片機相關(guān)寄存器的必須要初始化。主程序必須是閉環(huán)結(jié)構(gòu)。注釋部分可以用“//注釋內(nèi)容”或“/*注釋內(nèi)容*/”分割。程序中必須采用英文標點。3.1C51概述-程序結(jié)構(gòu)概述#include<reg51.h> //預(yù)處理命令//全局變量定義//函數(shù)聲明charfun() //功能函數(shù)定義{ …… //功能函數(shù)體}void函數(shù)名()interruptx//中斷函數(shù)定義{ …… //中斷函數(shù)體}voidmain() //主函數(shù){//局部變量定義//單片機寄存器初始化函數(shù)
while(1) { …… //主函數(shù)體 }}除了ANSIC標準的32個關(guān)鍵字之外,C51還根據(jù)MCS-51單片機的特點擴展了相關(guān)的關(guān)鍵字。右表按用途列出了KeilC51編譯器擴展的關(guān)鍵字。3.1.2
C51對標準C的擴展關(guān)鍵字用途說明_at_地址定位為變量進行存儲器絕對空間地址定位alien函數(shù)特性聲明用于聲明與PL/M51兼容函數(shù)small存儲器模式指定使用內(nèi)部數(shù)據(jù)存儲器空間compact存儲器模式指定使用外部“分頁尋址”數(shù)據(jù)存儲器空間large存儲器模式指定使用外部數(shù)據(jù)存儲器空間code存儲器類型聲明聲明程序存儲器空間data存儲器類型聲明指定直接尋址的內(nèi)部數(shù)據(jù)存儲器bdata存儲器類型聲明指定可位尋址的內(nèi)部數(shù)據(jù)存儲器idata存儲器類型聲明指定間接尋址的內(nèi)部數(shù)據(jù)存儲器pdata存儲器類型聲明指定“分頁尋址”的外部數(shù)據(jù)存儲器xdata存儲器類型聲明指定外部數(shù)據(jù)存儲器bit位變量聲明聲明位變量sbit位變量聲明聲明一個可位尋址變量sfr特殊功能寄存器聲明聲明一個8位的特殊功能寄存器sfr16特殊功能寄存器聲明聲明一個16位的特殊功能寄存器interrupt中斷函數(shù)聲明定義一個中斷服務(wù)函數(shù)using工作寄存器組定義定義工作寄存器組R0~R7_priority_多任務(wù)優(yōu)先聲明規(guī)定RTX或RTX51Tiny的任務(wù)優(yōu)先級reentrant再入函數(shù)聲明定義一個再入函數(shù)_task_任務(wù)聲明定義實時多任務(wù)函數(shù)3.1.2
C51對標準C的擴展關(guān)鍵字用途說明_at_地址定位為變量進行存儲器絕對空間地址定位alien函數(shù)特性聲明用于聲明與PL/M51兼容函數(shù)small存儲器模式指定使用內(nèi)部數(shù)據(jù)存儲器空間compact存儲器模式指定使用外部“分頁尋址”數(shù)據(jù)存儲器空間large存儲器模式指定使用外部數(shù)據(jù)存儲器空間code存儲器類型聲明聲明程序存儲器空間data存儲器類型聲明指定直接尋址的內(nèi)部數(shù)據(jù)存儲器bdata存儲器類型聲明指定可位尋址的內(nèi)部數(shù)據(jù)存儲器idata存儲器類型聲明指定間接尋址的內(nèi)部數(shù)據(jù)存儲器pdata存儲器類型聲明指定“分頁尋址”的外部數(shù)據(jù)存儲器xdata存儲器類型聲明指定外部數(shù)據(jù)存儲器bit位變量聲明聲明位變量sbit位變量聲明聲明一個可位尋址變量sfr特殊功能寄存器聲明聲明一個8位的特殊功能寄存器sfr16特殊功能寄存器聲明聲明一個16位的特殊功能寄存器interrupt中斷函數(shù)聲明定義一個中斷服務(wù)函數(shù)using工作寄存器組定義定義工作寄存器組R0~R7_priority_多任務(wù)優(yōu)先聲明規(guī)定RTX或RTX51Tiny的任務(wù)優(yōu)先級reentrant再入函數(shù)聲明定義一個再入函數(shù)_task_任務(wù)聲明定義實時多任務(wù)函數(shù)除了ANSIC標準的32個關(guān)鍵字之外,C51還根據(jù)MCS-51單片機的特點擴展了相關(guān)的關(guān)鍵字。右表按用途列出了KeilC51編譯器擴展的關(guān)鍵字。3.3.2變量-存儲類型存儲類型與存儲空間對應(yīng)關(guān)系data直接尋址片內(nèi)數(shù)據(jù)存儲器區(qū),訪問速度最快(128字節(jié))bdata可位尋址片內(nèi)數(shù)據(jù)存儲區(qū),允許位與字節(jié)混合訪問(16字節(jié))idata間接尋址片內(nèi)數(shù)據(jù)存儲區(qū),可訪問片內(nèi)全部RAM地址空間(256字節(jié))pdata片外RAM的256字節(jié),由MOVX@Ri訪問xdata片外64KB的RAM空間,由MOVX@DPTR訪問code代碼存儲區(qū)(64KB),由MOVCA,@A+DPTR訪問C51存儲類型與MCS-51單片機存儲空間的對應(yīng)關(guān)系如下所示。在C51中對變量進行定義的格式如下:[存儲種類]數(shù)據(jù)類型[存儲類型]變量名;在程序中,用關(guān)鍵字_at_實現(xiàn)對指定存儲空間絕對地址的訪問,使用_at_的格式如下:
[存儲類型]數(shù)據(jù)類型變量名_at_地址常數(shù);尋址:尋找操作數(shù)所在單元的地址。尋址方式:CPU尋找操作數(shù)所在地址的方法。MCS-51有7種尋址方式:立即尋址、直接尋址、寄存器尋址、寄存器間接尋址、變址尋址、相對尋址和位尋址。單片機的尋址方式(了解)尋址方式使用的變量尋址空間立即尋址直接給出數(shù)值,無變量ROM直接尋址直接給出地址,無變量片內(nèi)RAM低128字節(jié)、SFR寄存器尋址R0~R7、A、B、DPTR、位累加器C工作寄存器R0~R7,部分SFR寄存器間接尋址@R0、@R1、SP或@DPTR片內(nèi)RAM或片外RAM變址尋址@A+DPTR、@A+PCROM相對尋址PC+偏移量ROM位尋址直接給出位地址或位符號片內(nèi)RAM的位尋址區(qū)、SFR的可尋址位指令中直接給出操作數(shù)的尋址方式,經(jīng)典指令MOVA,#data。【例1】執(zhí)行MOVA,#68H
結(jié)果:(A)=68H
單片機的尋址方式-立即尋址注意:在立即數(shù)前必須使用“#”標志。尋址空間:ROM指令中直接給出操作數(shù)所在存儲單元的地址,經(jīng)典指令MOVA,direct?!纠?】若(30H)=56H,執(zhí)行MOVA,30H后,(A)=56H單片機的尋址方式-直接尋址尋址空間:片內(nèi)RAM低128字節(jié)SFR(一般采用符號形式替代直接地址,例:一般將MOVA,80H寫成MOVA,P0)操作數(shù)存放在寄存器中,指令中直接給出該寄存器名稱,經(jīng)典指令MOVA,Rn?!纠?】若(R1)=80H,執(zhí)行MOVA,R1后,(A)=80H
單片機的尋址方式-寄存器尋址指令中給出的寄存器中存放的不是操作數(shù),而是操作數(shù)所在單元的地址。為了與寄存器尋址區(qū)別,應(yīng)在寄存器的名稱前面加前綴標志“@”,經(jīng)典指令MOVA,@Ri。
單片機的尋址方式-寄存器間接尋址【例4】若(R0)=40H,(40H)=30H,執(zhí)行MOVA,@R0后,(A)=30H。尋址空間:片內(nèi)RAM(@Ri、SP)通用形式:MOV指令@Ri(i=0,1)PUSH/POPdirect(SP發(fā)生相應(yīng)變化)52系列內(nèi)部RAM的高128B只能用該尋址方式片外RAM(@Ri、@DPTR)通用形式:MOVX指令@DPTR
MOVX指令@Ri(i=0,1)單片機的尋址方式-寄存器間接尋址以數(shù)據(jù)指針DPTR或程序計數(shù)器PC作基址寄存器,以累加器A作變址寄存器,并以兩者內(nèi)容相加形成操作數(shù)所在單元的地址,經(jīng)典指令MOVCA,@A+DPTR。尋址空間:ROM,尋址范圍可達到64KB。單片機的尋址方式-變址尋址【例5】若(DPTR)=1234H,(A)=60H,執(zhí)行MOVCA,@A+DPTR后,(A)=78H將程序計數(shù)器PC的當前值加上指令中給出的偏移量rel,結(jié)果作為目標地址的尋址方式。用于跳轉(zhuǎn)指令,實現(xiàn)程序的分支跳轉(zhuǎn)。單片機的尋址方式-相對尋址【例6】若JCL1存于0200H開始的單元,而L1對應(yīng)的地址是0277H單元,則可計算出rel為75H,該指令的機器碼是40H75H。如果PSW.7為1,執(zhí)行JCL1指令后,程序?qū)⑻D(zhuǎn)到0277H單元。
因為SJMP是雙字節(jié)指令,則目標地址=(PC)+2-2=(PC)即轉(zhuǎn)移的目標地址就是SJMP指令的地址,在匯編指令中該偏移地址可用$符號表示。若在程序的末尾加上SJMP$指令,則程序?qū)⒃谠撎庍M行無限循環(huán),進入等待狀態(tài)。若SJMPrel中的rel=FEH(-2),目標地址=?單片機的尋址方式-相對尋址對片內(nèi)RAM的位尋址區(qū)和某些可位尋址的特殊功能寄存器進行位操作時的尋址方式,經(jīng)典指令MOVC,bit?!纠?】若位地址20H內(nèi)容為1,執(zhí)行MOVC,20H后,位地址PSW.7的內(nèi)容為1。單片機的尋址方式-位尋址在C51中的關(guān)鍵字除了ANSIC標準的32個關(guān)鍵字之外,還根據(jù)MCS-51單片機的特點擴展了相關(guān)的關(guān)鍵字,右表按用途列出了KeilC51編譯器擴展的關(guān)鍵字。3.1.2
C51對標準C的擴展關(guān)鍵字用途說明_at_地址定位為變量進行存儲器絕對空間地址定位alien函數(shù)特性聲明用于聲明與PL/M51兼容函數(shù)small存儲器模式指定使用內(nèi)部數(shù)據(jù)存儲器空間compact存儲器模式指定使用外部“分頁尋址”數(shù)據(jù)存儲器空間large存儲器模式指定使用外部數(shù)據(jù)存儲器空間code存儲器類型聲明聲明程序存儲器空間data存儲器類型聲明指定直接尋址的內(nèi)部數(shù)據(jù)存儲器bdata存儲器類型聲明指定可位尋址的內(nèi)部數(shù)據(jù)存儲器idata存儲器類型聲明指定間接尋址的內(nèi)部數(shù)據(jù)存儲器pdata存儲器類型聲明指定“分頁尋址”的外部數(shù)據(jù)存儲器xdata存儲器類型聲明指定外部數(shù)據(jù)存儲器bit位變量聲明聲明位變量sbit位變量聲明聲明一個可位尋址變量sfr特殊功能寄存器聲明聲明一個8位的特殊功能寄存器sfr16特殊功能寄存器聲明聲明一個16位的特殊功能寄存器interrupt中斷函數(shù)聲明定義一個中斷服務(wù)函數(shù)using工作寄存器組定義定義工作寄存器組R0~R7_priority_多任務(wù)優(yōu)先聲明規(guī)定RTX或RTX51Tiny的任務(wù)優(yōu)先級reentrant再入函數(shù)聲明定義一個再入函數(shù)_task_任務(wù)聲明定義實時多任務(wù)函數(shù)3.3.2變量-C51擴展數(shù)據(jù)類型數(shù)據(jù)類型位數(shù)字節(jié)數(shù)值域bit1/0或1sfr810~255sfr161620~65535sbit1/0或1(1)位變量bitbit用于定義位變量的名字,編譯器會對其分配地址。位變量分配在內(nèi)部RAM的20H~2FH單元相應(yīng)的位區(qū)域,位地址范圍是00~7FH,共128個。用bit定義位變量的值可以是1,也可以是0。定義方法如下:針對MCS-51單片機的硬件特點,C51在標準C的基礎(chǔ)上,擴展了4種數(shù)據(jù)類型,主要針對單片機片內(nèi)存儲區(qū)RAM。bit 位變量;(2)特殊功能寄存器sfr和sfr16特殊功能寄存器分布在片內(nèi)數(shù)據(jù)存儲區(qū)的地址單元80H~FFH之間?!皊fr”數(shù)據(jù)類型占用一個內(nèi)存單元,利用它可以直接對MCS-51單片機的特殊功能寄存器進行定義。“sfr16”數(shù)據(jù)類型則占兩個內(nèi)存單元,利用它可以定義占兩個字節(jié)的特殊功能寄存器,在定義時的地址選用低位地址。定義方法如下:sfr
特殊功能寄存器名=地址;sfr16
特殊功能寄存器名=地址;3.3.2變量-C51擴展數(shù)據(jù)類型(3)特殊功能位sbitsbit用于定義位變量的名字和地址。被定義的位變量是SFR中的可以進行位尋址的確定位,該位變量的絕對地址是確定的且不用編譯器分配。利用sbit定義位變量名字和地址的方法有如下三種。①第一種方法(將位的絕對地址賦給位變量,位地址必須位于80H~FFH之間)。注意:不要把bit與sbit混淆。bit直接用于定義位變量,而sbit用于定義位變量的名字和地址。sbit 位變量名=位地址;②第二種方法(可尋址位位于特殊功能寄存器中)sbit 位變量名=特殊功能寄存器名^位位置;③第三種方法sbit 位變量名=字節(jié)地址^位位置;3.3.2變量-C51擴展數(shù)據(jù)類型文件包含是將另一個指定的文件內(nèi)容包含進來。文件包含命令的一般格式為:#include的功能是用指定文件的全部內(nèi)容替換該預(yù)處理行。采用<文件名>格式時,在頭文件目錄中查找指定文件;采用"文件名"格式時,在當前目錄中査找指定文件,若沒找到,再到頭文件目錄中查找。#include通常放在C語言程序的開頭,被包含文件的類型通常為以“.h”為后綴的頭文件和以“.c”為后綴的源程序文件。#include<文件名>或#include"文件名"3.2.2C51的編譯預(yù)處理-文件包含3.2.2C51的編譯預(yù)處理-宏定義宏定義命令為#define,作用是用一個標識符替換一個字符串。(1)不帶參數(shù)的宏定義。不帶參數(shù)的宏定義又稱符號常量定義,一般格式為:#define標識符常量表達式(2)帶參數(shù)的宏定義。帶參數(shù)的宏定義與符號常量定義的不同之處在于,對于源程序中出現(xiàn)的宏符號名不僅進行字符串替換,而且還進行參數(shù)替換。帶參數(shù)宏定義的一般格式為:#define宏符號名(參數(shù)表)表達式3.3.1常量常量又稱為標量,它的值在程序執(zhí)行過程中不能改變。常量的數(shù)據(jù)類型有:1.整型。1234(十進制整數(shù))、0x123(十六進制整數(shù))、0123L(長整數(shù))。2.浮點型。有十進制數(shù)表示形式和指數(shù)表示形式兩種。3.字符型。單引號內(nèi)的字符,如'a','b'等。對于不可顯示的控制字符,可以在該字符前面加一個反斜杠“\”組成轉(zhuǎn)義字符。4.字符串型。由雙引號""內(nèi)的字符組成,如"ABCD"、"$1234"等。3.3C51的基本語法變量是一種在程序執(zhí)行過程中其值能不斷變化的量。在使用一個變量之前,必須要進行定義,用一個標識符作為變量名并指出它的數(shù)據(jù)類型和存儲類型,以便編譯系統(tǒng)為它分配相應(yīng)的存儲單元。在C51中對變量進行定義的格式如下:3.3.2變量[存儲種類]數(shù)據(jù)類型[存儲類型]變量名;變量的存儲種類有四種:自動(auto)、外部(extern)、靜態(tài)(static)和寄存器(register)。3.3.2變量-標準C數(shù)據(jù)類型數(shù)據(jù)類型位數(shù)字節(jié)數(shù)值域signedchar81-128~+127,有符號字符變量unsignedchar810~255,無符號字符變量signedint162-32768~+32767,有符號整型數(shù)unsignedint1620~65535,無符號整型數(shù)signedlong324-2147483648~+2147483647,有符號長整型數(shù)unsignedlong3240~+4294967695,無符號長整型數(shù)float324±1.175494E-38~±3.402823E+38,浮點數(shù)(精度6~7位)double648±4.940656458412465E-324~±1.797693134862316E+308,浮點數(shù)(精度15~16位)3.3.2變量-存儲模式(了解)在固定的存儲器地址上進行變量的傳遞,是C51標準特征之一。C51存儲模式分為以下幾種:(1)SMALL模式。所有變量都默認位于MCS-51單片機內(nèi)部的數(shù)據(jù)存儲器,這與使用data指定存儲類型的方式一樣。在此模式下,變量訪問的效率高,但所有數(shù)據(jù)對象和堆棧必須使用內(nèi)部RAM。(2)COMPACT模式。變量被定義在分頁尋址的片外數(shù)據(jù)存儲器中,每一頁的片外存儲器的長度為256字節(jié),適用于變量不超過256字節(jié)的情況,對應(yīng)pdata存儲類型。(3)LARGE模式。變量被定義在片外數(shù)據(jù)存儲器中(最大可達64KB),對應(yīng)xdata存儲類型。該模式要比SMALL和COMPACT產(chǎn)生更多的代碼。3.3.3常用運算符與表達式-算數(shù)運算符算術(shù)運算符及其說明如下表所示。符號說明+加法運算-減法運算*乘法運算/除法運算%取模(余數(shù))運算++自增1--自減1符號說明&&邏輯與||邏輯或!邏輯非3.3.3常用運算符與表達式-邏輯運算符邏輯運算符及其說明如下表所示。符號說明>大于<小于>=大于或等于<=小于或等于==等于!=不等于3.3.3常用運算符與表達式-關(guān)系運算符關(guān)系運算符及其說明如下表所示。符號說明&按位與|按位或^按位異或~按位取反<<按位左移>>按位右移3.3.3常用運算符與表達式-位運算符位運算符及其說明如下表所示?!纠?-1】編寫程序?qū)U展的I/O口PORT(假設(shè)地址是FFC0H,內(nèi)容是20H)的PORT.5清0,PORT.1置1。參考程序1:
xdataunsignedcharPORT_at_
0xffc0;//用_at_指定存儲空間絕對地址voidmain(){
PORT=0x20;
PORT=(PORT&0xdf)|0x02;}3.3.3常用運算符與表達式-位運算符參考程序2:#include<absacc.h>//定義片外I/O口變量PORT要用到頭文件absacc.h#definePORTXBYTE[0xffc0]//XBYTE是絕對地址訪問函數(shù)中的宏voidmain(){
PORT=0x20;
PORT=(PORT&0xdf)|0x02;}賦值運算符及其說明如下表所示。符號說明=將一個數(shù)據(jù)的值賦給一個變量變量=表達式;賦值語句的格式如下:變量
復(fù)合賦值運算符
表達式;例如:a+=3;x*=y+8;...復(fù)合賦值運算首先對變量進行某種運算,然后將運算的結(jié)果再賦給該變量。復(fù)合運算的一般形式為:3.3.3常用運算符與表達式-賦值運算符指針和取地址運算符及其說明如下表所示。符號說明*取內(nèi)容&取變量的地址變量=*指針變量;指針變量=&目標變量;取內(nèi)容(指針)和取地址的一般形式分別為:3.3.3常用運算符與表達式-指針和取地址運算符C51的程序按結(jié)構(gòu)可分為三類,即順序、分支和循環(huán)結(jié)構(gòu)。順序結(jié)構(gòu)是程序的基本結(jié)構(gòu),程序自上而下,從main()函數(shù)開始一直到程序運行結(jié)束,程序只有一條路可走,沒有其他的路徑可以選擇。3.4.1分支語句實現(xiàn)分支結(jié)構(gòu)的語句有:if語句和switch語句。1.if語句判定所給定的條件是否滿足,根據(jù)判定結(jié)果決定執(zhí)行哪種操作。if語句的基本結(jié)構(gòu)為:3.4C51的程序結(jié)構(gòu)if(表達式){語句;}3.4.1分支語句-if語句if(表達式){語句;}if(表達式){語句1;}else{語句2;}(2)形式2C51提供3種形式的if語句:(1)形式1if(表達式1){語句1;}elseif(表達式2){語句2;}elseif(表達式3){語句3;}……else{語句n;}(3)形式3【例8】已知片內(nèi)RAM的30H單元中存放著一個無符號數(shù)X,試編寫程序求出右式的函數(shù)值Y,并將結(jié)果存放在31H單元中。
#defineucharunsignedchardataucharx_at_0x30;datauchary_at_0x31;voidmain(){ if(x>0x20)y=0x01; elseif(x==0x20)y=0x00; elsey=0x0f; while(1);}3.4.1分支語句#include<absacc.h>#definexDBYTE[0x30]#defineyDBYTE[0x31]voidmain(){ if(x>0x20)y=0x01; elseif(x==0x20)y=0x00; elsey=0x0f; while(1);}參考程序2:參考程序1:【例9】已知片內(nèi)RAM的30H單元中存放著一個有符號數(shù)X,試編寫程序求出下式的函數(shù)值Y,并將結(jié)果存放在31H單元中。
datacharx_at_0x30;datachary_at_0x31;voidmain(){ if(x==0)y=0x00; elseif((x&0x80)==0)y=0x01; elsey=0x0f; while(1);}3.4.1分支語句#include<absacc.h>#definexDBYTE[0x30]#defineyDBYTE[0x31]voidmain(){ if(x==0)y=0x00; elseif((x&0x80)==0)y=0x01; elsey=0x0f; while(1);} 參考程序2:參考程序1:2.switch語句if語句只有兩個分支可供選擇,而switch語句是多分支選擇語句。switch語句的一般形式如下:switch(表達式){
case常量表達式1:{語句1;}break;
case常量表達式2:{語句2;}break;
……
case常量表達式n:{語句n;}break;
default:{語句n+1;}}3.4.1分支語句-switch語句【例3-2】在單片機程序設(shè)計中,常用switch語句作為鍵盤按鍵按下的判別,并根據(jù)按下鍵的鍵號跳向各自的分支處理程序。參考程序:
keynum=keyscan();switch(keynum){
case1: key1();break;//如果鍵值為1,則執(zhí)行函數(shù)key1()
case2: key2();break;//如果鍵值為2,則執(zhí)行函數(shù)key2()
case3: key3();break;//如果鍵值為3,則執(zhí)行函數(shù)key3()
case4: key4();break;//如果鍵值為4,則執(zhí)行函數(shù)key4()
……
default:;break;}3.4.1分支語句-switch語句實現(xiàn)循環(huán)結(jié)構(gòu)的語句有:while語句、do-while語句和for語句。1.while語句
while語句的語法形式為:3.4.2循環(huán)語句-while語句表達式是while循環(huán)能否繼續(xù)的條件,如果表達式為真,就重復(fù)執(zhí)行循環(huán)體語句;反之,則終止循環(huán)體內(nèi)的語句。while循環(huán)結(jié)構(gòu)的特點在于,循環(huán)條件的測試在循環(huán)體的開頭,如條件不成立,則循環(huán)體內(nèi)的重復(fù)操作一次也不能執(zhí)行。while(表達式){
循環(huán)體語句;}2.do-while語句do-while語句的語法形式如下:do{
循環(huán)體語句;}while(表達式);do-while語句的特點是先執(zhí)行內(nèi)嵌的循環(huán)體語句,再計算表達式,如果表達式的值為非0,則繼續(xù)執(zhí)行循環(huán)體語句,直到表達式的值為0時結(jié)束循環(huán)。3.4.2循環(huán)語句-do-while語句3.for語句for語句的語法形式如下:for(表達式1;表達式2;表達式3){
循環(huán)體語句;}for的執(zhí)行過程如下:①計算“表達式1”,表達式1通常稱為“初值設(shè)定表達式”。②計算“表達式2”,表達式2通常稱為“終值條件表達式”,若滿足條件,轉(zhuǎn)下一步,若不滿足條件,則轉(zhuǎn)步驟⑤。③執(zhí)行一次for循環(huán)體。④計算“表達式3”,“表達式3”通常稱為“更新表達式”,執(zhí)行完成后,轉(zhuǎn)向步驟②。⑤結(jié)束循環(huán),執(zhí)行for循環(huán)之后的語句。3.4.2循環(huán)語句-for語句【例3-3】分別用while語句、do-while語句和for語句編寫求和程序,求1+2+3+…+10的和。
voidmain(){unsignedintnum,sum;num=1;sum=0;while(num<=10){sum+=num;num++;}}參考程序1:voidmain(){unsignedintnum,sum;num=1;sum=0;do{sum+=num;
num++;}while(num<=10);}參考程序2:3.4.2循環(huán)語句-for語句voidmain(){
unsignedintnum,sum;
sum=0;
for(num=1;num<=10;num++)
sum+=num;}參考程序3:【例3-4】編寫賦值程序,使片內(nèi)RAM30H~3FH單元的內(nèi)容分別為00H~0FH。
dataunsignedcharbuffer[16]_at_0x30;voidmain(){
unsignedchari;
for(i=0;i<16;i++)
buffer[i]=i;}參考程序:3.4.2循環(huán)語句-for語句【例10】試編寫程序,將片內(nèi)RAM40H~50H單元的數(shù)據(jù)塊,全部搬移到片外RAM從2000H起始的存儲區(qū)域。
#defineucharunsignedchardataucharbuffer1[17]_at_0x40;xdatauchar buffer2[17]_at_0x2000;voidmain(){ uchari; for(i=0;i<17;i++) { buffer2[i]=buffer1[i]; } while(1);}3.4.2循環(huán)語句參考程序:【例11】試編寫程序?qū)⑵瑑?nèi)RAM以30H為起始地址的數(shù)據(jù)塊傳送到片外RAM以1000H為起始地址的區(qū)域,直到發(fā)現(xiàn)“#”字符,傳送停止。(假設(shè)數(shù)據(jù)塊長度為10)
#defineucharunsignedchardataucharbuffer1[10]_at_0x30;xdataucharbuffer2[10]_at_0x1000;voidmain(){ uchari; i=0; while((i<10)&&(buffer1[i]!=0x23)) { buffer2[i]=buffer1[i]; i++; } while(1);}參考程序:3.4.2循環(huán)語句【例12】試編寫程序,查找片外RAM以1000H為起始地址20個單元數(shù)據(jù)的最小值,并將結(jié)果送入片內(nèi)RAM30H單元。
#defineucharunsignedcharxdataucharbuffer[20]_at_0x1000;dataucharx_at_0x30;voidmain(){ uchari; x=0xff; for(i=0;i<20;i++) if(buffer[i]<x)x=buffer[i]; while(1);}參考程序:3.4.2循環(huán)語句3.5.1函數(shù)的定義和分類函數(shù)是一個完成一定相關(guān)功能的執(zhí)行代碼段。在高級語言中,函數(shù)與另外兩個名詞“子程序”和“過程”用來描述同樣的事情。一個C51程序必須至少有一個函數(shù),以main為名,稱為主函數(shù)。主函數(shù)是唯一的,整個程序從這個主函數(shù)開始執(zhí)行。從結(jié)構(gòu)上分,C51函數(shù)可分為主函數(shù)main()和普通函數(shù)兩種。而普通函數(shù)又分為兩種:標準庫函數(shù)和用戶自定義函數(shù)。
3.5C51的函數(shù)每個庫函數(shù)都在相應(yīng)的頭文件中給出了函數(shù)原型聲明,用戶如果需要使用庫函數(shù),必須在程序的開頭處采用預(yù)處理命令#include將有關(guān)頭文件包含進來。
例如,為便于對特殊功能寄存器進行讀寫操作,我們要在程序開頭處使用以下命令:3.5.1函數(shù)的定義和分類-C51標準庫函數(shù)#include<reg51.h>#include<stdio.h>調(diào)用輸出函數(shù)printf時,我們要在程序開頭處使用以下命令:(1)字符函數(shù)CTYPE.H。通常用來對字符做檢查和轉(zhuǎn)換。(2)內(nèi)部函數(shù)INTRINS.H。_crol_、_cror_可以實現(xiàn)變量循環(huán)移位,_nop_可以執(zhí)行一次空操作。(3)標準輸入/輸出函數(shù)STDIO.H。標準I/O函數(shù)通過MCS-51單片機的串行口讀寫數(shù)據(jù)。(4)標準函數(shù)STDLIB.H??梢酝瓿蓴?shù)據(jù)類型轉(zhuǎn)換以及存儲器分配操作。(5)字符串處理函數(shù)STRING.H。通常接收串指針作為輸入值。(6)絕對地址訪問函數(shù)ABSACC.H。(7)專用寄存器文件REGxx.H。包括了51系列所有的SFR及其中可尋址位(除P0~P3口外)的定義。3.5.1函數(shù)的定義和分類-C51標準庫函數(shù)(1)無參函數(shù)此種函數(shù)在被調(diào)用時,既無參數(shù)輸入,也不返回結(jié)果給調(diào)用函數(shù),只是為完成某種操作而編寫的函數(shù)。無參函數(shù)的定義形式為:無參函數(shù)一般不帶返回值,因此函數(shù)的返回值類型標識符可省略。返回值類型標識符函數(shù)名(){
函數(shù)體;}3.5.1函數(shù)的定義和分類-用戶自定義函數(shù)voiddelay1s(){ unsignedinti,j; for(i=0;i<1000;i++) for(j=0;j<125;j++);}【例3-5】已知單片機的fosc=12MHz,編寫一個延時1s的函數(shù)。分析:晶振頻率fosc=12MHz時,一個機器周期為12/fosc=1μs,因此延時1s需要消耗1000000個機器周期(1000000μs)。根據(jù)經(jīng)驗,利用C51的for語句進行內(nèi)部循環(huán)大約延時8個機器周期(不同的編譯器會產(chǎn)生不同的延時),因此將for語句循環(huán)125次可以得到1ms,采用兩個for嵌套語句可以得到1s。參考程序:3.5.1函數(shù)的定義和分類-用戶自定義函數(shù)(2)有參函數(shù)調(diào)用此種函數(shù)時,必須提供實際的輸入函數(shù)。有參函數(shù)的定義形式為:返回值類型標識符函數(shù)名(形式參數(shù)列表)形式參數(shù)說明{
函數(shù)體;}3.5.1函數(shù)的定義和分類-用戶自定義函數(shù)【例3-6】已知單片機的fosc=12MHz,編寫一個延時nms的函數(shù)。
voiddelaynms(unsignedintn){
unsignedinti,j;
for(i=0;i<n;i++)
for(j=0;j<125;j++);}參考程序:3.5.1函數(shù)的定義和分類-用戶自定義函數(shù)【例3-7】定義一個函數(shù)max(),用于求兩個數(shù)中的大數(shù)。
inta,b;intmax(a,b){ if(a>b)return(a); else
return(b);}參考程序:3.5.1函數(shù)的定義和分類-用戶自定義函數(shù)(3)空函數(shù)此種函數(shù)體內(nèi)是空白的。調(diào)用空函數(shù)時,什么工作也不做,不起任何作用。定義空函數(shù)的目的,并不是為了執(zhí)行某種操作,而是為了以后程序功能的擴充??蘸瘮?shù)的定義形式為:返回值類型標識符函數(shù)名(){}3.5.1函數(shù)的定義和分類-用戶自定義函數(shù)調(diào)用者稱為主調(diào)函數(shù),被調(diào)用者稱為被調(diào)函數(shù)。1.函數(shù)調(diào)用的一般形式3.5.2函數(shù)的調(diào)用-函數(shù)調(diào)用的一般形式函數(shù)名(實際參數(shù)列表);若被調(diào)函數(shù)是有參函數(shù),則主調(diào)函數(shù)必須把被調(diào)函數(shù)所需的參數(shù)傳遞給被調(diào)函數(shù)。傳遞給被調(diào)函數(shù)的數(shù)據(jù)稱為實際參數(shù)(簡稱實參),必須與形參的數(shù)據(jù)在數(shù)量、類型和順序上都一致。實參可以是常量、變量和表達式。實參對形參的數(shù)據(jù)是單向的,即只能將實參傳遞給形參。2.函數(shù)調(diào)用的方式(1)函數(shù)調(diào)用語句。把被調(diào)用函數(shù)的函數(shù)名作為主調(diào)函數(shù)的一個語句。例如:(2)函數(shù)結(jié)果作為表達式的一個運算對象。例如:要求被調(diào)用函數(shù)帶有return語句,以便返回一個明確的數(shù)值參加表達式的運算。(3)函數(shù)參數(shù)。被調(diào)用函數(shù)作為另一個函數(shù)的實際參數(shù)。例如:3.5.2函數(shù)的調(diào)用-函數(shù)調(diào)用的方式delay1s();result=2*max(a,b);m=max(a,max(u,v));【例3-10】89C51的P1口接了8個發(fā)光二極管,如右圖所示,請編程實現(xiàn)發(fā)光二極管由右向左流水顯示。
參考程序1:#include
<reg51.h>#include
<intrins.h> #define
uintunsignedint voiddelaynms(uintn) { uinti,j;for(i=0;i<n;i++)
for(j=0;j<125;j++);}voidmain(){ P1=0xfe; while(1) {delaynms(500); P1=_crol_(P1,1);}}3.8讀寫I/O端口的C51編程【例3-10】89C51的P1口接了8個發(fā)光二極管,如右圖所示,請編程實現(xiàn)發(fā)光二極管由右向左流水顯示。
參考程序2:#include
<reg51.h>#defineucharunsignedchar#define
uintunsignedint voiddelaynms(uintn) { uinti,j;for(i=0;i<n;i++)
for(j=0;j<125;j++);}3.8讀寫I/O端口的C51編程voidmain(){
uchari,temp;
while(1)
{
temp=0x01;
for(i=0;i<8;i++)
{
P1=~temp;
delaynms(500);
temp=temp<<1;
}
}}【例】89C51的P1口接了8個發(fā)光二極管,如下圖所示,請編程實現(xiàn)如下功能:1)讓其中一個發(fā)光二極管發(fā)光;2)讓其中一個發(fā)光二極管閃爍顯示,間隔時間為1s;3)兩只發(fā)光二極管交替閃爍顯示,間隔時間為1s;4)八只發(fā)光二極管依次流水顯示,間隔時間為1s。
3.8讀寫I/O端口的C51編程3.函數(shù)調(diào)用的條件(1)被調(diào)用函數(shù)必須是已經(jīng)存在的函數(shù)。(2)如果程序中使用了庫函數(shù),或使用了不在同一文件中的另外自定義函數(shù),則應(yīng)該在程序的開頭處使用#include包含語句。(3)如果程序中使用了自定義函數(shù),且該函數(shù)與調(diào)用它的函數(shù)同在一個文件中,則應(yīng)根據(jù)主調(diào)用函數(shù)與被調(diào)用函數(shù)在文件中的位置,決定是否對被調(diào)用函數(shù)做出說明。①如果被調(diào)用函數(shù)在主調(diào)用函數(shù)之后,一般應(yīng)在主調(diào)用函數(shù)中,在被調(diào)用函數(shù)調(diào)用之前,對被調(diào)用函數(shù)的返回值類型做出說明。②如果被調(diào)用函數(shù)出現(xiàn)在主調(diào)用函數(shù)之前,不用對被調(diào)用函數(shù)進行說明。通常把主函數(shù)main()放在最后。3.5.2函數(shù)的調(diào)用-函數(shù)調(diào)用的條件3.6.1數(shù)組的定義1.一維數(shù)組具有一個下標的數(shù)組元素組成的數(shù)組稱為一維數(shù)組,一維數(shù)組的形式如下:其中,數(shù)組名是一個標識符,元素個數(shù)是一個常量表達式,不能是含有變量的表達式。在定義數(shù)組時,可以對數(shù)組進行整體初始化,若定義后對數(shù)組賦值,則只能對每個元素分別賦值。3.6C51的數(shù)組類型說明符數(shù)組名[元素個數(shù)];2.二維數(shù)組或多維數(shù)組具有兩個或兩個以上下標的數(shù)組,稱為二維數(shù)組或多維數(shù)組。定義二維數(shù)組的一般形式如下:其中,數(shù)組名是一個標識符,行數(shù)和列數(shù)都是常量表達式。。二維數(shù)組可以在定義時進行整體初始化,也可在定義后單個地進行賦值。3.6.1數(shù)組的定義類型說明符數(shù)組名[行數(shù)][列數(shù)];3.字符數(shù)組若一個數(shù)組的元素是字符型的,則該數(shù)組就是一個字符數(shù)組。例如:C51還允許用字符串直接給字符數(shù)組置初值,例如:chara[10]={'H','E','L','L','O','!','\0'};chara[10]={"HELLO!"};用雙引號括起來的一串字符,稱為字符串常量,C51編譯器會自動地在字符串末尾加上結(jié)束符‘\0’(ASCII碼值為0的字符)。用單引號括起來的字符為字符的ASCII碼值,而不是字符串。一個字符串可以用一維數(shù)組來裝入,但數(shù)組的元素數(shù)目一定要比字符多一個,以便C51編譯器自動在其后面加入結(jié)束符'\0'。3.6.1數(shù)組的定義【例3-8】使用查表法,計算數(shù)0~9的平方。
#defineucharunsignedchar ucharcodesquare[10]={0,1,4,9,16,25,36,49,64,81};ucharfuction(ucharnumber){
returnsquare[number];} voidmain() {
ucharresult;
result=fuction(7);
while(1);}參考程序:3.6.2數(shù)組的應(yīng)用【例3-10】89C51的P1口接了8個發(fā)光二極管,如右圖所示,請編程實現(xiàn)發(fā)光二極管由右向左流水顯示。
參考程序3:3.6.2數(shù)組的應(yīng)用voidmain(){
uchari;
while(1)
{
for(i=0;i<8;i++)
{
P1=tab[i];
delaynms(500);
}
}}#include
<reg51.h>#include
<intrins.h> #defineucharunsignedchar#define
uintunsignedintuchar
codetab[]={0xfe,0xfd,
0xfb,0xf7,0xef,0xdf,0xbf,0x7f};voiddelaynms(uintn) { uinti,j;for(i=0;i<n;i++)
for(j=0;j<125;j++);}【例13】試編寫程序,求平方和c=a2+b2,設(shè)a、b分別存于內(nèi)部RAM的40H、41H兩個單元(假設(shè)a、b均小于10),計算結(jié)果存在內(nèi)部RAM的42H單元中。
#defineucharunsignedchardataucharx_at_0x40;datauchary_at_0x41;dataucharz_at_0x42;ucharcodesquare[10]={0,1,4,9,16,25,36,49,64,81};ucharfuction(ucharnumber){
returnsquare[number];} voidmain() { z=fuction(x)+fuction(y);
while(1);} 參考程序1:3.6.2數(shù)組的應(yīng)用#defineucharunsignedchar#include<absacc.h>#definexDBYTE[0x40]#defineyDBYTE[0x41]#definezDBYTE[0x42]ucharcodesquare[10]={0,1,4,9,16,25,36,49,64,81};ucharfuction(ucharnumber){
returnsquare[number];} voidmain() { z=fuction(x)+fuction(y);
while(1);} 參考程序2:3.7.1指針與地址
一個程序的指令、常量和變量等都要存放在機器內(nèi)存單元中,而機器內(nèi)存是按字節(jié)來劃分存儲單元的。
每個存儲單元都賦予一個編號,這就是存儲單元的地址。
每個存儲單元中所存放的數(shù)據(jù),稱為該存儲單元的內(nèi)容。
變量的地址就稱為該變量的指針。專門用來存放另一個變量的地址的變量,則稱之為“指針變量”。3.7C51的指針-指針與地址
為了表示指針變量和它所指向的變量之間的關(guān)系,C語言中用符號“*”來表示“指向”。3.7.1指針與地址符號“*”稱為指針運算符,它只能與指針變量一起聯(lián)用,結(jié)果是得到該指針變量所指向變量的值。指針的定義:“標識符”:是所定義的指針名。“數(shù)據(jù)類型”:說明該指針所指向的變量的類型。“存儲器類型1”:指針所指數(shù)據(jù)的存儲器空間?!按鎯ζ黝愋?”:指針變量本身的存儲器空間。3.7.2指針的定義“存儲器類型1”和“存儲器類型2”是可選項,它是KeilC51編譯器的一種擴展。數(shù)據(jù)類型[存儲器類型1]*[存儲器類型2]標識符;一般指針的語句如下:c_ptr、i_ptr、l_ptr全部位于MCS-51單片機的片內(nèi)數(shù)據(jù)存儲器中。可指定一般指針本身的存儲器空間位置,例如:3.7.2指針的定義-一般指針char*c_ptr;int*i_ptr;long*l_ptr;
char*xdatastrptr; //位于xdata空間的一般指針int*datanumptr; //位于data空間的一般指針long*idatavarptr; //位于idata空間的一般指針指定對象具有明確的存儲器空間,例如:指定指針本身的存儲器空間位置,例如:3.7.2指針的定義-基于存儲器的指針chardata*str;
//指向
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 滬科版八年級數(shù)學(xué)上冊第15章軸對稱圖形與等腰三角形15-2線段的垂直平分線課件
- 九年級英語語法專項三代詞一周強化人教實驗版
- 2024-2025學(xué)年版塊10 浮力 專題10-1 浮力的計算方法 (含答案) 初中物理尖子生自主招生培優(yōu)講義83講
- DB1410T 067-2024花生地下害蟲綜合防治技術(shù)規(guī)程
- 內(nèi)蒙古開來中學(xué)2023-2024學(xué)年中考沖刺卷數(shù)學(xué)試題含解析
- 吉林省四平市雙遼市 2024-2025學(xué)年八年級上學(xué)期10月期中數(shù)學(xué)試題(無答案)
- 幼兒園卡通課件
- 安全注射課件教學(xué)課件
- 溫棚用工合同模板
- 項目投資監(jiān)管合同模板
- 合規(guī)性評價記錄表
- SPSS第十講-線性回歸分析
- 青島版六年級上冊《比的認識》課件
- 國企施工資源配置講義
- 常見服裝英語課件
- 《無人機概述及系統(tǒng)組成》考試復(fù)習(xí)題庫(含解析)
- 江蘇省鎮(zhèn)江市各縣區(qū)鄉(xiāng)鎮(zhèn)行政村村莊村名居民村民委員會明細
- 2022年上海市松江區(qū)中考二模語文試卷及答案
- 幼兒園垃圾分類整改措施報告
- 第9課《美麗的顏色》課件(共25張PPT) 部編版語文八年級上冊
- 初中體育人教七年級體育(劉東)室內(nèi)課教學(xué)設(shè)計《體育保健按摩》
評論
0/150
提交評論