矿石收音机论坛

 找回密码
 加入会员

QQ登录

只需一步,快速开始

搜索
查看: 3427|回复: 6

51单片机在SDCC中实现定义位寻址变量一种方法。

[复制链接]
     
发表于 2020-4-3 08:28:31 | 显示全部楼层 |阅读模式
本帖最后由 翌阳 于 2020-4-10 12:15 编辑

!!!下面这种方法在后来发现存在个问题,那就是此变量会被其它变量覆盖,除非不允许变量覆盖,但这样会内存不够用。没找到SDCC来保留此区域不被覆盖的方法。如果能够确保变量不地址上冲突,此方法可用,否则有可能导致各种奇异的结果。在写编程器的程序时就遇到了,费了一天多功夫来找问题所在,后来才想到会不会是变量覆盖的问题,结果,果然是。
SDCC在51上有个不足,就是没有bdata变量。这样位操作就变麻烦了,什么与啊,或啊的,耗时也增加了。51在20H到2F的内部RAM是可以位寻址的,也就是变量A的第3位可以直接置1或者清0,一条指令就完成。不能浪费啊,于是想个办法,实现这功能。
Keil C51没这事儿。可SDCC是免费的啊,我喜欢用免费开源的东西。
SDCC 可以定义变量时指定所在的地址,这样就可以指定变量的地址在20H起,位变量也指定相应的地址,从0开始,8个对应20H起的一个字节变量。字变量似乎也可以这么做。
这变量也只有16个,一般用时足够了。
用宏来实现,用起来方便些。把宏写进一个头文件里,include它就可以用了。
bitMem.h:
  1. #define XBYTE ((unsigned char volatile __xdata *) 0)
  2. #define CBYTE ((unsigned char volatile __code *) 0)
  3. #define PBYTE ((unsigned char volatile __pdata *) 0)
  4. // BITCHAR(VARNAME,N)  N=0,1,2,3....15
  5. #define BITCHAR(VAR,ADD) \
  6. __data char __at 0x20+ADD VAR;\
  7. __bit __at 0x0+ADD*8 VAR##0;\
  8. __bit __at 0x1+ADD*8 VAR##1;\
  9. __bit __at 0x2+ADD*8 VAR##2;\
  10. __bit __at 0x3+ADD*8 VAR##3;\
  11. __bit __at 0x4+ADD*8 VAR##4;\
  12. __bit __at 0x5+ADD*8 VAR##5;\
  13. __bit __at 0x6+ADD*8 VAR##6;\
  14. __bit __at 0x7+ADD*8 VAR##7;
复制代码

XBYTE、CBYTE、PBYTE宏是为了直接访问外RAM,程序区,分页外RAM设计的,其实是想用P0+373或者374来扩展一下输出端口用。(想做编程器,我的那个仿真机工作在8031模式,端口不够用啊)。
下面是例程。用位寻址操作完成的跑马灯。
  1. /*
  2. */

  3. #include <mcs51/at89x52.h>
  4. #include<mcs51/bitMem.h>


  5. BITCHAR(D,0)

  6. void timer2(void) __interrupt 5{
  7.     TF2=0;

  8. }
  9. void main(void)
  10. {

  11.     __data char c=1,i=0;
  12.     __data int j=0;
  13.     __bit b=1;
  14.     RCAP2H=0;
  15.     RCAP2L=0;
  16.     T2CON=0;
  17.     T2MOD=0;
  18.     TR2=1;
  19.     ET2=1;
  20.     EA=1;
  21.     P1=0;

  22.     PBYTE[1]=0x20;
  23.     PBYTE[2]=0x55;
  24.     PBYTE[4]=0xaa;


  25.     D=0x33;
  26.     while(1){
  27.         PCON|=1;
  28.         i++;
  29.         if(i==10){
  30.             i=0;
  31.             b=D7;
  32.             D7=D6;
  33.             D6=D5;
  34.             D5=D4;
  35.             D4=D3;
  36.             D3=D2;
  37.             D2=D1;
  38.             D1=D0;
  39.             D0=b;
  40.             P1=D;
  41.         }
  42.     }
  43. }
复制代码
     
发表于 2020-4-3 10:51:08 | 显示全部楼层
貌似SDCC支持关键字bit吧,
如下定义一个位变量:
bit iFlag;
/* sdccman.pdf中有说明
When a variable is declared as a bit, it is allocated into the bit addressable memory of 8051
*/
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2020-4-3 10:56:11 | 显示全部楼层
天天爱玛丽 发表于 2020-4-3 10:51
貌似SDCC支持关键字bit吧,
如下定义一个位变量:
bit iFlag;

试了一下,还真不支持。
||=== Build: Release in testDouble (compiler: SDCC Compiler) ===|
main.c|6|error 1: Syntax error, declaration ignored at 'bit'|
main.c|6|syntax error: token -> 'iFlag' ; column 9|
||=== Build failed: 2 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|
也许是我这个版的事?这不是旧版呢。

