51汇编&C51相互调用
**
前言
**
单单是用汇编还是C都太无聊了,让我们进入混合编程的世界吧!
在C51中嵌入51汇编代码
第一个任务是想随便在C里嵌入一个延时准确的函数,自然需要用汇编啦。
(暂时还不传参数进汇编)
#include<reg52.h>
typedef unsigned int u16;
typedef unsigned char u8;
void delay(u16 i){
#pragma asm
mov r7,#20
DL1:
mov r6,#20
DL0:
mov r5,#200
djnz r5,$
djnz r6,DL0
djnz r7,DL1
#pragma endasm
}
void main(){
P2=0xff;
while(1){
P2=~P2;
delay(500);
}
}
用Keil编程的时候别忘记需要为需要嵌入汇编的C文件设置SRC编译控制命令。这个命令能把C文件编译成汇编文件。
在需要嵌入汇编的C文件处右击,找到Options for File ‘xxx.c’,把两个勾点黑。
然后还需要引入一个静态库文件,在Keil的安装目录里,找到Keil\C51\C51S.LIB。把这个文件加入你的Source Group.
C51S.LIB - 没有浮点运算的 Small model
C51C.LIB - 没有浮点运算的 Compact model
C51L.LIB - 没有浮点运算的 Large model
C51FPS.LIB - 带浮点运算的 Small model
C51FPC.LIB - 带浮点运算的 Compact model
C51FPL.LIB - 带浮点运算的 Large model
运行效果:
现在终于嵌入了汇编了。可以通过打断点,调试,好设置准确的延时时间了。
混合编程的目的已经实现了。
但是这仅仅是开始。
如何向嵌入的汇编程序中传递参数?
提到C51对51汇编的参数传递就不能不提C51之间参数的传递。在之前用C51led点阵做Point_Game那片文章里,我只用了函数返回值来传递。实际上,用函数传递是指只能用返回值的方式,引用和指针都不能用。
Point_Game那个我是跨文件的参数传递,所以只能使用返回值。
C51底层保存操作变量都是在寄存器上或固定存储区上操作的。所以只要是那些变量,那些操作涉及了这些寄存器,那么我在汇编部分就能直接使用。
比如,把上面那个示例中的第八行和第十行删除,把delay()的参数改为一个16进制数(0x1010)程序照样运行。
这是因为参数是unsigned int ,而C51把这个类型的数据放在R6,R7两个寄存器里,所以可以使用——如果不是传递参数进去,那么R6R7就不会得到正确赋值。
最多只能有3个参数传递过去。
在C51中调用51汇编函数
建两个文件MAIN.c func.c
//MAIN.c
#include"reg52.h"
extern char func(char _a);
extern void delay(unsigned int _a);
void main_call(){
char c = 0xfe;
while(1){
c = func(c);
delay(0x0707);
}
}
void main(){
main_call();
}
//func.c
#ifndef _MAIN_1_C_
#define _MAIN_1_C_
#include"reg52.h"
char func(char _a){
P2 = _a;
_a <<=1 ;
_a |= 0x01;
return _a;
}
void delay(unsigned int _a){
#pragma asm
DL1:
DL0:
mov r5,#200
djnz r5,$
djnz r6,DL0
djnz r7,DL1
#pragma endasm
}
#endif
对第二个文件func.c把SRC编译命令的勾打上,每次更改这个文件都要有这个操作。
编译一下后,把得到的func.SRC文件改成func.asm,
并加入Source Group。
再把func.c给移除掉。
编译后得到hex写入单片机。
这样你就得到了汇编的函数调用示例。但是,真像是脱裤子放屁!
在51汇编中调用C51函数
这一部分等到51汇编学到更深入的时候再说
参考:KeilC51中 C51程序与汇编程序的接口方法——张玉峰,荀建军
https://blog.****.net/u012363005/article/details/51814126