版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、在keil C語言與匯編語言的混合編程中曾經(jīng)遇到過的一些問題,寫下來留作以后參考。(本文寫于09.08.15,在8.18日加入了第4點(diǎn)的內(nèi)容)1、C語言中加入?yún)R編語言模塊的方法:例子:void func() C語言代碼#pragma asm MOV R6,#23DELAY2: MOV R7,#191DELAY1: DJNZ R7,DELAY1DJNZ R6,DELAY2RET#pragma endasm C語言代碼 其中紅色為C語言部分,綠色為嵌入的匯編語言部分。匯編部分需要用#pragma asm和#pragma endasm包起來2、Keil提示“asm/endasm”出錯(cuò)的解決方法如果只
2、是像1中那樣直接加入?yún)R編代碼的話,編譯將會報(bào)錯(cuò),錯(cuò)誤如下:compiling sendata.c.sendata.c(81): error C272: asm/endasm requires src-control to be activesendata.c(87): error C272: asm/endasm requires src-control to be activeTarget not created解決方法如下:首先左鍵單擊包含有匯編部分的c語言文件名,然后在菜單欄中選擇Project-Option for File中選擇帶有紅色方框的選項(xiàng)在彈出的對話框中,將上圖中紅色方框選中
3、的兩項(xiàng)打上勾(默認(rèn)的情況下,前面的勾是灰色的,要讓這兩項(xiàng)前的勾變?yōu)楹谏模c(diǎn)擊確定。3、?C_START等相關(guān)警告的處理按照2中的方法處理完之后,再編譯不會出現(xiàn)錯(cuò)誤信息了,但是會出現(xiàn)如下的警告信息:linking.* WARNING L1: UNRESOLVED EXTERNAL SYMBOLSYMBOL: ?C_STARTMODULE: STARTUP.obj (?C_STARTUP)* WARNING L2: REFERENCE MADE TO UNRESOLVED EXTERNALSYMBOL: ?C_STARTMODULE: STARTUP.obj (?C_STARTUP)ADDRE
4、SS: 000DH處理方法如下:在如上圖所示的“Source Group 1”上點(diǎn)右鍵,在菜單中選擇 “Add Files to Group Source Group 1 ”找到你的KEIL安裝目錄,選擇其中的“C51”目錄下的“LIB”目錄下的“C51S.LIB”文件,點(diǎn)擊Add,然后Close即可。注意,上圖所示的文件選擇框進(jìn)入LIB目錄下后,默認(rèn)只顯示.c文件,需要在“文件類型”中選擇“Library file (*.lib)”,即可顯示LIB文件了。添加C51S.LIB到工程后,再次編譯,警告信息消失。linking.Program Size: data=9.0 xdata=0 cod
5、e=28creating hex file from sendata.sendata - 0 Error(s), 0 Warning(s).4、寄存器沖突問題的解決匯編程序塊中常常會使用到51的通用寄存器,比如R0-R7。這種情況下可能會和C語言程序中已經(jīng)使用到的R0-R7產(chǎn)生沖突,以至于產(chǎn)生一些非常隱蔽和古怪的錯(cuò)誤。雖然有人說KEIL可以自動分配寄存器組使之不產(chǎn)生沖突。但是在我這里具體測試時(shí)還是有沖突的(或者是我的KEIL設(shè)置有問題?),下面是測試小程序:/*測試程序*/#include#includetypedefunsignedcharuint8;uint8buf16=0 x55;uin
6、t8i=0;/*初始化單片機(jī)相關(guān)寄存器*/voidUartInit()SCON=0 x50;TMOD|=0 x21;PCON|=0 x80;TH1=0 xE8;TL1=0 xE8;IE|=0 x90;TR1=1;/*延時(shí)*/voiddelay()#pragmaasmMOVR6,#19DELAY2: MOVR7,#18DELAY1: DJNZR7,DELAY1DJNZR6,DELAY2RET#pragmaendasm/*向COM1發(fā)送一個(gè)字符*/voidSendChar(uint8byteToSend)SBUF=byteToSend;while(!TI);TI=0;/*讀取一個(gè)字節(jié)*/uint8
7、read_byte()uint8recvdata=8;delay();/延時(shí)returnrecvdata;/*主程序*/intmain()UartInit();/串口初始化while(1)bufi+=read_byte();/*串口中斷處理*/voidchuankou()interrupt4if(RI)for(i=0;isizeof(buf);i+)SendChar(bufi);RI=0;程序本身非常簡單,一目了然。main函數(shù)的作用就是不斷把read_byte()的返回值讀入buf中,再待有串口中斷時(shí),將buf中的內(nèi)容輸出到串口。read_byte()函數(shù)也已經(jīng)做了簡化,返回值固定為8。將這
8、個(gè)程序在KEIL中編譯,下載運(yùn)行。奇怪的情況出現(xiàn)了,buf中的內(nèi)容輸出到串口總是0(輸出理所當(dāng)然應(yīng)該是8)。把delay();這一句注釋掉后,程序就輸出正常了。delay();不過起到了一個(gè)延時(shí)作用而已,怎么可能改變到函數(shù)返回值呢?看看read_byte()函數(shù)生成的匯編程序USING 0MOV R7,#08HACALL delayRET 才曉得,原來read_byte()函數(shù)將返回值放到R7中,然后調(diào)用delay函數(shù),再返回。后面的程序調(diào)用read_byte()返回值時(shí),直接從R7中取數(shù)。但是“ACALL delay”時(shí),已經(jīng)存放了#08H的R7,在延時(shí)中被遞減到了0,這也是為什么buf中存
9、放的內(nèi)容都是0的緣故。知道了原因就好辦一些了,由于本人是菜鳥,單片機(jī)水平很有限,目前只想到了如下4種解決方法:(1)避開C語言部分已經(jīng)使用了的Rn編匯編模塊時(shí),看看C語言部分生成的匯編程序,把那些C語言已經(jīng)使用到的,且可能對匯編部分構(gòu)成沖突的Rn避開就好了。比如上面的延時(shí)程序中,把R6、R7換成R3、R4,程序就正常了。(2)用USING X + ARX的方式調(diào)用其他組Rn寄存器51單片機(jī)有4組R0-R7的寄存器,據(jù)說main中一般使用的都是第0組。那么在匯編部分中使用其他的組就可以了,delay函數(shù)的內(nèi)容可以改成如下這樣:voiddelay()#pragmaasmUSING 2MOV AR6
10、,#19DELAY2: MOV AR7,#18DELAY1: DJNZ AR7,DELAY1DJNZ AR6,DELAY2RET#pragmaendasm但是注意,如果這樣用的話,delay延時(shí)的長度可能需要重新計(jì)算。因?yàn)锳R6和R6有所不同,以下是在網(wǎng)上找到的兩段英文描述:R0R7Theeight8bitgeneralpurpose8051registersinthecurrentlyactiveregisterbank.AMaximumoffourregisterbanksareavailable. AR0AR7RepresenttheabsolutedataaddressesofR0th
11、roughR7inthecurrentregisterbank. Theabsoluteaddressfortheseregisterschangesdependingontheregisterbankthatiscurrentlyselected. ThesesymbolsareonlyavailablewhentheUSINGassemblerstatementisgiven. RefertotheUSINGassemblerstatementformoreinformationonselectingtheregisterbank. Theserepresentationsaresuppr
12、essedbytheNOAREGSdirectiveofftheCx51compiler. 看這意思,似乎R0R7是寄存器,而AR0AR7是地址,所以“MOV AR6,#19”和“MOV R6,#19”所花的時(shí)鐘周期數(shù)是不同的。我調(diào)一個(gè)采集數(shù)據(jù)的程序時(shí),剛開始沒有注意到這個(gè)問題,因此很奇怪為什么用AR6和R6,采集到的數(shù)據(jù)是不一樣的,后來才反應(yīng)過來它們延時(shí)不同。(關(guān)于51單片機(jī)的各條指令的時(shí)鐘周期數(shù)可以在百度上搜到很多,這里就不列出了)(3)對匯編部分中使用到的寄存器采用入棧保護(hù)簡單的說就是在匯編部分使用Rn之前,將它們的內(nèi)容塞進(jìn)棧中存起來,延時(shí)循環(huán)結(jié)束之后再從棧中取出來重新賦給它們。比如上面
13、的delay程序,可以改成這樣:voiddelay()#pragmaasmMOVA,R6PUSHACCMOVA,R7PUSHACCMOVR6,#19DELAY2: MOVR7,#18DELAY1: DJNZR7,DELAY1DJNZR6,DELAY2POPACCMOVR7,APOPACCMOVR6,ARET#pragmaendasm (4)使用RS0和RS1切換使用的寄存器組51單片機(jī)中使用RS0和RS1來選擇使用哪一組Rn,因此在匯編程序通過修改這兩位的值,即可實(shí)現(xiàn)切換寄存器組。上面的delay函數(shù)可修改為如下形式:voiddelay()#pragmaasmSETBRS1SETBRS0MOVR6,#19DELAY2: MOVR7,#18DELAY1: DJNZR7,DELAY1DJNZR6,DELAY2CLRRS1CLRRS0RET#pragmaendasm 進(jìn)入?yún)R編部分后選擇采用第3組寄存器,退出匯編部分前更換回之前使用的第x組寄存器(在本程序中是第0組寄存器)不過對于比較精細(xì)的延時(shí)的話,方法(3)和方法(4)這樣或許會稍有些影響,畢竟增加了一些入棧出?;蛘咧梦磺辶愕恼Z句。因此如果對延時(shí)精度要求較高,且
溫馨提示
- 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)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 交通事故和解合同范本
- 產(chǎn)品采購合同范本
- 中小企業(yè)合同法務(wù)服務(wù)發(fā)展規(guī)劃定
- 個(gè)人商用房抵押貸款合同模板
- 產(chǎn)品銷售獨(dú)家代理合同模板
- 個(gè)人向單位租車合同及條款
- 個(gè)人向個(gè)人創(chuàng)業(yè)借款合同范本
- 臨時(shí)工勞動合同范本(合同僅限勞務(wù)派遣使用)
- 個(gè)人住宅抵押借款合同簡例范本
- 兼職人員勞務(wù)合同協(xié)議
- 2025江蘇南京市金陵飯店股份限公司招聘高頻重點(diǎn)提升(共500題)附帶答案詳解
- 公共政策分析 課件匯 陳振明 第0-9章 導(dǎo)論、緒論:政策科學(xué)的“研究綱領(lǐng)”- 政策監(jiān)控
- 2025年牛津譯林版英語七年級下冊全冊單元重點(diǎn)知識點(diǎn)與語法匯編
- 《小學(xué)作文指導(dǎo)》課件
- 小學(xué)六年級數(shù)學(xué)方程應(yīng)用題100道及答案解析
- 2025新譯林版英語七年級下單詞表
- 海洋工程設(shè)備保溫保冷方案
- 文藝演出排練指導(dǎo)服務(wù)合同
- 人教版(2024新版)一年級上冊數(shù)學(xué)第一單元《數(shù)學(xué)游戲》單元整體教學(xué)設(shè)計(jì)
- 中山大學(xué)孫逸仙紀(jì)念醫(yī)院醫(yī)用耗材試用登記表【模板】
- 衛(wèi)生部關(guān)于發(fā)布《綜合醫(yī)院組織編制原則試行草案》的通知((78)衛(wèi)醫(yī)字第1689號)
評論
0/150
提交評論