Hi, I'm trying to access SFR memory using the hexa address of the SFR and using only "C" instructions. Since SFR memory is accessed by direct addressing mode, like the first 128 bytes of internal RAM, I tried to use the following instruction :
* ((unsigned char data *) 0xA8) = 0x1;
MOV R0,#0A8H MOV @R0,#01H
* ((unsigned char idata *) 0xA8) = 0x1;
you can use the sfr keyword in "C" and it seems the easiest method to use? There is the _at_ keyword for absolute memory locations which should do the same (p71 C51 manual). if its only a bit, then sbit can be pointed to a sfr location. ( sbit VAR = 0xA8 )
*((unsigned char data *) 0xA8) = 0x1; Unfortunately the generated code is : MOV R0,#0A8H MOV @R0,#01H Which is exactly what should happen. The SFR's are not memory, the are registers. You cannot take the address of a register, thus you cannot point to it. You must use sbit, sfr, or sfr16 to access the 8051 registers. I.e.
*((unsigned char data *) 0xA8) = 0x1; Unfortunately the generated code is : MOV R0,#0A8H MOV @R0,#01H
sfr someBit = 0xA8; someBit = 0x12;
*((unsigned char data *) 0xA8) = 0x1; Unfortunately the generated code is : MOV R0,#0A8H MOV @R0,#01H Which is exactly what should happen. The SFR's are not memory, the are registers. ?????? Cf Keil C51 Compiler book p68 : "The 8051 family of microprocessors provides you with a distinct memory area for accessing SFRs. [...] SFRs reside from address 0x80 to 0xFF and can be accessed as bits, bytes and words. Moreover in Keil A51/A251 Assembler book p10, SFR Space Data appears as an area within DATA space. This is logic since SFR is only direct addressable as DATA area is. You cannot take the address of a register, thus you cannot point to it. You must use sbit, sfr, or sfr16 to access the 8051 registers. So if I want to init a SFR register (which is unknown at compile time), how can I do ? In fact, my application can use up to 14 interrupts. So it must initialize IE (or IE1) depending of the interrupt to enable. The best solution (from my point of view ! ;-) ) is : a funtion which receive the address of the SFR and the bit to "enable". That's why I tried to cast the SFR address into a pointer in order to address directly the byte. I also tried to use a local variable of type "sfr" but this can't be done. It seems that "sfr" type variables can only be global ones .... ? Have you a better solution ? Arnaud DELEULE
*((unsigned char data *) 0xA8) = 0x1;
It seems that "sfr" type variables can only be global ones .... ? The processor has only 1 set of registers; you can't just create a whole new set of "local" registers within a function! The Keil C51 manual is a bit misleading in its example: SFRs are declared in the same fashion as other C variables. The only difference is that the data type specified is sfr rather than char or int. For example:
sfr P0 = 0x80; /* Port-0, address 80h */
int P0 = 0x80;
The processor has only 1 set of registers; you can't just create a whole new set of "local" registers within a function! Sure but I want to name an SFR with a specific name within the local scope of a function. As you do with other parameters. And it appears that sfr can't be a parameter of a function. As I mentionned before, the SFR register to modify is unknown at compile time. I receive the address of the SFR in an unsigned char variable and don't know how to modify the corresponding SFR register value !!! So how can I do ? It seems that I have to modify the architecture of my software .... Arnaud
Cf Keil C51 Compiler book p68 : "The 8051 family of microprocessors provides you with a distinct memory area for accessing SFRs. [...] SFRs reside from address 0x80 to 0xFF and can be accessed as bits, bytes and words. Yes, and you use sbit, sfr, sfr16 to access them. Assembler allows you to do anything so I'll ignore that here. So if I want to init a SFR register (which is unknown at compile time), how can I do ? You mean on a new 8051 that Keil doesn't explicitly support? Look in the databook for the part, find the DATA address of the sfr, and sfr the thing.
sfr myNewSfr = 0xE8; if (myNewSfr & SOME_BIT) ...
Sure but I want to name an SFR with a specific name within the local scope of a function. As you do with other parameters. And it appears that sfr can't be a parameter of a function. No! SFR's cannot be parameters. Parameters are pushed onto the stack or placed in fixed locations in regular memory - you cannot do this with registers. Please stop attempting to do this - these are not memory mapped registers like external device registers. As I mentionned before, the SFR register to modify is unknown at compile time. C51 doesn't know about any SFR's at compile time. By including reg51.h you define them. Give me the address and description of you mystery SFR and I'll show you how to access it. For that matter, what chip are you using? - Mark
Yes, and you use sbit, sfr, sfr16 to access them. Assembler allows you to do anything so I'll ignore that here. When you do it in Assembler, you choose the appropriate Addressing Mode and/or mnemonic yourself; it's the sbit, sfr, sfr16 which tell the compiler that you're accessing an SFR and therefore what Addressing Mode and/or mnemonic to use.
How did what I said contradict what you said? I said, "Assembler allows you to do anything so I'll ignore that here." The OP is asking about how to do this in C but quoted irrelvant text about assembler. - Mark
How did what I said contradict what you said? No contradiction! Just adding some detail (which, as you say, was not essential to main 'C' discussion). "Reply" doesn't necessarily imply "Disagree" - sorry if it sounded that way.
"Reply" doesn't necessarily imply "Disagree" - sorry if it sounded that way. My fault. I was being overly sensitive. Please ignore me. Regards. - Mark