This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

How to use extern sbit declare?

I declare a variable unsigned char bdata Kde in a.c.

[in file a.c]

unsigned char bdata Kde;

Than I want to use the variable inb.c.
[in file b.c]
#include <stdio.h>
.....
extern unsigned char bdata Kde;
sbit testbit=Kde^1;
void main(void)
{......}

:error C141:.......a.c:syntax error near 'sbit'

why?

Parents
  • I have now tried it and it does work, but I did have to make a small change:

    [in file a.c]
    
    bdata unsigned char Kde;
    sbit testbit=Kde^1;
    
    [in file b.c]
    #include <stdio.h>
    .....
    extern bdata unsigned char Kde;
    extern bit testbit; 
    
    void main(void)
    {......}
    
    There is a section of this subject in appendix F of the C51 manual (page 328 in my copy).

Reply
  • I have now tried it and it does work, but I did have to make a small change:

    [in file a.c]
    
    bdata unsigned char Kde;
    sbit testbit=Kde^1;
    
    [in file b.c]
    #include <stdio.h>
    .....
    extern bdata unsigned char Kde;
    extern bit testbit; 
    
    void main(void)
    {......}
    
    There is a section of this subject in appendix F of the C51 manual (page 328 in my copy).

Children
  • Note that you are changing the type of 'testbit' from an sbit to a bit. How does the linker deal with this? This is very odd looking from a C standpoint and I wouldn't do it this way. Also, I cannot believe

    sbit testbit=Kde^1;
    can compile. I thought that sbits required a upper data space (e.g. DATA address 128 - 255) address to be assigned to them. Where does the linker actually place testbit? I think in this case you will simple end up with testbit as a lower data space bit var. which is not what sbit is for (that's why we have bdata). Talk about confusion.

    Regardless, this is all bad practice.

  • C51 is a bit strange with regard to bit memory, sbit etc. Of course, sbit is totally non-C. This thread contains some grumbles from me and some explanations from Keil: http://www.keil.com/forum/docs/thread1291.asp

    Yes, I agree, it is all bad practice and best avoided. Bit fields within structures is a much more natural and C compliant way to reference individual bits that belong in a 'set', but C51 does not emit efficient code for this. A variable residing in bdata and accessed by individual sbit addresses provides a way of efficiently accessing 1-bit fields withing a "structure". When fast and compact code is required, it is necessary to make use of bdata variables accessed via sbit definitions.

    The code I gave earlier in this thread is pretty much exactly what is in Appendix F of the C51 manual, it does compile and it seems to work. Actually, the type of testbit is not getting changed because bit is not a type but a memory area (like data). Perversely, C51 does not allow variables located in bit memory to have a type.

  • "I thought that sbits required a upper data space (e.g. DATA address 128 - 255) address to be assigned to them."

    It is with trepidation that I dare to suggest that you're wrong there, Mark.

    This was one of the first stumbling blocks which I fell over when I started using Keil - if you search back a couple of years, I probably moaned about it here!
    (probably along the lines, "you can tell it catches lots of people out by the way there's a special section in the manual!")

    Anyway, as I understand it, sbit is the means that Keil uses to give a name to a specific bit (hey - maybe I just hit on the meaning of the 's' there!) - whether it's in a hardware register, or a bdata variable.
    Effectively, sbit forms the definition of a bit "variable"

    bit, on the other hand, does not define the location of the "variable" - it simply says, "this is a single bit"

    Therefore, an extern must always use bit rather than sbit; repeating the sbit definition causes (if I remember correctly) a "multiple definition" Linker error.

  • Unbelievable! I never would have thought that sbit was meant for anything other than an sfr bit, that is DATA addresses > 0x80. I am sorry and disheartened about being wrong on this. I just assumed consistency where there isn't.

  • "I just assumed consistency where there isn't."

    Yes; as both Graham and I have noted, Keil's doesn't appear a particularly Elegant Solution...

  • Keil's doesn't appear a particularly Elegant Solution...

    From what I recall, the bit/sbit/bdata junk was what Intel introduced in the PL/M-51 Compiler. At the time the Keil C compiler was introduced, PL/M-51 was the de-facto standard compiler for the 8051. So, we adopted the Intel standard.

    These legacy language elements are sometimes difficult to kill-off or replace without breaking a lot of existing customer source code.

    Jon

  • The Buck Stops ... way over there! ;-)

  • I totally agree and sympathize. However, adding a feature such as

    /* foo.c */
    bit someBitVar = otherByteVar ^ 1;
    
    /* foo.h */
    extern bit someBitVar;
    probably would not break anyone's code. Right? Don't get me wrong, I think Keil's toolchain is top-notch. Especially after being stranded on PIC Island for my last project.

    - Mark

  • ...repeating the sbit definition causes (if I remember correctly) a "multiple definition" Linker error.

    If and only if they are defined in a bdata variable. There won't be any linker error if we do:

    /*Port.h*/
    .
    .
    sbit bTest   =P3^2;
    .
    .
    

  • Yes - I think that's the inconsistency Mark was referring to