keilC语言与汇编语言的混合编程方法.pdf

所需积分/C币:50 2013-05-05 22:14:00 6.14MB PDF
收藏 收藏
举报

keil是德国keil公司开发的单片机集成开发环境,后被ARM公司收购。在keil中c语言编辑程序直观明了,但是贴近硬件的部分也需要使用汇编语言开发。本文档讲解c语言中插入汇编代码的办法。
-E Target 1 测试用工程 创建时间:2009.8.14 E sendata c Select Device for Target'Target 1 #]STARTU.A Options for Group Source Group I' n Fila I: Rebuild target Build target Translate Fil stop build Add Files to Group Source Group 1 Targets, Groups, File Remove Group Source Group 1 and it s Files 在如上图所示的" Source Group1”上点右键,在菜单中选择“ Add Files to Group" Source Group 1 Add Files to Group Source Group 查找范围〔):|GLB 中国伴 2d c51FPS LIB *dc51mllib 2a CD51FPS LIB 2 CH51FPSLI 91 C51L LIB :51ms 1ib 9 CDS1L LIB 2 CH51LLIB 2dlc51mc lib 2c51S LIB yd CD51S LIB 2. CH51S LIB ad-51mfpc lib CD51C LIB 9 CH51CLIB 9d CS51C LIB 2d c51mfpl lib cD51FPC LTB 2 CH51FPC LIB 2 )CS51FPC LI ed c5lmfps lib *3 CD51FPL LIB 2 CH51FPL LIB CS51FPL. LT 《 文件名⑩:s.LIB Add 文件类型①):[ brary file(.1b) CL。se 找到你的KEL安装目录,选择其中的“C51”目录下的“LB目录下的C51SLB"文件,点击 Add,然后 Close即可 注意,上图所示的文件选择框进入LB目录下后,默认只显示.c文件,需要在“文件类型"中 选择" Library file(lib)”,即可显示LB文件了。 添加C51sLB到工程后,再次编译,警告信息消失。 linking… Program Size: data=9.0 xdata=0 code=28 creating hex file from " sendata" sendata"-0 Error(s), 0 Warning(s). 4、寄存器冲突问题的解决 汇编程序块中常常会使用到51的通用寄存器,比如R0R7。这种情况下可能会和C语言程 序中已经使用到的R0-R7产生冲突,以至于产生一些非常隐蔽和古怪的错误。虽然有人说 KEL可以自动分配寄存器组使之不产生冲突。但是在我这里具体测试时还是有冲突的(或 者是我的KEL设置有问题?),下面是测试小程序: /**大太大大大大方大古古大大大六大大古大大古古古大大大大古古大大古才古大大古大六古古大大 ★测试程序 ★★★大★大大★大★大★★★大★★定大★★大★宾★大大实★大★文★大★★大★★大大★大★★★实★★★大 #include<reg51h> #include<stdio. h> typedef unsigned char uint8 i uint8 buf[16]= 0x55 uint8 1-0 六六大古古六古卖内古内六古古古内大含六六六内大大内古古内★声古古古六大古六内古古六大古六内大古古六六六古 大初始化单片机相关寄存器 大★大大大大大大大★大大★大★大大★大大★大★大共★大★★大★大妆大★大大★大★大/ void Tartini( SCON=0x50 TMOD=0x21 PCON 1=0x80 7 TH1=OxE8 i TL1-OxE8 i IE|=0×90 TR1=1 ★★大六大大大大★大大大大古大古大古内大大大★大古内大大★大古大大★大内大古古★★大大大内★大古大 大延时 六六六六害六六六六内内六次内六六次六六六内六六实六六六六内六内六次古六六六内六六六六言; void delay() pragma asm MOV R6,#19 DELAY2 MOV R7#18 DELAYT DUNZ R7 DELAY1 DUNZ R6 DELAY2 RET pragma endasm ★★六古内古内★古古古★内内比内★古古六古★古古内★古古古古内大★★ 大向COM1发送一个字符 ★★灾★★实★☆★古★大★★我★责★大卖害灾★大灾古★★★宾★★★★责 void Sendchar (uint8 byteTosend) SBUE=byteTosend while(I Ti)i TI=0 读取一个字节 太★大★★★大大大★*太★★★大★★大★★★★大太★★*太★大大★★★*大★★★** uint8 read byte( uint8 recvdata-8 i delay()i /延时 return recvdata i 六★实大实大★★★★大★★食★大★★实六★大★次实★★大★文★六★★★大责★★大 主程序 ★★★大实灾★大★★★灾★大大★★大大★★★★★★★★大灾★★★★★实★大★★★★★★实★★ int main( { Uartinit();//串口初始化 while(1) buf[i++]=read byte ( /大*六六次大次大六六六光次六六六内六六六六六次次内六六内六六为 串口中断处理 肯古古古大古古古古内内大古古古古内古内内古六古古古古大古内古大古实古大内古古古大古古 void chuankou(interrupt 4 for:i=0;i<sizeof (buf)i++) Sendchar (buil)i RI=O 程序本身非常简单,一目了然。main函数的作用就是不断把 read_ byte()的返回值读入 buf中,再待有串口中断时,将buf中的内容输出到串口。 read byte()函数也已经做了 简化,返回值固定为8。 将这个程序在K工L中编译,下载运行。奇怪的情况出现了,buf中的内容输出到串口总是 0(输出理所当然应该是8)。 把 delay();这一句注释掉后,程序就输出正常了。 delay();不过起到了一个延时作用而已,怎么可能改变到函数返回值呢? 看看 read_byte()函数生成的汇编程序 USING MOV R7,#08H ACALL delay RE 才晓得,原来 read byte()函数将返回值放到R7中,然后调用de1ay函数,再返回。后 面的程序调用 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函数的内容可以改成如下这样 void delay ( pragma asm USING 2 MOV AR6,#19 DELAY2 MOV AR7#18 DELAYI DUNZ AR, DELAY1 DNZ AR6, DELAY2 RET #pragma endasm 但是注意,如果这样用的话, delay延时的长度可能需要重新计算。因为AR6和R6有所不 同,以下是在网上找到的两段英文描述 Ro- R7 The eight 8 bit general purpose 805 1 registers in the currently active register ba A Maximum of four register banks are available ARO- AR7 Represent the absolute data addresses of Ro through R7 in the current regist er bank The absolute address for these registers changes depending on the register bank that is currently selected. These symbols are only available when the USING assembler statement is given Refer to the USING assembler statement for more information on selecting the register b ank These representations are suppressed by the noaregs directive off the Cx51 compiler 看这意思,似乎R0一R7是寄存器,而AR0-AR7是地址,所以" MOV AR6,#19〃和"oV R6,#19″所花的时钟周期数是不同的。我调一个采集数据的程序时,刚开始没有注意到这 个问题,因此很奇怪为什么用AR6和R6,采集到的数据是不一样的,后来才反应过来它们 延时个同。(关于51单片机的各条指令的时钟周期数可以在白度上搜到很多,这里就个列 出了) (3)对汇编部分中使用到的寄存器采用入栈保护 简单的说就是在汇编部分使用Rn之前,将它们的内容塞进栈中存起来,延时循环结束之后 再从栈中取出来重新赋给它们。 比如上面的 delay程序,可以改成这样 void delay( #pragma asm IOV AR6 PUSH ACC MOV ART PUSH ACC MVR6,#19 DELAY2: MOV R7,#18 DELAYl: DJNZ R7 DELAY1 DUNZ R6 DELAY2 POP ACC MOV,A POP ACC RET pragma endasm (4)使用RS0和RS1切换使用的寄存器组 51单片机中使用Rs0和RS1来选择使用哪一组Rη,因此在汇编程序通过修改这两位的值, 即可实现切换寄存器组。 上面的 delay函数可修改为如下形式 void delay( pragma asm SETB RSI SETB RSO MOV R6,#19 DELAY2: MOV R7,#18 DELAYI: DUNZ R, DELAY1 DUNZ R6 DELAY2 CLR RSI CLR RSO RET #pragma endasm 进入汇编部分后选择采用第3组寄存器,退出江编部分前更换回之前使用的第ⅹ组寄存器 (在本程序中是第0组寄存器) 不过对于比较精细的延时的话,方法(3)和方法(4)这样或许会稍有些影响,毕竞增加 了一些入栈出栈或者置位清零的语句。因此如果对延时精度要求较高,且采用方法(3)或 (4)的话,讣算延时的循环次数时,需要把入栈出栈或置位清零语句花费的时间也考虑进 去 Keil中C与汇编混合编程的方法 2008年04月11日星期五15:45 如何在 KEIL C51(v6.21)中调用汇编函数的一个示例[ ycong kuang 有关c51调用汇编的方法已经有很多帖子讲到,但是一般只讲要点,很少有对整 个过程作详细描述,对于初学者是不够的,这里笔者 通过一个简单例子对这个过程进行描述,希望能对初学者有所帮助。几年来,在 这个论坛里笔者得到很多热心人指导,因此也希望 精此尽一点绵薄之力 在这个例子里,阐述了编写c51程序调用汇编函数的一种方法,这个外部函数的 入口参数是一个字符型变量和一个位变量,返回值是 一个整型变量。例中,先用c5l写出这个函数的主体,然后用SRC控制指令编译 生asm文件,进一步修改这个asm文件就得到我们所 要的汇编函数。该方法让编译器自动完成各种段的安排,提高了汇编程序的编写 效率。 stepl.按写普通c51程序方法,建立工程,在里面导入main.c文件和 CFUNO.c 文件。 相关文件如下: //main.c文件 *include regalh #define uchar unsigned cha #define uint unsigned int extern uint AFUNC (uchar v achr, bit v flag) void maino bit blag Ichar mav chr, uint mvintrslt may chr=0xd4: BFLag=1 mvintrsl t=AFUNC(mav chr, BFLAG / CFUNO.C文件 #define uchar unsigned char # define uint unsigned int uint AFUNC (uchar v achr, bit v flag) uchar tmp vcr uint tp vint, tmp schr=v achr tp vint=uint)v flag return tmp schr+(tp vint<<8) step2.在 Project窗口中包含汇编代码的C文件上右键,选择“ Options for...”,点击右边的“ Generate Assembler SRC File”和“ Assemble src file”,使检查框由灰色变成黑色(有效) 状态 steυ3.根捃选择的编译模式,把相应的库文件(如Sall模式时,是 Keil{C5I\ibC5IS.Lib)加入工程中,该文件必须作为工 程的最后文件; step4. build这个工程后将会产生一个 CFUNO.SRC的文件,将这个文件改名为 CFUNC.A51(也可以通过编译选项直接产生 CFUNO.A51文 件),然后在工程里去掉库文件(如C51S.Lib)和 CFUNO.c,而将 CFUNC.A51添加到工程里。 / CFUNC.SRC文件如下 \CFUNC SRC generated from: CFUNCC NAME CFUNC OPR? AFUNCOCFUNC SEGMENT CODE ?BI? AFUNC?CFUNC SEGMENT BIT OVERLAYABLE PUBLIC 2 AFUNC?BIT PUBLIC AFUNC RSEG BI? AFUNC?CFUNC 2 AFUNC?BIT v bilag?041 DBIT I #define uchar unsigned char #define uint unsigned int uint AFUNC (uchar v achr, bit y bilag RSEG ?PR? AFUNCOCFUNC AFUNC

...展开详情
试读 22P keilC语言与汇编语言的混合编程方法.pdf
立即下载 低至0.43元/次 身份认证VIP会员低至7折
    一个资源只可评论一次,评论内容不能少于5个字
    lyk07351 方法不错,可用且详细! 我根据上面的说法,用汇编做了精确延时
    2015-06-27
    回复
    u011031883 还行吧!谢谢!通学易懂
    2013-12-29
    回复
    j765937360 资源可以参考,易懂
    2013-07-14
    回复
    rj173173 资源可以参考,易懂!
    2013-06-24
    回复
    关注 私信 TA的资源
    上传资源赚积分,得勋章
    最新推荐
    keilC语言与汇编语言的混合编程方法.pdf 50积分/C币 立即下载
    1/22
    keilC语言与汇编语言的混合编程方法.pdf第1页
    keilC语言与汇编语言的混合编程方法.pdf第2页
    keilC语言与汇编语言的混合编程方法.pdf第3页
    keilC语言与汇编语言的混合编程方法.pdf第4页
    keilC语言与汇编语言的混合编程方法.pdf第5页
    keilC语言与汇编语言的混合编程方法.pdf第6页
    keilC语言与汇编语言的混合编程方法.pdf第7页

    试读已结束,剩余15页未读...

    50积分/C币 立即下载 >