⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c518.txt

📁 dsp&c51的编程,从小百合上down的
💻 TXT
📖 第 1 页 / 共 2 页
字号:
发信人: reflection (似水流年), 信区: EEtechnology 

标  题: C51 Primer (7) Accessing External Memory mapped 

发信站: 南京大学小百合站 (Wed Nov 24 12:00:35 1999), 转信 

  

  

7 Accessing External Memory Mapped 

Peripherals 

Commonly, extra IO ports are added to 8051s to compensate for the loss of Po 

rts 0 and 2. This is normally done by making the additional device(s) appear 

 to be just external RAM bytes. Thus they are addressed by the MOVX A,@DPTR 

instruction. Typically UARTS, additional ports and real time clock devices a 

re added to 8031s as xdata-mapped devices. 

The simplest approach to adding external devices is to attach the /RD and or 

 /WR lines to the device. Provided that only one device is present and that 

it only has one register, no address decoding is necessary. To access this d 

evice from C simply prefix an appropriately named variable with "xdata". Thi 

s will cause the compiler to use MOVX A,@DTPR instructions when getting data 

 in or out. In actual fact the linker will try to allocate a real address to 

 this but, as no decoding is present, the device will simply be enabled by / 

WR or /RD. 

In practice life is rarely this simple. Usually a mixture of RAM, UARTS, por 

ts, EEPROM and other devices may all be attached to the 8031 by being mapped 

 into the xdata space. Some sort of decoding is provided by discrete logic o 

r (more usually) a PAL. 

Here the various registers of the different devices will appear at fixed loc 

ations in the xdata space. With normal on-chip resources the simple "data bo 

ok" name can be used to access them, so ideally these external devices shoul 

d be the same. 

There are three basic approaches to this: 

Use normal variables, char, ints etc, located by the linker 

Use pointers and offsets, either via the XBYTE macros or directly with user- 

defined pointers. 

Use the _At_ and _ORDER directives. 

In detail, these may be implemented as shown in the following sections. 

7.1 The XBYTE And XWORD Macros 

To allow memory-mapped devices to be accessed from C, a method is required t 

o effectively force pointers to point to fixed addresses. C51 provides many 

methods of achieving this, the simplest of which are the XBYTE[addr16] and X 

WORD[addr16] macros 

For instance: 

The byte wide PORT8_DDI register of a memory mapped IO device is at 8000H. T 

o access it from C it must be declared thus: 

    #include "absacc.h";   /*Contains macro definitions */ 

    #define port8_ddi   XBYTE[0x8000] 

    #define port8_data  XBYTE[0x8001] 

To use it then, 

    port8_ddi = 0xFF       ; 

    input_val = port8_data ; 

To access a word at an even external address: 

    #define word_reg XWORD[0x4000] 

    /* gives a word variable at 8000H */ 

Ignoring the pre-defined XWORD macro, the equivalent C line is: 

    #define word_reg_ptr ((unsigned int *) 0x24000L) 

    /*creates a pointer to a word (int) at address 8000H*/ 

To use this address then, 

    *word_reg_ptr = 0xFFFF ; 

Note that the address 8000H corresponds to 4000H words, hence the " 0x24000L 

 ". 

Here are some examples with the code produced: 

#define XBYTE ((unsigned char volatile *) 0x20000L) 

#define XWORD ((unsigned int volatile *) 0x20000L) 

main() { 

char x ; 

 int y ; 

x = XBYTE[0x8000]       ; 

0000 908000        MOV     DPTR,#08000H 

0003 E0            MOVX    A,@DPTR 

0004 FF            MOV     R7,A 

0005 8F00    R     MOV     x,R7 

y = XWORD[0x8000/sizeof(int)] ; 

} 

0007 908000        MOV     DPTR,#08000H 

000A E0            MOVX    A,@DPTR 

000B FE            MOV     R6,A 

000C A3            INC     DPTR 

000D E0            MOVX    A,@DPTR 

000E FF            MOV     R7,A 

000F 8E00    R     MOV     y,R6 

0011 8F00    R     MOV     y+01H,R7 

} 

0013         ?C0001: 

0013 22            RET 

