單片機課件單片機的C語言編程.ppt
《單片機課件單片機的C語言編程.ppt》由會員分享,可在線閱讀,更多相關(guān)《單片機課件單片機的C語言編程.ppt(92頁珍藏版)》請在裝配圖網(wǎng)上搜索。
第10章單片機的C語言編程 單片機原理 接口及應用 內(nèi)容提要 C51程序結(jié)構(gòu) C51的數(shù)據(jù)類型 數(shù)據(jù)的存貯類型和存貯模式 C51對SFR 可尋址位 存儲器和I O口的定義 C51的運算符 函數(shù) C語言編程實例 單片機資源的C語言編程實例 匯編語言和C語言的混合編程 C語言函數(shù)庫的管理與使用 小結(jié) 51系列單片機支持三種高級語言 即PL M C和BASIC 8052單片機內(nèi)固化有解釋BASIC語言 BASIC語言適用于簡單編程而對編程效率運行速度要求不高的場合 PL M是一種結(jié)構(gòu)化的語言 很象PASCAL PL M編譯器好象匯編器一樣產(chǎn)生緊湊的機器代碼 可以說是高級匯編語言 但它不支持復雜的算術(shù)運算 無豐富庫函數(shù)支持 學習PL M無異于學習一種新的語言 C語言是一種通用的程序設計語言 其代碼率高 數(shù)據(jù)類型及運算符豐富 并具有良好的程序結(jié)構(gòu) 適用于各種應用的程序設計 是目前使用較廣的單片機編程語言 單片機的C語言采用C51編譯器 簡稱C51 由C51產(chǎn)生的目標代碼短 運行速度高 所需存儲空間小 符合C語言的ANSI標準 生成的代碼遵循Intel目標文件格式 而且可與A51匯編語言或PL M51語言目標代碼混和使用 應用C51編程具有以下優(yōu)點 1 C51管理內(nèi)部寄存器和存貯器的分配 編程時 無需考慮不同存儲器的尋址和數(shù)據(jù)類型等細節(jié)問題 程序由若干函數(shù)組成 具有良好的模塊化結(jié)構(gòu) 有豐富的子程序庫可直接引用 從而大大減少用戶編程的工作量 C語言和匯編語言可以交叉使用 匯編語言程序代碼短 運行速度快 但復雜運算編程耗時 如果用匯編語言編寫與硬件有關(guān)的部分程序 用C語言編寫與硬件無關(guān)的運算部分程序 充分發(fā)揮兩種語言的長處 可以提高開發(fā)效率 10 1C51程序結(jié)構(gòu) 同標準C一樣 C51的程序由一個個函數(shù)組成 這里的函數(shù)和其他語言的 子程序 或 過程 具有相同的意義 其中必須有一個主函數(shù)main 程序的執(zhí)行從main 函數(shù)開始 調(diào)用其他函數(shù)后返回主函數(shù)main 最后在主函數(shù)中結(jié)束整個程序而不管函數(shù)的排列順序如何 C語言程序的組成結(jié)構(gòu)如下所示 全局變量說明 可被各函數(shù)引用 main 主函數(shù) 局部變量說明 只在本函數(shù)引用 執(zhí)行語句 包括函數(shù)調(diào)用語句 fun1 形式參數(shù)表 函數(shù)1 形式參數(shù)說明 局部變量說明執(zhí)行語句 包括調(diào)用其他函數(shù)語句 funn 形式參數(shù)表 函數(shù)n 形式參數(shù)說明 局部變量說明執(zhí)行語句 C語言的語句規(guī)則 1 每個變量必須先說明后引用 變量名英文大小寫是有差別的 2 C語言程序一行可以書寫多條語句 但每個語句必須以 結(jié)尾 一個語句也可以多行書寫為好 3 C語言的注釋用 表示 4 花括號必須成對 位置隨意 可在緊挨函數(shù)名后 也可另起一行 多個花括號可以同行書寫 也可逐行書寫 為層次分明 增加可讀性 同一層的 花括號對齊 采用逐層縮進方式書寫 10 2C51的數(shù)據(jù)類型 C51的數(shù)據(jù)有常量和變量之分 常量 在程序運行中其值不變的量 可以為字符 十進制數(shù)或十六進制數(shù) 用0 x表示 常量分為數(shù)值型常量和符號型常量 如果是符號型常量 需用宏定義指令 define 對其進行定義 相當于匯編的 EQU 偽指令 如 definePI3 1415那么程序中只要出現(xiàn)PI的地方 編譯程序都譯為3 1415 變量 在程序運行中其值可以改變的量 一個變量由變量名和變量值構(gòu)成 變量名即是存貯單元地址的符號表示 而變量的值就是該單元存放的內(nèi)容 定義一個變量 編譯系統(tǒng)就會自動為它安排一個存貯單元 具體的地址值用戶不必在意 10 2 1C51變量的數(shù)據(jù)類型 無論哪種數(shù)據(jù)都是存放在存貯單元中的 每一個數(shù)據(jù)究竟要占用幾個單元 即數(shù)據(jù)的長度 都要提供給編譯系統(tǒng) 正如匯編語言中存放數(shù)據(jù)的單元要用DB或DW偽指令進行定義一樣 編譯系統(tǒng)以此為根據(jù)預留存貯單元 這就是定義數(shù)據(jù)類型的意義 C51編譯器支持數(shù)據(jù)類型見表10 1 表10 1C51的數(shù)據(jù)類型 對表10 1作如下說明 1 字符型 char 整型 int 和長整型 long 均有符號型 signed 和無符號型 unsigned 兩種 如果不是必須 盡可能選擇unsigned型 這將會使編譯器省卻符號位的檢測 使生成的程序代碼比signed類型短得多 2 程序編譯時 C51編譯器會自動進行類型轉(zhuǎn)換 例如將一個位變量賦值給一個整型變量時 位型值自動轉(zhuǎn)換為整型值 當運算符兩邊為不同類型的數(shù)據(jù)時 編譯器先將低級的數(shù)據(jù)類型轉(zhuǎn)換為較高級的數(shù)據(jù)類型 運算后 運算結(jié)果為高級數(shù)據(jù)類型 3 51單片機內(nèi)部數(shù)據(jù)存貯器的可尋址位 20H 2FH 定義為bit型 而特殊功能寄存器的可尋址位 即地址為X0H和X8H的SFR的各位 只能定義為sbit類型 10 2 2關(guān)于指針型數(shù)據(jù) 1 關(guān)于指針型變量在匯編語言程序中 要取存貯單元m的內(nèi)容可用直接尋址方式 也可用寄存器間接尋址方式 如果用R1寄存器指示m的地址 用 R1取m單元的內(nèi)容 相對應的在C語言中用變量名表示取變量的值 相當于直接尋址 也可用另一個變量 如P 存放m的地址 P就相當于R1寄存器 用 P取得m單元的內(nèi)容 相當于匯編的間接尋址方式 這里P即為指針型變量 下面表格表示兩種語言將m單元的內(nèi)容送n單元的對照語句 注 上表省略了匯編語言程序中對符號地址n和m用EQU偽指令進行具體地址定義的語句以及C語言對變量n m和指針變量P進行類型定義的語句 實際程序設計中 此步是不可缺少的 表中 為取地址運算符 為取內(nèi)容運算符 表1O 2匯編語言和C語言的對照 2 指針型數(shù)據(jù)的類型由于C51是結(jié)合51單片機硬件的 51單片機的不同存貯空間 有不同的地址范圍 即使對于同一外部數(shù)據(jù)存貯器 又有用 Ri分頁尋址 Ri為八位 和用 DPTR尋址 DPTR為十六位 兩種尋址方式 而指針本身也是一個變量 有它存放的存貯區(qū)和數(shù)據(jù)長度 因此 在指針類型的定義中要說明 被指的變量的數(shù)據(jù)類型和存貯類型 指針變量本身的數(shù)據(jù)類型 占幾個字節(jié) 和存貯類型 即指針本身存放在什么存貯區(qū) 例如類型定義為data或idata 表示指針指示內(nèi)部數(shù)據(jù)存貯器 而pdata表示指針指向外部數(shù)據(jù)存貯器 用 Ri間址 以上均為八位地址 而類型code xdata表示指針指向外部程序存貯器或外部數(shù)據(jù)存貯器指針 本身 即被指示地址 應為十六位長度 如果想使指針能適用于指向任何存貯空間 則可以定義指針為通用型 此時指針長度為3字節(jié) 第一字節(jié)表示存貯器類型編碼 第二 三字節(jié)分別表示所指地址的高位和低位 第一字節(jié)表示的存貯器類型編碼見表10 3 表10 3通用型指針的存貯類型編碼 10 3數(shù)據(jù)的存貯類型和存貯模式 10 3 1數(shù)據(jù)的存貯類型C51是面向8XX51系列單片機及硬件控制系統(tǒng)的開發(fā)語言 它定義的任何變量必須以一定的存貯類型的方式定位在8XX51的某一存貯區(qū)中 否則便沒有意義 因此在定義變量類型時 還必須定義它的存貯類型 C51的變量的存貯類型如表10 4所示 表10 4C51的變量的存貯類型 訪問內(nèi)部數(shù)據(jù)存貯器 idata 比訪問外部數(shù)據(jù)存貯器 xdata 相對要快一些 因此 可將經(jīng)常使用的變量置于內(nèi)部數(shù)據(jù)存貯器中 而將較大及很少使用的數(shù)據(jù)變量置于外部數(shù)據(jù)存貯器中 例如定義變量x語句 datacharx 等價于chardatax 如果用戶不對變量的存貯類型定義 則編譯器承認默認存貯類型 默認的存貯類型由編譯控制命令的存貯的模式部分決定 10 3 2存貯器模式 存貯器模式?jīng)Q定了變量的默認存貯器類型 參數(shù)傳遞區(qū)和無明確存貯區(qū)類型的說明 C51的存貯器模式有SMALL LARGE和COMPACT 見表10 5 在固定的存貯器地址進行變量參數(shù)傳遞是C51的一個標準特征 在SMALL模式下參數(shù)傳遞是在內(nèi)部數(shù)據(jù)存貯區(qū)中完成的 LARGE和COMPACT模式允許參數(shù)在外部存貯器中傳遞 C51同時也支持混合模式 例如在LARGE模式下生成的程序可將一些函數(shù)分頁放入SMALL模式中從而加快執(zhí)行速度 例如設C語言源程序為PROR C 若使程序中的變量類型和參數(shù)傳遞區(qū)限定在外部數(shù)據(jù)存貯區(qū) 有兩種方法 方法1 用C51對PROR C進行編譯時 使用命令C51PROR CCOMPACT 方法2 在程序的第一句加預處理命令 pragmacompact 表10 5存貯器模式 10 3 3變量說明舉例 datacharvar 字符變量var定位在片內(nèi)數(shù)據(jù)存貯區(qū) charcodeMSG PARAMETER 字符數(shù)組MSG 定位在程序存貯區(qū) unsignedlongxdataarray 100 無符號長型數(shù)組定位在片外RAM區(qū) 每元素占4bytes floatidatax y z 實型變量x y z 定位在片內(nèi)用間址訪問的內(nèi)部RAM區(qū) bitlock 位變量Lock定位在片內(nèi)RAM可位尋址區(qū) unsignedintpdatasion 無符號整型變量sion定位在分頁的外部RAM unsignedcharxdatavector 10 4 4 無符號字符型三維數(shù)組 定位在片外RAM區(qū) sfrP0 0 x80 定義P0口 地址為80H charbdataflags 字符變量flags定位在可位尋址內(nèi)部RAM區(qū) sbitflag0 flags 0 定義flag0為flags 0 如果在變量說明時略去存貯器類型標志符 編譯器會自動選擇默認的存貯器類型 默認的存貯器類型由控制指令SMALL COMPACT和LARGE限制 例如如果聲明charvar 則默認的存貯器模式為SMALL var放在data存貯區(qū) 如果使用COMPACT模式 var放入idata存貯區(qū) 在使用LARGE模式的情況下 var被放入外部數(shù)據(jù)存貯區(qū) xdata存貯區(qū) 10 3 4指針變量說明舉例longxdata px 指針px指向long型xdata區(qū) 每個數(shù)據(jù)占四個單元 指針自身在默認存貯器 如不指定編譯模式在data區(qū) 指針長度為2個字節(jié) charxdata datapd 指針pd指向字符型xdata區(qū) 自身在data區(qū) 長度2字節(jié) datacharxdata pd 與上例等效 dataint pn 和int datapn及intr pn等效 定義一個類型為int型的通用型指針 指針自身在data區(qū)長度為3字節(jié) 在上例的指針聲明中包含如下幾個內(nèi)容 1 1 指針變量名 如px 前面冠以 表示px為指針型變量 此處 不帶取內(nèi)容之意 2 指針指向的存貯類型 即指向哪個存貯區(qū) 它決定了指針本身的長度 見表10 1 存貯類型聲明的位置在數(shù)據(jù)類型和指針名 如 px 之間 如無次項聲明 則此指針型變量為通用型 3 3 指針指向的存貯區(qū)的數(shù)據(jù)類型 即被指向的存貯區(qū)以多少個單元作一個數(shù)據(jù)單位 當程序通過指針對該區(qū)操作時 將按此規(guī)定的單元個數(shù)的內(nèi)容作為一個數(shù)據(jù)操作 4 指針變量自身的存貯類型 即指針處于什么區(qū)與自身的長度無關(guān) 該聲明可位于聲明語句的開頭 也可在 和變量名之間 此項由編譯模式放在默認區(qū) 如無規(guī)定編譯模式 通常在data區(qū) 10 4C51對SFR 可尋址位 存儲器和I O口的定義 10 4 1特殊功能寄存器SFR定義C51提供了一種自主形式的定義方式 使用特定關(guān)鍵字sfr如sfrSCON 0 x98 串行通信控制寄存器地址98H sfrTMOD 0 x89 定時器模式控制寄存器地址89H sfrACC 0 xe0 A累加器地址E0H sfrP1 0 x90 P1端口地址90H 定義了以后 程序中就可以直接引用寄存器名 C51也建立了一個頭文件reg51 h 增強型為reg52 h 在該文件中對所有的特殊功能寄存器的進行了sfr定義 對特殊功能寄存器的有位名稱的可尋址位進行了sbit定義 因此 只要用包含語句 include 就可以直接引用特殊功能寄存器名 或直接引用位名稱 要特別注意 在引用時特殊功能寄存器或者位名稱必須大寫 10 4 2對位變量的定義 C51對位變量的定義有三種方法 1 將變量用bit類型的定義符定義為bit類型 如bitmn mn為位變量 其值只能是 0 或 1 其位地址C51自行安排在可位尋址區(qū)的bdata區(qū) 2 采用字節(jié)尋址變量 位的方法 如bdataintibase ibase定義為整型變量 sbitmybit ibase 15 mybit定義為ibase的D15位 這里位是運算符 相當于匯編中的 其后的最大取值依賴于該位所在的字節(jié)尋址變量的定義類型 如定義為char最大值只能為7 3 對特殊功能寄存器的位的定義方法1 使用頭文件及sbit定義符 多用于無位名的可尋址位 例如 includesbitP1 1 P1 1 P1 1為P1口的第1位 sbitac ACC 7 ac定義為累加器A的第7位 方法2 使用頭文件reg51 h 再直接用位名稱 例如 includeRS1 1 RS0 0 方法3 用字節(jié)地址位表示例如sbitOV 0 xD0 2 方法4 用寄存器名 位定義例如sfrPSW 0 xd0 定義PSW地址為d0H sbitCY PSW 7 CY為PSW 7 10 4 3C51對存貯器和外接I O口的絕對地址訪問 1 對存貯器的絕對地址訪問利用絕對地址訪問的頭文件absacc h可對不同的存貯區(qū)進行訪問 該頭文件的函數(shù)有 CBYTE 訪問code區(qū)字符型 DBYTE 訪問data區(qū)字符型 PBYTE 訪問pdata或I O區(qū)字符型 XBYTE 訪問xdata或I O區(qū)字符型 還有CWORD DWORD PWORD和XWORD四個函數(shù) 它們的訪問區(qū)域同上 只是訪問的類型為int型 例10 1 include definecomXBYTE 0 x07ff 那么后面程序com變量出現(xiàn)的地方 就是對地址為07ffH的外部RAM或I O口進行訪問 例10 2XWORD 0 0 x9988 即將9988H int類型 送入外部RAM的0號和1號單元 使用中要注意 absacc h一定要包含進程序 XBYTE必須大寫 2 對外部I O口的訪問由于單片機的I O口和外部RAM統(tǒng)一編址 因此對I O口地址的訪問可用XBYTE MOVX DPTR 或PBYTE MOVX Ri 進行 例10 3XBYTE 0Xefff 0 x10 將10H輸出到地址為EFFFH端口 10 5C51的運算符 1 賦值運算符 將 的右邊的值賦值給左邊的變量 2 C51的算術(shù)運算符 加或正號 減或負號 乘號 除號 求余 優(yōu)先級為 先乘除 后加減 先括號內(nèi) 再括號外3 C51的關(guān)系運算符有六種 小于 大于 小于等于 大于等于 相等 不相等 優(yōu)先級 前四個高 后二個 和 級別低 4 C51的邏輯運算符有三種 邏輯表達式和關(guān)系表達式的值相同 以0代表假 以1代表真 以上三種運算的優(yōu)先級見圖10 1 5 C51的按位操作的運算符有六種 按位與 按位或 按位異或 位取反 位右移 注 補零移位 例1 a 0 xf0H 表達式a a值為0FH例2 a 0 xea 表達式a 2值為A8H 即a值左移兩位 移位后空白位補0 6 自增 自減運算符 i i 在使用i之前 先使i值加1 減1 i i 在使用i之后 再使i值加1 減1 例設i原值為5j i則j值為6 i值也為6j i 則j值為5 i值為6 非 算術(shù)運算 關(guān)系運算 和 賦值運算 圖10 1運算符的優(yōu)先級 7 復合賦值運算符 例 a b相當于a a b a 7 相當于a a 7 8 對指針操作的運算符 取地址運算 間址運算符例a b 取b變量的地址送變量ac b 將以b的內(nèi)容為地址的單元的內(nèi)容送c這里要注意 與按位與運算符的差別 如果 為 與 的兩邊必須為變量或常量 與指針定義時指針前的 的差別 如char pt 這里的 只表示pt為指針變量 不代表間址取內(nèi)容的運算 10 6函數(shù) C語言程序由函數(shù)組成 下面介紹函數(shù)的要點 10 6 1函數(shù)的分類及定義從用戶使用角度劃分 函數(shù)分為庫函數(shù)和用戶自定義函數(shù) 庫函數(shù)是編譯系統(tǒng)為用戶設計的一系列標準函數(shù) 見本書附錄二 用戶只需調(diào)用 而無需自己去編寫這些復雜的函數(shù) 如前面所用到的頭文件reg51 h absacc h等 有的頭文件中包括一系列函數(shù) 要使用其中的函數(shù)必須先使用 include包含語句 然后才能調(diào)用 用戶自定義函數(shù)是用戶根據(jù)任務編寫的函數(shù)從參數(shù)形式上函數(shù)分為無參函數(shù)和有參函數(shù) 有參函數(shù)即是在在調(diào)用時 調(diào)用函數(shù)用實際參數(shù)代替形式參數(shù) 調(diào)用完返回結(jié)果給調(diào)用函數(shù) 10 6 2函數(shù)的定義 函數(shù)以 開始 以 結(jié)束 無參函數(shù)的定義 返回值類型函數(shù)名 函數(shù)體語句 如果函數(shù)沒有返回值 可以將返回值類型設為void 有參函數(shù)的定義 返回值類型函數(shù)名 形式參數(shù)表列 形式參數(shù)類型說明 函數(shù)體語句return 返回形參名 也可以這樣定義返回值類型函數(shù)名 類型說明形式參數(shù)表列 函數(shù)體語句return 返回參形名 其中形式參數(shù)表列的各項要用 隔開 通過return語句將需返回的值返回給調(diào)用函數(shù) 10 6 3函數(shù)的調(diào)用 函數(shù)調(diào)用的形式為 函數(shù)名 實際參數(shù)表列 實參和形參的數(shù)目相等類型一致 對于無參函數(shù)當然不存在實際參數(shù)表列 函數(shù)的調(diào)用方式有三種 函數(shù)調(diào)用語句 即把被調(diào)函數(shù)名作為調(diào)用函數(shù)的一個語句 如fun1 被調(diào)函數(shù)作為表達式的運算對象 如result 2 get a b 此時get函數(shù)中的a b應為實參 其以返回值參予式中的運算 被調(diào)函數(shù)作為另一個數(shù)的實際參數(shù)如m max a get a b 函數(shù)get a b 作為函數(shù)max 的一個實際參數(shù) 10 6 4對被調(diào)函數(shù)的說明 如果被調(diào)函數(shù)出現(xiàn)在主調(diào)函數(shù)之后 在主調(diào)函數(shù)前應對被調(diào)函數(shù)作以說明 形式為 返回值類型被調(diào)函數(shù)名 形參表列 如果被調(diào)函數(shù)出現(xiàn)在主調(diào)函數(shù)之前 可以不對被調(diào)函數(shù)說明 下面以一個簡單例子來說明intfun1 a b inta b intc c a b return c main intd 0u 3 v 2 d 2 fun u v 上例被調(diào)函數(shù)在主調(diào)函數(shù)前 不用說明 intfun1 a b main intd u 3 v 2 d 2 fun1 u v intfun1 a b inta b intc c a b return c 上例中被調(diào)函數(shù)在主調(diào)函數(shù)后 在前面對被調(diào)函數(shù)進行說明 10 7C語言編程實例 為了使C語言的編程方法和匯編語言的編程方法有一個對比 本節(jié)采用3 1節(jié)的例題 由于C51編譯器是針對單片機的 因此ANSIC中的scanf和printf等對PC電腦的鍵盤和監(jiān)視器的輸入 輸出語句無效 運算的數(shù)據(jù)可以通過變量置入或取出 這時C51會自動安排使用的存貯單元 當然也可以用戶自行通過具體的內(nèi)存地址置入數(shù)據(jù)或從特定地址取出數(shù)據(jù) 這就少不了要會觀察具體地址的內(nèi)容或改變該地址的內(nèi)容 C語言的編程上機調(diào)試見本教材的實驗部分 下面通過一個例子說明C語言程序編譯后生成的機器代碼及對應的反匯編程序 從中引出一些道理 10 7 1順序程序的設計 例10 5完成19805 24503的編程分析 兩個乘數(shù)比較大 其積更大 采用unsignedlong類型 設乘積存放在外部數(shù)據(jù)存貯器0號開始的單元 程序如下 main unsignedlongxdata p 設定指針p指向類型為unsignedlong的外部RAM區(qū) unsignedlonga 19805 設置a為unsignedlong類型 并賦初值 unsignedlongb 24503 c 設置b和積為unsignedlong類型 并賦初值 p 0 設地址指向0號單元 c a b p c 積存入外部RAM0號單元 上機通過WAVE軟件仿真調(diào)試 在變量觀察窗口看到運算結(jié)果c 48528195 即為乘積的十進制數(shù) 觀察XDATA區(qū) 外部RAM 的0000H 0003H單元分別為1CECD07B 即存放的為乘積的十六進制數(shù) 觀察DATA區(qū) 內(nèi)部RAM區(qū) 地址0405060708090A0B0C0D0E0F1CECD07B00004D5D00005FB7C變量 積 a變量b變量可見定義為unsignedlong類型 給每個變量分配四個單元 如果定義類型不對 將得不到正確的結(jié)果 對于復雜的運算通常采用查表的方法 如同匯編程序設計一樣 在程序存貯器建立一張表 在C語言中表格定義為數(shù)組 表內(nèi)數(shù)據(jù) 元素 的偏移量表現(xiàn)為下標 數(shù)組的使用如同變量一樣 要先進行定義 說明數(shù)組名 維數(shù) 數(shù)據(jù)類型和存貯類型 在定義數(shù)組的同時 還可以給數(shù)組各元素賦初值 通過下例說明C51數(shù)組的定義方法和用C語言編查表程序的方法 例10 6片內(nèi)RAM20H單元存放著一個0 05H的數(shù) 用查表法 求出該數(shù)的平方值放入內(nèi)部RAM21H單元 main charx pcharcodetab 6 0 1 4 9 16 25 p 0 x20 x tab p p p x 10 7 2循環(huán)程序的設計 C語言的循環(huán)語句有以下幾種形式1 while 表達式 語句 其中表達式為循環(huán)條件 語句為循環(huán)體 當表達式值為真 值為非0 重復執(zhí)行 語句 語句可只一條以 結(jié)尾 可以多條組成復合語句 復合語句必須用 括起 也可以沒有語句 通常用于等待中斷 或查詢 2 do 語句 while 表達式 表達式為真執(zhí)行循環(huán)體 語句 直至表達式為假 退出循環(huán)執(zhí)行下一個語句 3 for 表達式1 表達式2 表達式3 語句 其中語句為循環(huán)體 執(zhí)行過程是 執(zhí)行表達式1后進入循環(huán)體 如表達式2為假 按表達式3修改變量 再執(zhí)行循環(huán)體 直到表達式2為真 語句中的表達式可以省其中任一項甚至全部 但二個分號不可省 如for 語句 為無限循環(huán) for i 4 i 語句 i從4開始無限循環(huán) for i 100 相當于while i 100 例10 7while P1 本程序完成0 1 2 10的累加 執(zhí)行后sum 55 例10 9將例10 8改用for語句編程main intsum 0 i for i 0 i 10 i sun i 10 7 3分支程序的設計 C語言的分支選擇語句有以下幾種形式 1 if 表達式 語句 句中表達式為真執(zhí)行語句 否則執(zhí)行下一條語句 當花括號中的語句不只一條 花括號不能省 2 if 表達式 語句1 else 語句2 句中表達式為真執(zhí)行語句1 否則執(zhí)行語句2為了能無論哪種情況 執(zhí)行完后都執(zhí)行下一條語句 if語句可以嵌套 3 switch 表達式 case常量表達式1 語句1 break case常量表達式2 語句2 break case常量表達式n 語句n break default 語句n 1 說明 語句先進行表達式的運算 當表達式的值與某一case后面的常量表達式相等 就執(zhí)行它后面的語句 當case語句后有break語句時 執(zhí)行完這一case語句后 跳出switch語句 當case后面無break語句 程序?qū)?zhí)行下一條case語句 如果case中常量表達式值和表達式的值都不匹配 就執(zhí)行default后面的語句 如果無default語句就退出switch語句 default的次序不影響執(zhí)行的結(jié)果 也可無此語句 case語句適于多分支轉(zhuǎn)移的情況下使用 例10 10片內(nèi)RAM的20H單元存放一個有符號數(shù)x 函數(shù)y與x有如下關(guān)系式 xx 0y 20Hx 0 x 5x 0設y存放于21H單元 程序如下main charx p y p 0 x20 y 0 x21 for x p if x 0 y x if x 0 y x 5 if x 0 y 0 x20 程序中為觀察不同數(shù)的執(zhí)行結(jié)果 采用了死循環(huán)語句for 上機調(diào)試時退出死循環(huán)可用Ctrl C 例10 11有兩個數(shù)a和b 根據(jù)R3的內(nèi)容轉(zhuǎn)向不同的處理子程序 r3 0 執(zhí)行子程序pr0 完成兩數(shù)相加 r3 1 執(zhí)行子程序pr1 完成兩數(shù)相減 r3 2 執(zhí)行子程序pr2 完成兩數(shù)相乘 r3 3 執(zhí)行子程序pr3 完成兩數(shù)相除 分析 C語言中的子程序即為函數(shù) 因此需編四個處理的函數(shù) 如果主函數(shù)在前 主函數(shù)要對子函數(shù)進行說明 如果子函數(shù)在前 主函數(shù)無須對子函數(shù)說明 但是無論子 主函數(shù)的順序如何 程序總是從主函數(shù)開始執(zhí)行 執(zhí)行到調(diào)用子函數(shù)就會轉(zhuǎn)到子函數(shù)執(zhí)行 在C51編譯器中通過頭文件reg51 h可以識別特殊功能寄存器 但不能識別R0 R7通用寄存器 因此R0 R7只有通過絕對地址訪問識別 程序如下 include definer3DBYTE 0 x03 intc c1 a b pr0 c a b pr1 c a b pr2 c a b pr3 c a b main a 90 b 30 for switch r3 case0 pr0 break case1 pr1 break case2 pr2 break case3 pr3 break c1 56 在上述程序中 為便于調(diào)試觀察 加了C1 56語句 并使用了死循環(huán)語句for 用Ctrl C可退出死循環(huán) 10 8單片機資源的C語言編程實例 例10 12在3 1節(jié)曾用匯編語言完成了外部RAM的000EH單元和000FH單元的內(nèi)容交換 現(xiàn)改用C語言編程 C語言對地址的指示方法可以采用指針變量 也可以引用absacc h頭文件作絕對地址訪問 下面采用絕對地址訪問方法 includemain charc for c XBYTE 14 XBYTE 14 XBYTE 15 XBYTE 15 c 程序中為方便反復觀察 使用了死循環(huán)語句for 只要用Ctrl C即可退出死循環(huán) 上面程序通過編譯 生成的機器代碼和反匯編程序如下 0000020014LJMP0014H000390000EMOVDPTR 000EH0006E0MOVXA DPTR0007FFMOVR7 A0008A3INCDPTR0009E0MOVXA DPTR000A90000EMOVDPTR 000EH000DF0MOVX DPTR A000EA3INCDPTR000FEFMOVA R70010F0MOVX DPTR A 001180F0SJMP0003H001322RET0014787FMOVR0 7FH0016E4CLRA0017F6MOV R0 A0018D8FDDJNZR0 0017H001A758107MOVSP 07H001D020003LJMP0003H 例中可見 一進入C語言程序 首先執(zhí)行初始化 將內(nèi)部RAM的0 7FH128個單元清零 然后置SP為07H 視變量多少不同 SP置不同值 依程序而定 因此如果要對內(nèi)部RAM置初值 一定要在執(zhí)行了一條C語言語句后進行 C語言程序設定的變量 C51自行安排寄存器或存貯器作參數(shù)傳遞區(qū) 通常在R0 R7 一組或兩組 視參數(shù)多少定 因此 如果對具體地址置數(shù)據(jù) 應避開這些R0 R7的地址 如果不特別指定變量的存貯類型 通常被安排在內(nèi)部RAM中 10 8 2并行口及鍵盤的C語言編程 例10 13用P1 0輸出1KHz和500Hz的音頻信號驅(qū)動揚聲器 作報警信號 要求1KHz信號響100ms 500Hz信號響200ms 交替進行 P1 7接一開關(guān)進行控制 當開關(guān)合上 響報警信號 當開關(guān)斷Kk告警信號停止 編出程序 分析500Hz信號周期為2ms 信號電平為每1ms變反一次 1KHz信號周期為1ms 信號電平每500 s變反一次 用C語言編程如下 includesbitP10 P1 0 sbitP17 P1 7 main unsignedchari j while 1 while P17 0 for i 1 i 150 i 控制音響時間 P10 P10 for j 0 j 50 j 延時完成信號gou周期時間 for i 1 i 100 i 控制音響時間 P10 P10 for j 0 j 100 j 延時 完成信號周期時間 例10 14在下圖中8XX51接有五個共陰極數(shù)碼管的動態(tài)顯示接口電路 開關(guān)打向位置 1 時 顯示 12345 字樣 當開關(guān)打向 2 時 顯示 HELLO 字樣 C語言編程程序清單如下 圖10 7接五個共陰極數(shù)碼管的動態(tài)顯示接口 用C語言完成上述功能編程 include defineuintunsignedint deefineucharunsignedcharsbitP17 P1 7 main ucharcodetab1 5 0 x86 0 xdb 0 xcf 0 xe6 0 xed 1 5 的字形碼 因P1 7接的開關(guān) 最高位送的 1 ucharcodetab2 5 0 xf8 0 xf9 0 xb8 0 xb8 0 x bf HELLO 的段碼 1 uchari unitj while 1 p3 0 x011for i 0 i if p17 1 P1 tab1 i elseP1 tab2 i P3 1 for j 0 j 25000 j 例10 15以P1 0 P1 3作輸出線 以P1 4 P1 7作輸入線 如圖4 6所示 C語言編程程序清單如下 include defineucharunsignedchar defineuintunsignedintvoiddlms void ucharkbscan void 函數(shù)說明 voidmain void0 ucharkey while 1 key kbscan 鍵盤掃描函數(shù) 返回鍵碼送key保存 dlms voiddlms void 延時 uchari for i 200 i 0 i 圖10 84 4矩陣鍵盤 ucharkbscan void 鍵盤掃描函數(shù) ucharsccode recode P1 0 xf0 P1 0 P1 3發(fā)全0 P1 4 P1 7輸入 if P1 無鍵按下 返回值為0 10 8 3C51中斷程序的編制 C51使用戶能編寫高效的中斷服務程序 編譯器在規(guī)定的中斷源的矢量地址中放入無條件轉(zhuǎn)移指令 使CPU響應中斷后自動地從矢量地址跳轉(zhuǎn)到中斷服務程序的實際地址 而無需用戶去安排 中斷服務程序定義為函數(shù) 函數(shù)的完整定義如下 返回值函數(shù)名 參數(shù) 模式 再入 interruptn usingm 其中必選項interruptn表示將函數(shù)聲明為中斷服務函數(shù) n為中斷源編號 可以是0 31間的整數(shù) 不允許是帶運算符的表達式 n通常取以下值 0外部中斷0 1定時器 計數(shù)器0溢出中斷 2外部中斷1 3定時器 計數(shù)器1溢出中斷 4串行口發(fā)送與接收中斷5定時器 計數(shù)器2中斷 各可選項的意義如下 usingm定義函數(shù)使用的工作寄存器組 m的取值范圍為0 3 可缺省 它對目標代碼的影響是 函數(shù)入口處將當前寄存器保存 使用m指定的寄存器組 函數(shù)退出時原寄存器組恢復 選不同的工作寄存器組 可方便實現(xiàn)寄存器組的現(xiàn)場保護 再入 屬性關(guān)鍵字reentrant將函數(shù)定義為再入的 在C51中 普通函數(shù) 非再入的 不能遞歸調(diào)用 只有再入函數(shù)才可被遞歸調(diào)用 中斷服務函數(shù)不允許用于外部函數(shù) 它對目標代碼影響如下 當調(diào)用函數(shù)時 SFR中的ACC B DPH DPL和PSW當需要時入棧 如果不使用寄存器組切換 中斷函數(shù)所需的所有工作寄存器Rn都入棧 函數(shù)退出前 所有工作寄存器都出棧 函數(shù)由 RETI 指令終止 下面示例說明C語言的編程方法 例10 15對10 2 3的例10 4 見圖 要求每中斷一次 發(fā)光二極管顯示開關(guān)狀態(tài)用C語言編程 include int0 interrupt0 INT0中斷函數(shù) P1 0 x0f 輸入端先置1 燈滅 P 4 讀入開關(guān)狀態(tài) 并左移四位 使開關(guān)反映在發(fā)光二極管上 main EA 1 開中斷總開關(guān) EX0 1 允許INT0中斷 IT0 1 下降沿產(chǎn)生中斷 while 1 等待中斷 例10 16記錄并顯示中斷次數(shù)用C語言編程 可有兩種編程方法 法1 在主程序中判斷中斷次數(shù) 程序如下 include chari codechartab 16 0 x3f 0 x06 0 x5b 0 x4F 0 x66 0 x6d 0 x7d 0 x07 0 x7f 0 x6f 0 x77 0 x7c 0 x39 0 x5e 0 x79 0 x71 int interrupt2 i 計中斷次數(shù) P1 tab i 查表 次數(shù)送顯示 main EA 1 EX1 1 IT1 1 ap5 P1 0 x3f 顯示 0 for i 0 i 16 當i小于16等待中斷 gotoap5 當i 16重復下一輪16次中斷 法2 在中斷程序中判斷中斷次數(shù) include chari codechartab 16 0 x3f 0 x06 0 x5b 0 x4F 0 x66 0 x6d 0 x7d 0 x07 0 x7f 0 x6f 0 x77 0 x7c 0 x39 0 x5e 0 x79 0 x71 int interrupt1 i if i 16 P1 tab i else i 0 P1 0 x3f main EA 1 EX1 1 IT1 1 P1 0 x3f while 1 等待中斷 10 8 4定時 計數(shù)器的C語言編程 例10 17在P1 7端接一個發(fā)光二極管LED 要求利用定時控制使LED亮一秒滅一秒周而復始 設fosc 6MHz 分析T0定時100ms初值 100 103 2 50000 即初值為 50000 T1計數(shù)5個脈沖工作于方式2 計數(shù)初值為 5 T0和T1均采用中斷方式 程序如下 include reg51 h sbitP1 0 P1 0 sbitP1 7 P1 7 timer0 interrupt1using1 T0中斷服務程序 P1 0 P1 0 100ms到P1 0反相 TH0 50000 256 重載計數(shù)初值 TL0 50000 256 timerl interrupt3using2 T1中斷服務程序 P1 7 P1 7 1s到 燈改變狀態(tài) main P1 7 0 置燈初始滅 P1 0 1 保證第一次反相便開始計數(shù) TMOD 0 x61 T0方式1定時 T1方式2計數(shù) TH0 50000 256 預置計數(shù)初值 TL0 50000 256 TH1 5 TL1 5 IP 0 x08 置優(yōu)先級寄存器 EA 1 ET0 1 ET1 1 開中斷 TR0 1 TR1 1 啟動定時 計數(shù)器 for 等待中斷 例10 18在內(nèi)部數(shù)據(jù)存貯器20H 3FH單元中共有32個數(shù)據(jù) 要求采用方式1串行發(fā)送出去 傳送速率為1200波特 設fosc 12MHZ 方法 T1工作于方式2作波特率發(fā)生器 取SMOD 0 T1的時間常數(shù)計算如下 波特率 2SMOD 32 fosc 12 256 x 1200 1 32 12 106 12 256 x x 230 E6H 1 查詢方式編程C語的編程 發(fā)送程序 include main unsingnedchari char p TMOD 0 x20 TH1 0 xe6 TL1 0 xe6 TR1 1 SCON 0 x40 p 0 x20 for i 0 i 32 i SBUF p p while TI TI 0 接收程序 include main unsingnedchari char p TMOD 0 x20 TH1 0 xe6 TL1 0 xe6 TR1 1 SCON 0 x50 p 0 x20 for i 0 i 32 i while RI RI 0 p SBUF p 10 8 6外擴并行I O口的C語言編程 例10 19用8155作6位共陰極LED顯示器接口 PB口經(jīng)驅(qū)動器7407接LED的段選 PA0 PA5位反相驅(qū)動器7406接位選 待顯示字符依次存于dis buf數(shù)組 從右向左順序顯示 8155命令字03 table為段碼表 動態(tài)顯示6個字符 8155和8XX51的接口見圖10 12 圖10 128155和8XX51單片機的接口電路 各口的地址 A口 7FF1H B口 7FF2HC口 7FF3H命令 狀態(tài)口 7FF0HC語言程序如下 include include defineucharunsignedchar defineCOM8155XBYTE 0 x7ff0 definePA8155XBYTE 0 x7ff1 definePB8155XBYTE 0 x7ff2 definePC8155XBYTE 0 x7ff3 ucharidatadis 6 2 4 6 8 10 12 存放顯示字符2 4 6 8 A C ucharcodetable 18 0 x3f 0 x06 0 x5b 0 x4f 0 x66 0 x6d 0 x7d 0 x07 0 x7f 0 x6f 0 x77 0 x7c 0 x39 0 x5e 0 x79 0 x71 0 x40 0 x00 voiddisplay ucharidata p ucharsel i j COM8155 0 x03 scl 0 x01 送命令字 選最右邊的LED for i 0 i 6 i PB8155 table p PA8155 sel 送段碼和位碼 for j 400 j 0 j 延時 p 地址指針下移位 sel sel 1 左移一位 main display dis 5 10 8 7D A的C語言編程 單級緩沖工作方式下的DAC0832與51系列單片機的接口地址為7FFFH 要求輸出端得到鋸齒波電壓信號用C語言編程 程序如下 include include defineda0832XBYTE 0X7fff main unsignedchari j while 1 for i 0 i 255 i da0832 i 啟動轉(zhuǎn)換 for j 0 j 255 j 延時 圖10 4鋸齒波電壓信號 10 9匯編語言和C語言的混合編程 本節(jié)介紹不同的模塊 不同的語言相結(jié)合的編程方法 通常情況下以高級語言編寫主程序 用匯編語言編與硬件有關(guān)的子程序 高級語言不同的編譯程序?qū)R編的調(diào)用方法不同 在KEILC51中 是將不同的模塊 包括不同語言的模塊 分別匯編或編譯 再通過連接生成一個可執(zhí)行文件 C語言程序調(diào)用匯編語言程序要注意以下幾點 1 被調(diào)函數(shù)要在主函數(shù)中說明 在匯編程序中 要使用偽指令使CODE選項有效并聲明為可再定位段類型 并且根據(jù)不同情況對函數(shù)名作轉(zhuǎn)換 見表10 6 表10 6函數(shù)名的轉(zhuǎn)換 2 對為其他模塊使用的符號進行PUBLIC聲明 對外來符號進行EXTRN聲明 3 要注意參數(shù)的正確傳遞 10 9 1C語言程序和匯編語言程序參數(shù)的傳遞 在混合語言編程中 關(guān)鍵是入口參數(shù)和出口參數(shù)的傳遞 KEILC51編譯器可使用寄存器傳遞參數(shù) 也可以使用固定存貯器或使用堆棧 由于8XX51的堆棧深度有限 因此多用寄存器或存貯器傳遞 用寄存器傳遞最多只能傳遞三個參數(shù) 選擇固定的寄存器 見表10 7 表10 7參數(shù)傳遞的寄存器選擇 例如funcl inta a 是第一個參數(shù) 在R6 R7傳遞 func2 intb intc int d b 在R6 R7中傳遞 c 在R4 R5中傳遞 指針變量 d 在R1 R2 R3中傳遞 如果傳遞參數(shù)寄存器不夠用 可以使用存貯器傳送 通過指針取得參數(shù) 匯編語言通過寄存器或存貯器傳遞參數(shù)給C語言程序 匯編語言通過寄存器傳遞給C語言的返回值見表10 8 表10 8匯編語言通過寄存器傳遞給C語言的返回值 下面通過實例說明混合編程的方法及參數(shù)傳遞過程 10 9 2C語言程序調(diào)用匯編語言程序舉例 例1 用P1 0產(chǎn)生周期為4ms的方波 同時用P1 1產(chǎn)生周期為8ms的方波 說明 用C語言編寫主程序 使P1 1產(chǎn)生周期為8ms的方波為模塊一 P1 0產(chǎn)生周期為4ms的方波為模塊二 用匯編語言編寫的延時1ms程序為模塊三 模塊一調(diào)用模塊二獲得8ms方波 模塊二調(diào)模塊三時向匯編程序傳遞了字符型參數(shù) x 2 延時2ms 程序如下 C語言程序模塊一 include defineucharunsignedchar sbitP1 1 P1 1 voiddelay4ms void 定義延時4ms函數(shù) 模塊二 main uchari for P1 1 0 delay4ms 調(diào)模塊二延時4ms P1 1 1 delay4ms 調(diào)模塊二延時4ms 模塊二 include defineucharunsignedchar sbitP1 0 P1 0 delaylms ucharx 定義延時1ms函數(shù) 模塊三 voiddelay4ms void P1 0 0 delaylms 2 調(diào)匯編函數(shù) 模塊三 P1 0 1 delaylms 2 調(diào)匯編函數(shù) 模塊三 模塊三 PUBLIC DELAY1MS DELAY1MS為其他模塊調(diào)用 DESEGMENTCODE 定義DE段為再定位程序段 RSEGDE 選擇DE為當前段 DELAY1MS NOP DELA MOVR1 0F8H 延時 LOP1 NOPNOPDJNZR1 LOP1 DJNZR7 DELA R7為C程序傳遞過來的參數(shù) EXIT RET END 上例可見匯編語言程序從R7中獲取參數(shù) x 2 模塊編譯連接方法以上各模塊可以先分別匯編或編譯 選擇DEBUG編譯控制項 生成各自的 OBJ文件 然后運行L51將各OBJ文件連接 生成一個新的文件 在集成環(huán)境下的連接調(diào)試可以連續(xù)進行 比上面方法更為方便 現(xiàn)使用wave 偉福 的仿真軟件的編譯連接步驟如下 1 編輯好各個模塊 保存 2 點擊文件 新建項目 彈出項目窗口 3 點擊項目菜單 選加入模塊 此時彈出有文件目錄的對話框 選中要加入剛才編輯好的文件 模塊 并打開 此時在項目窗口中可以看到加入的模塊文件 4 點擊項目菜單中的全部編輯 并取名保存項目 于是系統(tǒng)對加入各模塊進行編譯 并進行連接 5 編譯連接完成會彈出信息窗口 如編譯連接有錯 信息窗口將出現(xiàn)錯誤信息 6 模塊連接成功 生成二進制文件 BIN 和十六進制文件 HEX 7 點擊跟蹤或單步按鈕 就可對程序進行跟蹤調(diào)試 程序運行到不同模塊時 wave就會彈出相應的模塊源程序窗口 顯示程序運行情況 例2 在匯編程序中比較兩數(shù)大小 將大數(shù)放到指定的存儲區(qū) 由C程序的主調(diào)函數(shù)取出模塊一 C語言程序 defineucharunsignedchar voidmax uchara ucharb 定義匯編函數(shù) main uchara 5 b 35 c d c 0 x30 c指針變量指向內(nèi)部RAM30H單元 max a b 調(diào)匯編函數(shù) a b為傳遞的參數(shù) d c d存放模塊二傳遞過來的參數(shù) 模塊二 匯編語言程序PUBLIC MAXMAX為其他模塊調(diào) DESEGMENTCODE 定義DE段為再定位程序段 RSEGDE 選擇DE為當前段 MAX MOVA R7 取模塊一的參數(shù)a MOV30H R5 取模塊一的參數(shù)b CJNEA 30H TAG1 比較a b的大小 TAG1 JCEXIT MOV30H R7 大數(shù)存于30H單元 EXIT RET END 此例中 C語言程序通過R7和R5傳遞字符型參數(shù)a和b到匯編語言程序 匯編語言程序?qū)⒎祷刂捣旁诠潭ù尜A單元 主調(diào)函數(shù)通過指針取出返回值 10 9 3C和匯編混合編程傳遞的參數(shù)多于三個的編程方法 C語言程序調(diào)用匯編程序最多只能傳遞三個參數(shù) 如果多于三個參數(shù) 就需要通過存貯區(qū)傳遞 可以通過數(shù)組 也可以在匯編程序中建立數(shù)據(jù)段 下面例中C語言程序向匯編傳遞的參數(shù)多于三個的編程方法例3A D采用查詢方式采樣50個數(shù)據(jù) A D地址為7FF8H 將其求平均并送數(shù)碼管顯示 分析8位A D最大值255 用三個數(shù)碼管顯示 以P3 4為查詢位 電路設計如圖 以匯編編A D轉(zhuǎn)換程序 采集50個數(shù)據(jù) 以C編求平均值 變十進制顯示 程序如下 圖例3電路 include defineuintunsignedint defineucharunsignedcharexternvoidcallasm uchar 定義外部匯編函數(shù) externvoiddayl uint 定義外部匯編函數(shù)dayl voidmain void uinti j m total 0 ucharidatabuf 50 dis 3 ucharcodetab 16 0 x3f 0 x06 0 x5b 0 x4f 0 x66 0 x6d 0 x7d 0 x07 0 x7f 0 x6f 0 x77 0 x7c 0 x39 0 x5e 0 x79 0 x71 段碼表 P1 0 xf8 while 1 total 1 callasm buf 調(diào)匯編函數(shù) 傳遞參數(shù)為數(shù)組首址 for i 50 i 0 i 匯編函數(shù)執(zhí)行完后返回于此 total buf i 1 50個數(shù)累加 total total 50 求平均 dis 0 total 10 求個位 并存入顯示緩沖區(qū) total total 10 dis 1 total 10 求十位 并存入顯示緩沖區(qū) dis 2 total 10 求百位 并存入顯示緩沖區(qū) P3 0 x01 P3口位選 for m 0 m 50 m for i 0 i 3 i 顯示 P1 tab dis i dayl 50 調(diào)匯編函數(shù)DAYL 延時 P3 1 匯編語言程序CALLASM ASM 完成50個數(shù)據(jù)采集并存于BUF為首址的單元 PUBLIC CALLASM 公共符號定義DFFESEGMENTCODE DFFE定為可再定位段RSEGDFFE DFFE為當前段 CALLASM PUSH07HPUSH00H 保護變量 因在下述程序中要用R7和R0MOVA R7 取BUF地址MOVR0 A R0指示存放地址MOVR7 50MOVDPTR 7FF8H DPTR指向A D地址AGA MOVA 0 MOVX DPTR A 啟動轉(zhuǎn)換JBP3 4 等待轉(zhuǎn)換結(jié)束MOVXA DPTR 讀轉(zhuǎn)換數(shù)據(jù)MOV R0 A 存入BUF數(shù)組INCR0DJNZR7 AGAPOP00HPOP07H 恢復BUF地址RETEND 匯編語言程序DAYL ASM 延時PUBLIC DAYL 公共符號定義DTESEGMENTCODE 定義DTE段為再定位程序段 RSEGDTE 選擇DTE為當前段 DAYL NOP DELA MOVR1 0F8H 延時 LOP1 NOPNOPDJNZR1 LOP1 DJNZR7 DELA R7為C程序傳遞過來的參數(shù) EXIT RET END 10 10C語言函數(shù)庫的管理與使用 C語言作為一種高級編程語言 其主要的優(yōu)勢之一就是有大量的豐富的庫函數(shù)可直接使用 而庫函數(shù)的使用是解決程序共享和提高編程效率的最有效的途徑之一 函數(shù)庫是具有目標代碼形式的函數(shù)的集合 雖然在許多方面 庫就像一個獨立編譯的模塊 但它有一個不同于目標文件的特別之處 當某個獨立編譯的目標文件與其它文件連接時 所有該目標文件中的函數(shù) 無論它們是否真正被程序所用 都成為可執(zhí)行的一部分 而當一個庫文件與其它文件連接時 可執(zhí)行程序中只包含那些真正由程序所用的庫函數(shù) 例如 C51標準庫中包含很多函數(shù) 而你的程序只包含真正由你的程序所調(diào)用的函數(shù) 10 10 1庫函數(shù)的編寫庫函數(shù)的編寫同普通的函數(shù)編寫的方法一樣 需要主要的幾點是 庫函數(shù)命名時 不能用主函數(shù)名或C51已有的庫函數(shù)名 需要改寫C51提供的函數(shù)庫例外 在采用RTOS時 多要求系統(tǒng)調(diào)用的函數(shù)為可重入函數(shù) 因此若要編寫可重入的函數(shù) 則需按照可重入函數(shù)的編寫規(guī)則編寫即可 C51的函數(shù)庫是分存儲模式的 因此 在編寫庫函數(shù)是一定要注意區(qū)分C51的存儲模式 不同模式下編譯出來的庫函數(shù)一般是不能混用的 某些特殊的庫函數(shù)程序可以采用匯編編寫 而在C51中調(diào)用即可 編輯好庫函數(shù)對應的頭文件 以便用戶引用 保存好庫函數(shù)的源程序代碼 以供維護升級時使用 一個簡單的加法例子如下所示 includeintadd inta intb ints s a b return s 10 10 2函數(shù)庫的管理 未經(jīng)特殊說明 我們這里的主要討論是針對小存儲模式的情形 在談函數(shù)庫管理前 先要獲得在小模式下編譯通過的二進制代碼 常用的函數(shù)庫管理命令有創(chuàng)建庫文件 在庫文件中添加模塊 刪除模塊和替換模塊等 下面分別介紹之 C51庫管理的執(zhí)行程序為lib51 exe 位于其安裝路徑下bin子目錄中 lib51的操作有兩種 一是運行l(wèi)ib51程序 進入庫管理控制臺 鍵入help 便可顯示所有的操作控制臺命令 如下圖所示 另一種就是直接以命令行方式一次實現(xiàn) 這種方式使用靈活 既可以做成批處理一次自動完成一批庫管理的操作 又可以與功能強大的文- 1.請仔細閱讀文檔,確保文檔完整性,對于不預覽、不比對內(nèi)容而直接下載帶來的問題本站不予受理。
- 2.下載的文檔,不會出現(xiàn)我們的網(wǎng)址水印。
- 3、該文檔所得收入(下載+內(nèi)容+預覽)歸上傳者、原創(chuàng)作者;如果您是本文檔原作者,請點此認領(lǐng)!既往收益都歸您。
下載文檔到電腦,查找使用更方便
14.9 積分
下載 |
- 配套講稿:
如PPT文件的首頁顯示word圖標,表示該PPT已包含配套word講稿。雙擊word圖標可打開word文檔。
- 特殊限制:
部分文檔作品中含有的國旗、國徽等圖片,僅作為作品整體效果示例展示,禁止商用。設計者僅對作品中獨創(chuàng)性部分享有著作權(quán)。
- 關(guān) 鍵 詞:
- 單片機 課件 語言 編程
鏈接地址:http://www.820124.com/p-6753274.html