The basic structure of the 8051 series MCU includes: 32 I/O ports (4 groups of 8-bit ports); two 16-bit timer counters; full-duplex serial communication; 6 interrupt sources (2 external interrupts, 2 timer/counter interrupts, 1 serial port input/output interrupt), two-level interrupt priority; 128 bytes of built-in RAM; independent 64K bytes of addressable data and code areas. After an interrupt occurs, the MCU switches to one of the 5 interrupt entry points and then executes the corresponding interrupt service
handler. The entry address of the interrupt program is placed in the interrupt vector by the compiler. The interrupt vector is located at the lowest address of the program code segment. Note that the serial port input/output interrupt here shares an interrupt vector. The interrupt vector table of 8051 is as follows:
Interrupt source interrupt vector
---------------------------
Power-on reset 0000H
External interrupt 0 0003H
Timer 0 overflow 000BH
External interrupt 1 0013H
Timer 1 overflow 001BH
Serial port interrupt 0023H
Timer 2 overflow 002BH
Both interrupt and using are keywords of C51. The interrupt process of C51 is implemented by using the interrupt keyword and the interrupt number (0 to 31). The interrupt number indicates the entry address of the compiler interrupt program. The interrupt number corresponds to the enable bit in the 8051 interrupt enable register IE. The corresponding relationship is as follows:
8051's
enable bit in IE register C51 Interrupt number Interrupt source
--------------------------------
IE.0 0 External interrupt 0
IE.1 1 Timer 0 overflow
IE.2 2 External interrupt 1
IE.3 3 Timer 1 overflow
IE.4 4 Serial port interrupt
IE.5 5 Timer 2 overflow
With this declaration, the compiler does not need to care about the use of register group parameters and the protection of accumulator A, status register, register B, data pointer and default registers. As long as they are used in the interrupt program, the compiler will push them onto the stack and pop them off the stack at the end of the interrupt program. C51 supports all five 8051 standard interrupts from 0 to 4 and up to 27 interrupt sources in the 8051 series (enhanced). The
using keyword is used to specify the register group used by the interrupt service routine. The usage is: using followed by a number from 0 to 3, corresponding to 4 groups of working registers. Once the working register group is specified, the default working register group will not be pushed onto the stack, which will save 32 processing cycles, because both stacking and popping require 2 processing cycles. The disadvantage of this approach is that all processes that call interrupts must use the same specified register group, otherwise parameter passing will be incorrect. Therefore, for using, you need to be flexible in your use.
About using:
You said in the article that "the disadvantage of this approach is that all interrupt calling processes must use the same specified register bank." Is this what you mean?
For example:
define a function
void func(unsigned char i) {
...
if(++i==0x12) {
...
}
...
}
and there is an interrupt function
void int_0(void) interrupt 0 using 1 {
....
}
In the default state, func uses register bank 0 (BANK0), so when int_0 calls func, will there be a parameter passing error when passing parameters?
Thank you!
If registers are used in the interrupt service function ISR, the use of using must be handled properly:
1. The interrupt service function uses using to specify a register bank different from the main function (the main function generally uses Register bank 0).
2. ISRs with the same interrupt priority can use using to specify the same register bank, but ISRs with different priorities must use different register banks. The function called in the ISR must also use using to specify the same register bank as the interrupt function.
3. If using is not used to specify, at the entrance of the ISR, C51 selects register bank 0 by default, which is equivalent to the entrance of the interrupt service program first executing the instruction:
MOV PSW #0.
This ensures that the high-priority interrupt is not specified by using. The low-priority interrupt using different register banks can be interrupted.
4. Use the using keyword to specify the register bank for the interrupt, so that the register bank can be switched directly without a large number of PUSH and POP operations, which can save RAM space and speed up the MCU execution time. In general, the switching of register banks is more prone to errors. You must have a clear understanding of the memory usage, and its correctness must be guaranteed by yourself. Especially when there is direct address access in the program, be careful! As for "when to use register bank switching", one situation is: when you try to run two (or more) jobs at the same time, and their scenes need some isolation, it will be used. Registers are very useful in ISR or using real-time operating system RTOS.
Principles of register bank use: 1.
The lowest 32 bytes of 8051 are divided into 4 groups of 8 registers. They are registers R0 to R7. The register bank is selected by the lower two bits of PSW. In ISR, MCU can switch to a different register bank. Access to register banks is not bit addressable. The C51 compiler stipulates that functions using using or disabling interrupts (#pragma disable) cannot return bit type values.
2. The main program (main function) uses one group, such as bank 0; all interrupts with low interrupt priority use the second group, such as bank 1; all interrupts with high interrupt priority use another group, such as bank 2. Obviously, there is no problem for interrupts of the same level to use the same set of registers, because interrupt nesting will not occur; while high-priority interrupts must use a different set from low-priority interrupts, because it is possible that a high-priority interrupt may occur in a low-priority interrupt. The compiler will automatically determine when absolute register access can be used.
3. When calling other functions in the ISR, the same register group must be used as the interrupt. When the NOAREGS command is not used to make an explicit statement, the compiler will use absolute register addressing to access the register group selected by the function (that is, specified by using or REGISTERBANK). When the register group assumed by the function is different from the actual selected register group, unpredictable results will occur, which may cause parameter passing errors and the return value may be in the wrong register group.
For example: when you need to call the same function inside and outside an interrupt, assuming that according to the program flow control, there will be no recursive call of the function, will there be any problems with such a call? If you are sure that reentry will not occur, there are two situations:
1. If the ISR and the main program use the same register bank (the main program uses BANK 0 by default, and if the ISR does not use using to specify the register area for it, it also uses BANK 0 by default), no other settings are required.
2. If the ISR and the main program use different register banks (the main program uses BANK 0 by default, and the ISR uses using to specify other BANKs), the called function must be placed in:
#pragma NOAREGS
#pragma AREGS
control parameter pair, specifying the compiler not to use absolute register addressing mode for this function; or you can also select "Don't use absolute register accesses" in Options->C51 to make all codes not use absolute register addressing mode (this will slightly reduce execution efficiency). Regardless of the above situation, the compiler will give a reentry warning, and you need to manually change the OVERLAY parameter to make a reentry description.
3. There is another way: if the code of the called function is not very long, it is better to copy the function and replace it with a different function name. This situation is suitable for ROM with enough extra space.
Therefore, if you are not sure about the use of the using keyword, it is better not to use it and let the compiler system handle it. interrupt xx using y
The xx value after interrupt is the interrupt number, that is, which interrupt port this function corresponds to. Generally, in 51,
0 is external interrupt 0
1 is timer 0
2 is external interrupt 1
3 is timer 1
4 is serial interrupt
The other root examples have their own meanings for the corresponding microcontroller. In fact, when the C compiler is compiled, the entry address of your function is converted to the jump address of the corresponding interrupt
using y. The y refers to the register group used by this interrupt function, which is generally 4 registers r0-r7 in 51. If your terminal function and other programs do not use the same register group, the register group will not be pushed into the stack when entering the interrupt, nor will it be popped out when returning to save code and time. Generally, there are only using 0,1,2,3.
The interrupt response of the microcontroller can be divided into the following steps: 1. Stop the main program. The current program will be terminated immediately after the current instruction is executed. 2. Protect the breakpoint. Push the current value of the program counter PC into the stack and save the termination address (i.e. the breakpoint address) so that the program can continue to be executed when returning from the interrupt service program. 3. Find the interrupt entry. According to the interrupts generated by 5 different interrupt sources, find 5 different entry addresses. 4. Execute the interrupt handler. I won't talk about this; 5. Interrupt return. After executing the interrupt handler, return to the main program from the interruption point and continue to execute.
The above work is done automatically by the computer and has nothing to do with the programmer. The interrupt handling program is stored at these 5 entry addresses (this is where the program is written. If the interrupt handling program is not placed there, it will be wrong because the interrupt program cannot be executed). A bit complicated, right? It doesn't matter, keep reading.
The natural priorities of the five interrupt sources are arranged in the order of external interrupt 0 → timer 0 → external interrupt 1 → timer 1 → serial port interrupt. If we do not set it, the microcontroller will continuously check each interrupt flag in this order (just like we deal with things according to habit in our lives), but sometimes we need to manually set high and low priorities, that is, the programmer sets which interrupts are high priority and which are low priority (of course, since there are only two levels, there must be only some interrupts at the priority level, while other interrupts are at the same level. The order of interrupts at the same level is determined by the natural priority. Please make sure you understand this).
Since manual priority can be set, how to set it? In fact, it is very simple. We just need to set the corresponding position of the IP register to "1". See the table below:
× × × PS PT1 PX1 PT0 PX0
Serial port T1 INT1 T0 INT0
When the computer is turned on, each interrupt is at a low priority. We can use instructions to set the priority. For example, there is a requirement to set T0 and INT1 to high priority and the others to low priority. Find the value of IP.
The first 3 bits of IP are useless and can be any value. Set it to 000, and then write 00000110 according to the requirements, that is, IP=06H, see the table below.
× × × PS PT1 PX1 PT0 PX0
0 0 0 0 0 1 1 0
Previous article:About IO port simulation SPI
Next article:Example of using the command line to compile C51 source code and generate a HEX file
- Popular Resources
- Popular amplifiers
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
- Basic features of TI's C54xDSP
- IEEE 754 floating point hexadecimal conversion tool
- Disassembling the world's first automotive LiDAR
- How to Design an RF Power Amplifier
- The simulation of multiplication floating point IP in quartus, has anyone used it?
- LED downlight replacement dimmable power supply
- LM358 audio amplifier circuit (loudspeaker)
- CircuitPython OLED Watch/Bracelet
- Research on the process of long and short printed plug products
- [TI recommended course] #[High Precision Laboratory] Magnetic Sensor Technology#