Keil内联汇编的设置问题

上传人:re****.1 文档编号:552646831 上传时间:2023-08-21 格式:DOC 页数:9 大小:137.52KB
返回 下载 相关 举报
Keil内联汇编的设置问题_第1页
第1页 / 共9页
Keil内联汇编的设置问题_第2页
第2页 / 共9页
Keil内联汇编的设置问题_第3页
第3页 / 共9页
Keil内联汇编的设置问题_第4页
第4页 / 共9页
Keil内联汇编的设置问题_第5页
第5页 / 共9页
点击查看更多>>
资源描述

《Keil内联汇编的设置问题》由会员分享,可在线阅读,更多相关《Keil内联汇编的设置问题(9页珍藏版)》请在金锄头文库上搜索。

1、在keil C语言与汇编语言的混合编程中曾经遇到过的一些问题,写下来留作以后参考。(本文写于09.08.15,在8.18日加入了第4点的内容)1、C语言中加入汇编语言模块的方法:例子: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”出错的解决方法如果只

2、是像1中那样直接加入汇编代码的话,编译将会报错,错误如下: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中选择带有红色方框的选项在弹出的对话框中,将上图中红色方框选中

3、的两项打上勾(默认的情况下,前面的勾是灰色的,要让这两项前的勾变为黑色的),点击确定。3、?C_START等相关警告的处理按照2中的方法处理完之后,再编译不会出现错误信息了,但是会出现如下的警告信息: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”上点右键,在菜单中选择 “Add Files to Group Source Group 1 ”找到你的KEIL安装目录,选择其中的“C51”目录下的“LIB”目录下的“C51S.LIB”文件,点击Add,然后Close即可。注意,上图所示的文件选择框进入LIB目录下后,默认只显示.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语言程序中已经使用到的R0-R7产生冲突,以至于产生一些非常隐蔽和古怪的错误。虽然有人说KEIL可以自动分配寄存器组使之不产生冲突。但是在我这里具体测试时还是有冲突的(或者是我的KEIL设置有问题?),下面是测试小程序:/*测试程序*/#include#includetypedefunsignedcharuint8;uint8buf16=0x55;uint

6、8i=0;/*初始化单片机相关寄存器*/voidUartInit()SCON=0x50;TMOD|=0x21;PCON|=0x80;TH1=0xE8;TL1=0xE8;IE|=0x90;TR1=1;/*延时*/voiddelay()#pragmaasmMOVR6,#19DELAY2: MOVR7,#18DELAY1: DJNZR7,DELAY1DJNZR6,DELAY2RET#pragmaendasm/*向COM1发送一个字符*/voidSendChar(uint8byteToSend)SBUF=byteToSend;while(!TI);TI=0;/*读取一个字节*/uint8read_by

7、te()uint8recvdata=8;delay();/延时returnrecvdata;/*主程序*/intmain()UartInit();/串口初始化while(1)bufi+=read_byte();/*串口中断处理*/voidchuankou()interrupt4if(RI)for(i=0;isizeof(buf);i+)SendChar(bufi);RI=0;程序本身非常简单,一目了然。main函数的作用就是不断把read_byte()的返回值读入buf中,再待有串口中断时,将buf中的内容输出到串口。read_byte()函数也已经做了简化,返回值固定为8。将这个程序在KEI

8、L中编译,下载运行。奇怪的情况出现了,buf中的内容输出到串口总是0(输出理所当然应该是8)。把delay();这一句注释掉后,程序就输出正常了。delay();不过起到了一个延时作用而已,怎么可能改变到函数返回值呢?看看read_byte()函数生成的汇编程序USING 0MOV R7,#08HACALL delayRET 才晓得,原来read_byte()函数将返回值放到R7中,然后调用delay函数,再返回。后面的程序调用read_byte()返回值时,直接从R7中取数。但是“ACALL delay”时,已经存放了#08H的R7,在延时中被递减到了0,这也是为什么buf中存放的内容都是0

9、的缘故。知道了原因就好办一些了,由于本人是菜鸟,单片机水平很有限,目前只想到了如下4种解决方法:(1)避开C语言部分已经使用了的Rn编汇编模块时,看看C语言部分生成的汇编程序,把那些C语言已经使用到的,且可能对汇编部分构成冲突的Rn避开就好了。比如上面的延时程序中,把R6、R7换成R3、R4,程序就正常了。(2)用USING X + ARX的方式调用其他组Rn寄存器51单片机有4组R0-R7的寄存器,据说main中一般使用的都是第0组。那么在汇编部分中使用其他的组就可以了,delay函数的内容可以改成如下这样:voiddelay()#pragmaasmUSING 2MOV AR6,#19DEL

10、AY2: MOV AR7,#18DELAY1: DJNZ AR7,DELAY1DJNZ AR6,DELAY2RET#pragmaendasm但是注意,如果这样用的话,delay延时的长度可能需要重新计算。因为AR6和R6有所不同,以下是在网上找到的两段英文描述:R0R7Theeight8bitgeneralpurpose8051registersinthecurrentlyactiveregisterbank.AMaximumoffourregisterbanksareavailable. AR0AR7RepresenttheabsolutedataaddressesofR0throughR7

11、inthecurrentregisterbank. Theabsoluteaddressfortheseregisterschangesdependingontheregisterbankthatiscurrentlyselected. ThesesymbolsareonlyavailablewhentheUSINGassemblerstatementisgiven. RefertotheUSINGassemblerstatementformoreinformationonselectingtheregisterbank. TheserepresentationsaresuppressedbytheNOAREGSdirectiveofftheCx51compiler. 看这意思,似乎R0R7是寄存器,而AR0AR7是地址,所以“MOV AR6,#19”和“MOV R6,#19”所花的时钟周期数是不同的。我调一个采集数据的程序时,刚开始没有注意到这个问题,因此很奇怪为什么用AR6和R6,采集到的数据是不一样的,后来才反应过来它们延时不同。(关于51单片机的各条指令的时钟周期数可以在百度上

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 高等教育 > 习题/试题

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号