However the address indicated by "word_reg" is fixed and can only be defined 

 at compile time, as the contents of the square brackets may only be a const 

ant. Any alteration to the indicated address is not possible with these macr 

o-based methods. This approach is therefore best suited to addressing locati 

ons that are fixed in hardware and unlikely to change at run time. 

Note the use of the volatile storage class modifier. This is essential to pr 

event the optimiser removing data reads from external ports. 

See section 7.4 for more details. 

Note: the header file "absacc.h" must be included at the top of the source f 

ile as shown above. This contains the prototype for the XBYTE macro. (see pa 

ge 9-15 in the C51 manual) 

7.2 Initialised XDATA Pointers 

In many cases the external address to be pointed at is known at compile time 

 but may need to be altered at some point during execution. Thus some method 

 of making a pointer point at an intial specific external address is require 

d. 

Probably the simplest way of setting up such a pointer is to let the C_INIT 

program set the pointer to a location. However the initial address must be k 

nown at compile time. If the pointer is to be altered at run time, just equa 

te it (without the "*" at run time) to the new address. 

Note: this automatic initialisation was not supported on earlier versions of 

 C51. 

Simply do: 

/* Spaced pointer */ 

  xdata char xdata *a_ptr = 0x8000 ; 

/* Generic Pointer */ 

  xdata char *a_ptr = 0x028000L ; 

Here the pointer is setup to point at xdata address 0x8000. Note that the sp 

aced *a_ptr can only point at xdata locations as a result of the second xdat 

a used in its declaration. In the generic *a_ptr case, the "02" tells C51 th 

at an xdata address is intended. 

An example might be: 

   6             xdata char xdata *ptr = 0x8000 ; 

   7 

   8 

   9             main() { 

  11   1         char x ; 

  13   1         ptr += 0xf0 ; 

0000 900000  R     MOV     DPTR,#ptr+01H 

0003 E0            MOVX    A,@DPTR 

0004 24F0          ADD     A,#0F0H 

0006 F0            MOVX    @DPTR,A 

0007 900000  R     MOV     DPTR,#ptr 

000A E0            MOVX    A,@DPTR 

000B 3400          ADDC    A,#00H 

000D F0            MOVX    @DPTR,A 

  15   1         x = *ptr ; 

  16   1 

  17   1         } 

000E E0            MOVX    A,@DPTR 

000F FE            MOV     R6,A 

0010 A3            INC     DPTR 

0011 E0            MOVX    A,@DPTR 

0012 F582          MOV     DPL,A 

0014 8E83          MOV     DPH,R6 

0016 E0            MOVX    A,@DPTR 

0017 F500    R     MOV     x,A 

  17   1         } 

0019 22            RET 

7.3 Run Time xdata Pointers 

The situation often occurs that you need to point at addresses in the xdata 

space which are only known at run time. Here the xdata pointer is setup in t 

he executable code. 

The best way to achieve this is to declare an "uncommitted" pointer at compi 

le time and to then equate it to an address when running: 

char xdata *xdata_ptr ;   /* Uncommitted pointer */ 

                    /* to xdata memory */ 

main() { 

xdata_ptr=(char xdata*) 0x8000 ; /*Point at 0x8000 in */ 

                                   /*xdata */ 

} 

An alternative is to declare a pointer to the xdata space and simply equate 

it to a variable. 

Here is an example: 

   char xdata *ptr ; /* This is a spaced pointer!!! */ 

   main(){ 

   start_address = 0x8000 ;  /*Variable containing address*/ 

                    /*to be pointed to */ 

0000 750080  R     MOV     start_address,#080H 

0003 750000  R     MOV     start_address+01H,#00H 

   ptr = start_address ; 

000C AE00    R     MOV     R6,start_address 

000E AF00    R     MOV     R7,start_address+01H 

0010 8E00    R     MOV     ptr,R6 

0012 8F00    R     MOV     ptr+01H,R7 

0014         ?C0001: 

   while(1) { 

   x = *ptr++ ; 

0014 0500    R     INC     ptr+01H 

0016 E500    R     MOV     A,ptr+01H 

0018 AE00    R     MOV     R6,ptr 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -