原创 Keil C51小贴士

2008-3-14 12:26 3343 11 17 分类: MCU/ 嵌入式

Keil C51的Tips



1:_testbit_() 调令对应着JBC指令,会自动清掉测试位。_at_ 和 _nop_()
都挺好用。但是,_crol_()等循环调令就没什么意思了,循环不带Cy,不会给位操作带来方便,而且,即使只循环一位,也带个计数器,是典型的垃圾代码。



2:打开.M51文件察看内存分配情况。在Option for Target->C51中选中Keep
Variable in order会使检察内存容易些。在Option for
Target->Listing->Linker Listing中,只选择Memory Map和Public Symbols会使.M51减肥。



3:编译器会从0x00开始为所有的子程序分配局部变量,然后,从局部变量的最高地址+1开始分配全局变量。全局变量的最高地址+1开始是堆栈区。由于编
译器不会优化内存,故idata区的下方可能会有部分空白区域被浪费,可以通过手工移动全局变量(特别是数组类型的变量)的定义相对顺序尝试解决。



4:返回bit的函数,返回值在"Cy"中。函数的bit参数,会自动安排为public,在bdata中定义。



5:使用强制类型转换可能会发生意外。



6:switch(){case...}块中最好加上"default: break;"。否则死都不知道怎么死的(未曾确认,但加上后就好了,也可能是巧合)。



7:不要在定义全局变量时赋初始值,可以在主程序开始时人工初始化。否则编译器会在Startup.A51的最后两句:MOV
SP,#?STACK-1 和 LJMP ?C_START
之间加入一大堆初始化语句,效率低下,令人讨厌。


8:在Keil C51的目录下有一个文件"C51.pdf"是原版的帮助,不过,目录做的不是很详细,查找什么东西最好用Acrobat的Find功能。另外,这个文件也不是万能的,有些东西也是不清不楚。


9:C51里嵌汇编。最好不要这样做,虽然我很喜欢汇编。

因为C51编译器不象VC++那样功能强大,所以要想在汇编中加入一个循环并且使用某一个R寄存器作为循环指针,这就有点麻烦了。换句话说,就是在嵌入的汇编语句中,不可以使用局部变量。

虽然C51有它的参数传递规则,可以知道在进入当前函数时使用了那几个寄存器,在当前函数中定义局部变量又使用了哪几个寄存器,还有那几个寄存器没有用到,但是,不能保证优化程序一定将这几个寄存器保护了,它们不一定可以被安全使用的。

虽然如此,还是要将嵌入汇编的部分做一下总结:


首先,在"Project Window"中选择要加入汇编代码的".C"文件,右击,选择"Options
for File ???.c"。在"Properties"页中,选中"Generate
Assembler SRC File"和"Assemble SRC File",使检查框由灰色变成黑色。

然后,把"...\Keil\C51\Lib\C51S.Lib"添加到"Source
Group"中。有人说该文件一定要作为工程的最后文件,倒是未必。

最后,在c函数中添加汇编语句,以 #pragma asm 开头,以 #pragma endasm
结尾。


如果汇编中有循环,可以写为如下形式:

void OutSPIByte(unsigned char m){

    unsigned char i;



    for(i = 8,ACC = m; i > 0; i--){

    #pragma asm

    clr SCK

    rlc A

    mov SI,C

    setb SCK

    nop

    #pragma endasm

    }

}

在for循环中,如果使用类似"i--"的递减方式,当终止条件为"i
> 0"时,会生成汇编代码:

    mov r6,#08H

    ......

    djnz r6,rel

当终止条件为"i > 2"时,会生成汇编代码:

    mov r6,#08H

    ......

    dec r6

    cjne r6,#02H,rel

这两种代码都是正确的。

在for循环中,如果使用类似"i++"的递增方式,当终止条件为"i
< 8"时,会生成汇编代码:

    clr A

    mov r6,A

    ......

    inc r6

    cjne r6,#08H,rel

在这种情况下,如果不是把"ACC = m"放在For循环的初始化位置,在"i
= 8"之后,而是放在整个For程序块之前,就会有灾难发生。另外,如果终止条件写错了,写成"i
< 0",汇编结果更是一塌糊涂。

所以,如果一定要嵌入汇编,在汇编的循环时,要用计数器递减方式--"i--"。


10: 只用汇编。

Keil51需要一个定义SFR的文件。可以从Keil\c51\ASM\下面拷贝一个".inc"到工作目录下,根据需要增加SFR地址定义。然后将".inc"添加到source
group,在主程序中加入#include <.inc>即可使用。

如果定义SFR的文件是以".A51"结尾的,就要在source group中修改它的Option,去掉“Include
In Target Build”选项。否则会提示“重复定义错误”。






PARTNER CONTENT

文章评论6条评论)

登录后参与讨论

用户14869 2008-3-27 21:34

果然在i++的时候会出现灾难!这也许算得上是编译器的bug!

用户411912 2008-3-27 13:40

在for循环中,如果使用类似"i++"的递增方式,当终止条件为"i < 8"时,会生成汇编代码: clr A mov r6,A ...... inc r6 cjne r6,#08H,rel 在这种情况下, “这种情况”指的是“在for循环中,如果使用类似"i++"的递增方式”。 感谢你认真阅读了我的笔记,有读者,我写的高兴。

用户411912 2008-3-27 13:33

Woodpeker的QQ会经常换,现在是947868993,不接受没有自我介绍的添加请求。

用户14869 2008-3-27 11:18

可否透露您的email or QQ or msn???

用户14869 2008-3-27 11:16

RSEG ?PR?_OutSPIByte?QIANASM _OutSPIByte: USING 0 ; SOURCE LINE # 4 ;---- Variable 'm?040' assigned to Register 'R7' ---- ; unsigned char i; ; ACC = m; ; SOURCE LINE # 6 MOV A,R7 ; for(i = 8; i > 0; i--){ ; SOURCE LINE # 7 ;---- Variable 'i?041' assigned to Register 'R7' ---- MOV R7,#08H ?C0001: ; #pragma asm ; clr SCK clr SCK ; rlc A rlc A ; mov SI,C mov SI,C ; setb SCK setb SCK ; nop Nop ; #pragma endasm ; } ; SOURCE LINE # 15 DJNZ R7,?C0001 ; } ; SOURCE LINE # 16 ?C0004: RET ; END OF _OutSPIByte END

用户14869 2008-3-27 11:12

ACC = m放在整个For程序块之前,就会有灾难发生!我怎么看不出来! RSEG ?PR?_OutSPIByte?QIANASM _OutSPIByte: USING 0 ; SOURCE LINE # 4 ;---- Variable 'm?040' assigned to Register 'R7' ---- ; unsigned char i; ; ACC = m; ; SOURCE LINE # 6 MOV A,R7 ; for(i = 8; i > 0; i--){ ; SOURCE LINE # 7 ;---- Variable 'i?041' assigned to Register 'R7' ---- MOV R7,#08H ?C0001: ; #pragma asm ; clr SCK clr SCK ; rlc A rlc A ; mov SI,C mov SI1,C ; setb SCK setb SCK ; nop nop ; #pragma endasm ; } ; SOURCE LINE # 15 DJNZ R7,?C0001 ; } ; SOURCE LINE # 16 ?C0004: RET ; END OF _OutSPIByte END
相关推荐阅读
用户411912 2013-10-17 15:21
实用链接
贴片元件型号查询: http://www.s-manuals.com/smd  ...
用户411912 2011-03-26 18:47
Word2007小贴士
为文档添加页码: 1、    将文档分为若干“节”,每节有自己独立的页码设置及编号:在第一节最后一页的末尾,选择“页面布局”->“分隔符”->“分节符”,添加一个分节符。分节符后面的页成为...
用户411912 2009-05-20 23:27
国际邮政邮件跟踪查询
全国统一咨询电话11185 。国际邮政邮件跟踪查询:http://intmail.183.com.cn EMS查询:http://211.156.193.130邮编查询:http://211.156....
用户411912 2009-02-24 15:38
Protel99 SE被忽视的细节
今天,排了一块小板。HTML clipboard1、用"Design"->"Netlist Manager"->"Menu"->"Compare Net Li...
用户411912 2008-09-27 21:35
C语言的优先级
今天,又被优先级耽搁了1小时零2分钟,索性把这个东东放在网上,经常看到可以增强记忆。1、( )   [ ]   ->   .   四种最高优先级。2、 !   ~   ++   --   -  ...
用户411912 2008-09-25 17:47
惨烈的爆炸现场
随着惊天动地的一声巨响,某小区发生了一起罕见的爆炸事故!据目击者称,这次爆炸不是恐怖分子所为。到目前为止,未发现有人在这次爆炸事故中受伤。本博记者到达时,现场的工作人员正闻着满屋的酸味 儿,收拾着一片...
我要评论
6
11
关闭 站长推荐上一条 /3 下一条