Experience in accessing the special function register sfr in the C language environment

The special function register SFR of the microcontroller is the SRAM unit whose SRAM address has been determined. There are two methods for summarizing the access in the C language environment. 1

Implemented using standard C's casts and pointers

Use the standard C cast and pointer concept to implement access to the MCU registers, for example: #define DDRB (*(volatile unsigned char *)0x25)

analyse as below:

A: (unsigned char *) 0x25 in 0x25 is just a value, plus (unsigned char *) means 0x25 is an address, and the data type of the data stored in this address is unsigned char, meaning that when reading / writing this address To write the value of unsigned char, read the value of unsigned char.

(*(volatile unsigned char *)0x25) is a fixed pointer that is immutable, not a pointer variable. Then add "*" in front, that is, *(volatile unsigned char *) 0x25 becomes a variable (normal unsigned char variable, not a pointer variable), if it is #define i (*(volatile unsigned char *)0x25), It is the same as unsigned char i, except that the address of the previous i is fixed.

B: The keyword volatile ensures that this instruction will not be omitted as an optimization of the C compiler and requires direct reading each time. For example, when using while(*(unsigned char *)0x25), sometimes the system may not actually read the value of 0x25, but use the value read out for the first time. If so, the loop may be an infinite loop. Using volatile requires reading the actual value of 0x25 every time.

In this way, the SRAM cell with 0x25 address is read/written, and DDRB can be written directly, that is, DDRB is a variable, but the address of the variable is fixed to 0x25. E.g:

DDRB = 0xff;

This is much more intuitive and convenient than using pointer variables directly, for example:

Unsigned char *p, i;p = 0x25;i = *p; //Read the data in the address 0x25 unit into the i variable *p = 0; //write 0 to the unit with address 0x25

To sum up, (*(volatile unsigned char *)0x25) can be regarded as a normal variable, this variable å“Ÿ fixed address, pointing to 0x25. And 0x25 is just a constant, not a pointer, not a variable.

2

Syntax expansion for the C compiler

Syntax extensions to the C compiler. For example, the extended sfr keyword in the MCS51 series KeilC is as follows:

Sfr P0 = 0x80;

In this way, the 0x80 unit can be directly written to P0.

The following describes the method of accessing the MCU registers for the AVR song C compiler.

A: The standard C's forced type conversion and pointers are used to implement access to the MCU's registers. Each C compiler supports it for the simple reason that this is standard C.

B: ICCAVR and GCCAVR do not define new data types. Only standard C mandatory casts and pointers can be used to implement access to the MCU registers. The IAR and CodeVisionAVR compilers have extended ANSI C to define new data types. C language can directly access the relevant registers of the MCU. For example, in IAR:

SFR_B (DDRB, 0x28) CodeVisionAVR: sfrb DDRB = 0x28

Thus, PORTB=0xff; equivalent to (*(volatile unsigned char *)0x05) = 0xff; and 0x25 happens to be the address of register PORTB in device ATmega48/88/168.

Each CAVRVR AVR device does not directly define a special function register macro in the header file. For example, in the iomx8.h file, one definition is as follows: #define PORTB _SFR_IO8(0x25)

The following two macro definitions can be found in sfr_defs.h:

#define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr)+0x20)#define _MMIO_BYTE(mem_addr) (*(volatile unit8_t *)(mem_addr))

Essentially the same as direct cast and pointer definitions.

In addition, macro _BV (bit) in GCCAVR is frequently used to operate I / O registers, avr-libc recommends using this macro for register bit operations, he defined in the file sfr_defs.h as follows:

#define _BV(bit) (1

The following is an example of his use;

DDRB = _BV(PB0) | _BV(PB1); //PB0 is defined as 0 in the device header file, and PB1 is 1

He is equivalent to "DDRB=0x03;", so the purpose of writing is to provide readability. Don't worry that it will generate more code than "DDRB=0x03;", the compiler will handle this kind of thing, and will eventually output the same result as "DDRB=0x03;".

Elf Bar

Elf Bar,Elf Bar 1500,Elf Bar Bc5000,Elf Bar Bc

Shenzhen Kate Technology Co., Ltd. , https://www.katevape.com