I declare a variable unsigned char bdata Kde in a.c.
[in file a.c] unsigned char bdata Kde;
[in file b.c] #include <stdio.h> ..... extern unsigned char bdata Kde; sbit testbit=Kde^1; void main(void) {......}
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;
#include <stdio.h> ..... extern bdata unsigned char Kde; extern bit testbit; void main(void) {......}
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;
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;
...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