SDCC支持 __bit 关键字,也是会放在位寻址区,问题在于我是想把8个bit变量 与一个char变量合在一起用。用union是不行的。

评分

1

查看全部评分

回复 支持 反对

使用道具 举报

     
发表于 2020-4-3 18:41:34 | 显示全部楼层
用union操作位的也比较多的,没有你的代码清爽,
typedef union {
    unsigned char c;
    struct {
        unsigned char b0:1;
        unsigned char b1:1;
        unsigned char b2:1;
        unsigned char b3:1;
        unsigned char b4:1;
        unsigned char b5:1;
        unsigned char b6:1;
        unsigned char b7:1;
    }b;
} BITS;

BITS __at (0x20) var;

void main(void)
{
    var.c = 0x55;
    var.b.b0 = 1;
    var.b.b1 = 1;

    while(1);
}
回复 支持 反对

使用道具 举报

     
发表于 2020-4-3 19:09:57 | 显示全部楼层
赞,楼主的做法是最优的,它可以直接使用mov指令,因为使用了__bit限定,
而用union的方式,为了照顾非位寻址,会优先使用ACC寄存器,这样效率就降低了很多。
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2020-4-3 19:40:41 | 显示全部楼层
这样看起来比较清爽点:
  1. typedef union {
  2.     unsigned char c;
  3.     struct {
  4.         unsigned char b0:1;
  5.         unsigned char b1:1;
  6.         unsigned char b2:1;
  7.         unsigned char b3:1;
  8.         unsigned char b4:1;
  9.         unsigned char b5:1;
  10.         unsigned char b6:1;
  11.         unsigned char b7:1;
  12.     };
  13. } BITS;

  14. BITS __at (0x20) var;

  15. void main2(void)
  16. {
  17.     var.c = 0x55;
  18.     var.b0 = 1;
  19.     var.b1 = 1;

  20.     while(1);
  21. }
复制代码

功能实现是一样的。
不过看汇编:

  1. ;        main.c:69: var.b7=var.b6;
  2.         mov        r0,#_var
  3.         mov        a,@r0
  4.         rl        a
  5.         rl        a
  6.         anl        a,#0x01
  7.         mov        r0,#_var
  8.         rrc        a
  9.         mov        a,@r0
  10.         mov        acc.7,c
  11.         mov        @r0,a
复制代码

不如这个:

  1. ;        main.c:58: D7=D6;
  2. ;        assignBit
  3.         mov        c,_D6
  4.         mov        _D7,c
复制代码

比较用的源码:

  1. /*
  2. */

  3. #include <mcs51/at89x52.h>
  4. #include<mcs51/bitMem.h>


  5. BITCHAR(D,15)

  6. typedef union {
  7.     unsigned char c;
  8.     struct {
  9.         unsigned char b0:1;
  10.         unsigned char b1:1;
  11.         unsigned char b2:1;
  12.         unsigned char b3:1;
  13.         unsigned char b4:1;
  14.         unsigned char b5:1;
  15.         unsigned char b6:1;
  16.         unsigned char b7:1;
  17.     };
  18. } BITS;
  19. BITS __at (0x20) var;

  20. void timer2(void) __interrupt 5{
  21.     TF2=0;

  22. }
  23. void main(void)
  24. {

  25.     __data char c=1,i=0;
  26.     __data int j=0;
  27.     __bit b=1;
  28.     RCAP2H=0;
  29.     RCAP2L=0;
  30.     T2CON=0;
  31.     T2MOD=0;
  32.     TR2=1;
  33.     ET2=1;
  34.     EA=1;
  35.     P1=0;

  36.     PBYTE[1]=0x20;
  37.     PBYTE[2]=0x55;
  38.     PBYTE[4]=0xaa;


  39.     D=0x33;
  40.     var.c=0xa0;
  41.     while(1){
  42.         PCON|=1;
  43.         i++;
  44.         if(i==10){
  45.             i=0;

  46.             b=D7;
  47.             D7=D6;
  48.             D6=D5;
  49.             D5=D4;
  50.             D4=D3;
  51.             D3=D2;
  52.             D2=D1;
  53.             D1=D0;
  54.             D0=b;
  55.             P1=D;

  56.             b=var.b7;
  57.             var.b7=var.b6;
  58.             var.b6=var.b5;
  59.             var.b5=var.b4;
  60.             var.b4=var.b3;
  61.             var.b3=var.b2;
  62.             var.b2=var.b1;
  63.             var.b1=var.b0;
  64.             var.b0=b;
  65.             P1=var.c;
  66.         }
  67.     }
  68. }
复制代码

回复 支持 反对

使用道具 举报

     
发表于 2020-4-3 23:44:24 | 显示全部楼层
学习了
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 加入会员

本版积分规则

小黑屋|手机版|矿石收音机 ( 蒙ICP备05000029号-1 )

蒙公网安备 15040402000005号

GMT+8, 2025-4-29 05:11

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表