900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > keil C语言编程 位地址定义 Keil C编写下位机程序的小技巧和注意点

keil C语言编程 位地址定义 Keil C编写下位机程序的小技巧和注意点

时间:2022-07-04 11:30:15

相关推荐

keil C语言编程 位地址定义 Keil C编写下位机程序的小技巧和注意点

1. 用C直接操作DPTR方式

我们平常用Keil C访问总线一般是定义unsigned char xdata *fardptr; fardptr=0xbf00; *fardptr=0; 来访问,这就涉及到一个问题:首先增加一个占两个字节的变量,其次是每次系统多了一个赋值给这个变量,不论你是否要用这个用量。用汇编操作总线 MOVX A,@DPTR 和MOVX @DPTR,A,我们可以用混汇编方法是可以插入,但象这种类似操作多了,代码看起来不清晰,还有一种办法:

我们先定义一个宏:#define dptr(n) (*((unsigned char xdata *)n)) 然后我们就可以象写函数一样

dptr(0xbf04)=0;

dptr(0xbf05)=0xff;

dptr(0xbf06)=0x18;

这种方式用Keil C 编译成的实际形式就是:

MOV DPTR,#0BF04H

CLR A

MOVX @DPTR,A

INC DPTR;这里Keil c自动优化为INC ,而不是 MOV DPTR,#0BF05H,使执行速度更快

MOV A,#0FFH

MOVX @DPTR,A

INC DPTR

MOV A,#018H

MOVX @DPTR,A

这种写法是和直接汇编的效率是一样高的!但反过来行不行呢?

unsigned char m;

dptr(0xbf04)=0; m=dptr(0xbf05); 编译后得到:MOV DPTR,#0BF04H

CLR A

MOVX @DPTR,A

INC DPTR

MOVX A,@DPTR

MOV m,A

效率看起来好象真不错呢!但这里有一种潜在的BUG,如我们要实现对写出去的总线再验证读的时候就出问题了,如:

do { dptr(0xbf00)=0; ACC=dptr(0xbf00); }while(!ACC0);

这段代码实际是送出总线值后再读回来,保证设置正确,但实际Keil C 编译后成了

?C0018:

MOV DPTR,#0BF00H

CLR A

MOVX @DPTR,A

MOV R7,A 这里不是 MOVX A,@DPTR

JNB ACC0,?C0018

如果真需要验证的情况下,显然没有达到我们的目的! 这种情况我一般是头文件里加 #define checkDPTR _asm MOVX A,@DPTR,在需要的时候(前后DPTR值不更改,ACC也没有再附值的时候)用于取出总线。大部分的时候,是可以这么取出来的。或者在程序过程如有加减运算(非加减1)或位运算后,累加器必参位运算,这时就可以用这种方法。程序的可读性就可大大提高的同时,保证效率。

2 循环的使用

看下面一段代码:

void SendSIOData2(const unsigned char value)

{

unsigned char i;

for(i=0,ACC=value;i<8;i++)

{

MCP2510_SCK2=0;

__asm RLC A

MCP2510_SI2=CY;

MCP2510_SCK2=1;

}

MCP2510_SCK2=0;

} 我相信至少一半的人会如此写这个循环,这种类似的代码在串行总线里是用得最多,也最可能占我们时间的,需要我们写出最经典的代码。但这种循环汇编后的代码是

CLR A

MOV R6,A

MOV A,R7

CLR MCP2510_SCK2 ......循环体省了

INC R6

CJNE R6,#08H,?C0005

如果我们把 for(i=0,ACC=value;i<8;i++) 改成 for(i=8,ACC=value;i!=0;i--) 呢?判断循环体就成了: MOV R6,08H 。。。DJNZ R6 ,?C0005

一个小小的编程习惯让我们在这里至少提高了10%-20%的效率。



本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。