ARM Technical Support Knowledge Articles

HOW TO DIRECTLY ADDRESS MULTIPLE CONSECUTIVE SFRS

Applies to: C51 C Compiler

Answer


Information in this article applies to:


QUESTION

Can I use structures to access data in the direct area of my 8051? I would also like to address several byte wide SFRs as one data element. I wrote the following code:

typedef union {
  char bits8;
  int bits16;
  long bits32;
} PAGE_TYPE;

PAGE_TYPE data* PageData = 0xBC;

But this generates an indirect read through a register.

Is there a more optimal solution to this problem?

ANSWER

It is not possible to locate variables of any kind, except sfrs, in the SFR memory area.

When you located the union at BCH and obtained indirect addressing, you were actually accessing the portion of idata that resides between 80H and FFH. This overlays the SFR area, which also resides between 80H and FFH. In fact, when you locate any variable between 80H and FFH, it is located in idata, not the SFR area.

However there are two ways to solve this problem

1. Solution directly in the C Language

One solution is to declare each SFR with a separate name and perform shifting operations. For example:

sfr EDATA1 = 0xBC;
sfr EDATA2 = 0xBD;
sfr EDATA3 = 0xBE;
sfr EDATA4 = 0xBF;

#define READ16 ((EDATA1 << 8 ) | (EDATA2))
#define READ32 ((EDATA1 << 24 ) | (EDATA2 << 16 ) | (EDATA3 << 8 ) | (EDATA4))

Another more optimal solution uses type casting:

sfr EDATA1 = 0xBC;
sfr EDATA2 = 0xBD;
sfr EDATA3 = 0xBE;
sfr EDATA4 = 0xBF;

void main (void)  {
  unsigned long lval;

  EDATA1 = ((unsigned char *) &lval) [0];
  EDATA2 = ((unsigned char *) &lval) [1];
  EDATA3 = ((unsigned char *) &lval) [2];
  EDATA4 = ((unsigned char *) &lval) [3];
}

The code generated for this solution appears as follows:

0000 8500BC R MOV EDATA1,asdf
0003 8500BD R MOV EDATA2,asdf+01H
0006 8500BE R MOV EDATA3,asdf+02H
0009 8500BF R MOV EDATA4,asdf+03H
000C 22 RET

2. Solution via Assembler define

In assembly language you may define the address of the SFR as a PUBLIC symbol. For example:

--- SRFSYM.A51 ---
PUBLIC ADRES
   EDATA_SFR  DATA  0xBC
END

Now you may access the SFR as a long value in the C source code by using an extern variable definition:

extern unsigned long data EDATA_SFR;

unsigned long v;

void test (void)  {
  v = EDATA_SFR;
  EDATA_SFR = 123456;
}

MORE INFORMATION

SEE ALSO

Article last edited on: 2005-08-05 08:13:23

Rate this article

[Bad]
|
|
[Good]
Disagree? Move your mouse over the bar and click

Did you find this article helpful? Yes No

How can we improve this article?

Link to this article
Copyright © 2011 ARM Limited. All rights reserved. External (Open), Non-Confidential