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:
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)
In 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)
Here 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;".
ShenZhen Haofa Metal Precision Parts Technology Co., Ltd. , https://www.haofametals.com