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

SFR access without keyword "sfr"

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;
Unfortunately the generated code is :
MOV  	R0,#0A8H
MOV  	@R0,#01H
which is indirect addressing and points to the upper 128 bytes of
internal memory (in a 8052) or nowhere (with 8051).

If I try to address specificly the upper 128 bytes of internal RAM using
* ((unsigned char idata *) 0xA8) = 0x1;
then the generated code is :
MOV  	R0,#0A8H
MOV  	@R0,#01H
which seems to be correct.

I think I miss something but I don't see what.
Anybody can help ?

Thanks in advance.

Arnaud

Parents
  • 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) ...

    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.


    Write two functions, maskInterrupt() and allowInterrupt() that take an enum of all 14 possible interrupts. Have these functions set/clear the appropriate bits in IE0 and IE1. Also, write enableInterrupts() and disableInterrupts() which set/clear the .EA flag. SFR's are registers, registers are hardware, hardware is global, you can not make an SFR local. C scoping rules don't apply to them.

    - Mark

Reply
  • 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) ...

    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.


    Write two functions, maskInterrupt() and allowInterrupt() that take an enum of all 14 possible interrupts. Have these functions set/clear the appropriate bits in IE0 and IE1. Also, write enableInterrupts() and disableInterrupts() which set/clear the .EA flag. SFR's are registers, registers are hardware, hardware is global, you can not make an SFR local. C scoping rules don't apply to them.

    - Mark

Children