




已阅读5页,还剩4页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
在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”出错的解决方法如果只是像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、?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)ADDRESS: 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 code=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;uint8i=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_byte()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。将这个程序在KEIL中编译,下载运行。奇怪的情况出现了,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的缘故。知道了原因就好办一些了,由于本人是菜鸟,单片机水平很有限,目前只想到了如下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,#19DELAY2: MOV AR7,#18DELAY1: DJNZ AR7,DELAY1DJNZ AR6,DELAY2RET#pragmaendasm但是注意,如果这样用的话,delay延时的长度可能需要重新计算。因为AR6和R6有所不同,以下是在网上找到的两段英文描述:R0R7Theeight8bitgeneralpurpose8051registersinthecurrentlyactiveregisterbank.AMaximumoffourregisterbanksareavailable. AR0AR7RepresenttheabsolutedataaddressesofR0throughR7inthecurrentregisterbank. Theabsoluteaddressfortheseregisterschangesdependingontheregisterbankthatiscurrentlyselected. ThesesymbolsareonlyavailablewhentheUSINGassemblerstatementisgiven. RefertotheUSINGassemblerstatementformoreinformationonselectingtheregisterbank. TheserepresentationsaresuppressedbytheNOAREGSdirectiveofftheCx51compiler. 看这意思,似乎R0R7是寄存器,而AR0AR7是地址,所以“MOV AR6,#19”和“MOV R6,#19”所花的时钟周期数是不同的。我调一个采集数据的程序时,刚开始没有注意到这个问题,因此很奇怪为什么用AR6和R6,采集到的数据是不一样的,后来才反应过来它们延时不同。(关于51单片机的各条指令的时钟周期数可以在百度上搜到很多,这里就不列出了)(3)对汇编部分中使用到的寄存器采用入栈保护简单的说就是在汇编部分使用Rn之前,将它们的内容塞进栈中存起来,延时循环结束之后再从栈中取出来重新赋给它们。比如上面的delay程序,可以改成这样:voiddelay()#pragmaasmMOVA,R6PUSHACCMOVA,R7PUSHACCMOVR6,#19DELAY2: MOVR7,#18DELAY1: DJNZR7,DELAY1DJNZR6,DELAY2POPACCMOVR7,APOPACCMOVR6,ARET#pragmaendasm (4)使用RS0和RS1切换使用的寄存器组51单片机中使用RS0和RS1来选择使用哪一组Rn,因此在汇编程序通过修改这两位的值,即可实现切换寄存器组。上面的delay函数可修改为如下形式:voiddelay()#pragmaasmSETBRS1SETBRS0MOVR6,#19DELAY2: MOVR7,#18DELAY1: DJNZR7,DELAY1DJNZR6,DELAY2CLRRS1CLRRS0RET#pragmaendasm 进入汇编部分后选择采用第3组寄存器,退出汇编部分前更换回之前使用的第x组寄存器(在本程序中是第0组寄存器)不过对于比较精细的延时的话,方法(3)和方法(4)这样或许会稍有些影响,毕竟增加了一些入栈出栈或者置位清零的语句。因此如果对延时精度要求较高,且
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025分布式光伏发电屋顶租赁合同
- 2025年度空调设备供应合同
- 2025存量房买卖合同附件样本
- 阴茎癌的临床护理
- 《中医诊断学题》课件
- 《公共卫生法规与传染病管理》课件
- 《深度解析医疗制度》课件
- 2025年陕西货运从业资格证模拟考试下载
- 塔里木职业技术学院《教学统计软件》2023-2024学年第二学期期末试卷
- 上海市长宁区高级中学2025届初三年级第一次质量检测试题化学试题含解析
- GB/T 4326-2006非本征半导体单晶霍尔迁移率和霍尔系数测量方法
- 酒水购销合同范本(3篇)
- GCP培训考试题库及参考答案(完整版)
- 乒乓球社团活动记录
- 新时代中小学教师职业行为十项准则考核试题及答案
- 数据结构-第6章-图课件
- 《变态心理学与健康心理学》考试复习题库150题(含答案)
- DB15T 489-2019 石油化学工业建设工程技术资料管理规范
- 皮内针讲课课件
- 村卫生室静脉输液准入申请审批表
- 提高钢柱安装垂直度合格率QC成果PPT
评论
0/150
提交评论