The special function register SFR of the microcontroller is an SRAM unit with a fixed SRAM address. There are two ways to access it in the C language environment.
1. Use the standard C forced type conversion and pointer to implement
the use of standard C forced conversion and pointer concepts to access the MCU registers, for example:
#define DDRB (*(volatile unsigned char *)0x25)
The analysis is as follows:
A: The 0x25 in (unsigned char *)0x25 is just a value. The addition of (unsigned char *) in front means that 0x25 is an address, and the data type of the data stored at this address is unsigned char, which means that when reading/writing this address, the value of unsigned char must be written in, and the value of unsigned char is also read out.
(*(volatile unsigned char *)0x25) is a fixed pointer, which is immutable, not a pointer variable. Add "*" in front, that is, *(volatile unsigned char *)0x25, and it becomes a variable (a 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 i in front is fixed.
B: The keyword volatile ensures that this instruction will not be omitted for optimization by the C compiler, and requires direct reading of the value 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 for the first time. If so, this loop may be an infinite loop. Using volatile requires reading the actual value of 0x25 each time.
In this way, to read/write the SRAM unit with 0x25 as the address, just write DDRB directly, that is, DDRB is a variable, but the address of the variable is fixed to 0x25. For example:
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 unit with address 0x25 and send it to the i variable
*p = 0; //Write 0 to the unit with address 0x25
In summary, (*(volatile unsigned char *)0x25) can be regarded as an ordinary variable. This variable has a fixed address and points to 0x25. 0x25 is just a constant, not a pointer, let alone a variable.
2. Expand the syntax of the C compiler
Expand the syntax of the C compiler. For example, expand the sfr keyword in the MCS51 series KeilC, as follows:
sfr P0 = 0x80;
In this way, the 0x80 unit can be directly written to P0.
The following is a brief introduction to the method of accessing MCU registers by the AVR C compiler.
A: Use standard C type conversion and pointers to access MCU registers. Every C compiler supports this. The reason is simple. This is standard C.
B: ICCAVR and GCCAVR do not define new data types. Only standard C type conversion and pointers can be used to access MCU registers. IAR and CodeVisionAVR compilers have expanded ANSI C and defined new data types. C language can directly access MCU registers. For example, in IAR:
SFR_B(DDRB, 0x28)
In CodeVisionAVR:
sfrb DDRB = 0x28
In this way, PORTB = 0xff; is equivalent to (*(volatile unsigned char *)0x05) = 0xff; and 0x25 is exactly the address of register PORTB in the device ATmega48/88/168.
GCCAVR Each AVR device does not use direct definition of special function register macros in the header file. For example, in the iomx8.h file, a definition is as follows:
#define PORTB _SFR_IO8(0x25)
and in sfr_defs.h, the following two macro definitions can be found:
#define _SFR_IO8(io_addr) _MMIO_BYTE((io_addr)+0x20)
#define _MMIO_BYTE(mem_addr) (*(volatile unit8_t *)(mem_addr))
is essentially the same as direct type conversion box pointer definition.
In addition, the macro _BV(bit) in GCCAVR is frequently used to operate I/O registers. avr-libc recommends using this macro to operate register bits. It is defined in the file sfr_defs.h as follows:
#define _BV(bit) (1<<(bit))
The following is an example of its use;
DDRB = _BV(PB0) | _BV(PB1); //The device header file has defined PB0 to represent 0 and PB1 to represent 1.
It is equivalent to "DDRB=0x03;". The purpose of writing this is to provide program readability. Don't worry that it will generate larger code than "DDRB=0x03;". The compiler will handle this and will eventually output the same result as "DDRB=0x03;".
Previous article:AVR-atmega16 BOOTLoader Program
Next article:Notes on using avr studio - Issues related to cannot find '*.elf'
Recommended ReadingLatest update time:2024-11-17 00:54
- Popular Resources
- Popular amplifiers
- Wireless Sensor Network Technology and Applications (Edited by Mou Si, Yin Hong, and Su Xing)
- Modern Electronic Technology Training Course (Edited by Yao Youfeng)
- Modern arc welding power supply and its control
- Small AC Servo Motor Control Circuit Design (by Masaru Ishijima; translated by Xue Liang and Zhu Jianjun, by Masaru Ishijima, Xue Liang, and Zhu Jianjun)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- Someone's Volkswagen chip burned out, come and help him
- Matlab Machine Learning (English and Chinese subtitles)
- 【NXP Rapid IoT Review】+Preparation for Data Download
- 10 common basic knowledge of MCU
- [RT-Thread reading notes] The simplest port to STM32F103CBT6
- I am 31 years old, I have been coding for 10 years, and I will retire tomorrow!
- Evaluation of domestic single-chip networking chips
- [Jihai APM32E103VET6S MINI Development Board Review] Second post PLL and system clock questions
- Ink screen calendar based on AB32 and RT-Thread, open source
- Transistor common emitter amplifier circuit