Direct access to registers and ports
Definition
SFr P0 0x80
SFr P1 0x81
SFr adcon; 0xde
Sbit EA 0x9f
Operation
Adcon = 0x08;/* write data to register */
P1 = 0xff;/* write data to port */
Io_status = P0;/* read data from Port */
Ea = 1;/* set a bit (enable all interrupts )*/
After the interrupt 1 keyword is used, the interrupt vector is automatically generated.
Local variables cannot be shared with other "background loop Code" (the background loop Code) in ISR.
Because the connector will reuse the positions of these variables in Ram, they have different meanings, depending on the different functions currently used
Reusing variables will be very important to ram's limited 51. Therefore, these functions are executed in a certain order without being interrupted.
Timer0_int () interrupt 1 using 2
{
Unsigned char temp1;
Unsigned char temp2;
Executable C statements;
}
The "interrupt" statement indicates that the vector is generated in (8 * n + 3). Here, n is the number after the interrupt parameter.
Here, an ljmp timer0_int command is generated in the code area of 08h.
"Using" tells the compiler to switch register banks on entry to an interrupt routine. this "context" switch is the fastest way of providing a fresh registerbank for an Interrupt Routine's local data and is to be preferred to stacking registers for very time-critical routines. note that interrupts of the same priority can share a register Bank, since there is no risk that they will interrupt each other.
The 'using' tells the compiler to switch the register bank into the interrupt processor. This "contet" switch is
Provides the fastest way to register the bank for local variables of the interrupt handler. Programs with strict timing requirements are the preferred stack registers (store registers to Stacks.
Note: an interrupt with the same priority can share the register bank because it is not dangerous to interrupt each time.
If a using 1 is added to the timer1 interrupt function prototype, the pushing of registers is replaced by a simple mov to psw to switch registerbanks. unfortunately, while the interrupt entry is speeded up, the direct register addressing used on entry to sys_interp fails. this is because C51 has not yet been told that the registerbank has been changed. if no working registers are used and no other function is called, The optimizer eliminiates teh code to switch register banks.
If using 1 is used in the interrupt function prototype of timer1, the register pushing will be replaced by the mov to psw switching register bank.
Unfortunately, when an interrupt entry is accelerated. Direct register addressing for entry will fail.
This is because the C51 did not tell the register that the Bank has changed. Registers that do not work will be used. If no other function is called, optimizer .....
Logically, with an Interrupt Routine, parameters cannot be passed to it or returned. when the interrupt occurs, compiler-inserted code is run which pushes the accumulator, B, dptr AND THE psw (program status word) onto the stack. finally, on exiting the Interrupt Routine, the items previusly stored on the stack are restored and the closing "}" causes a reti to be used rather than a normal ret.
Logically, a service interruption program cannot pass parameters or return values.
When the interrupt occurs, the code inserted by the compiler is run, which puts the accumulators, B, dptr, and psw (program State word) into the stack. Finally, the pre-stored in the stack is restored when the interrupted program is exited. Last "}" ending symbol
Insert reti to the end of the interrupt program,
To create an interrupt service program (ISR) in the Keil 'C' language, use the interrupt keyword and correct interrupt number to declare a static void function. The Keil 'C' compiler automatically generates the interrupt vector and the Import and Export Code of the interrupt program. The interrupt function attribute indicates that the function is ISR. The using attribute can be used to specify which register zone the ISR uses. This is optional. Valid register ranges from 1 to 3.
Vector location of the interrupt source
Interrupt source Keil interrupt number vector address
Highest priority 6 0x0033
External Interrupt 0 0 0x0003
Timer 0 overflow 1 0x000b
External Interrupt 1 2 0x0013
Timer 1 Overflow 3 0x001b
Serial Port 4 0x0023
Timer 2 Overflow 5 0x002b
DMA 7 0x003b
Hardware breakpoint 8 0x0043
JTAG 9 0x004b
Software breakpoint 10 0x0053
Monitoring timer 12 0x0063
1.
Before a function is called, the definition is very different from the code generated after the call (especially when the optimization level is greater than 3 ). (I am not quite sure why, probably because the called function has known the usage of the called function to the register before the call is defined, the function itself can be optimized; after the call, the function does not know the usage of the called function to the Register, by default, the called function has changed the registers (ACC, B, DPH, DPL, psw, R0, R1, R2, R3, R 4, R5, R6, and r7, therefore, valid data is not stored in these registers)
2.
When a function is called, in addition to storing the returned address in the stack, do not store the contents of any other registers (ACC, B, DPH, DPL, psw, R0, R1, R2, R3, R 4, R5, R6, r7) in the stack. (Unless the using feature is used by the called function)
3.
The interrupt function is an exception, it calculates itself and the functions it calls (ACC, B, DPH, DPL, psw, R0, R1, R2, R3, R 4, R5 ,, r6, r7), and save the registers that it considers to be changed.
4.
When using C to write a program, use the Using n (n = 0, 1, 2, 3) features as little as possible. (This feature has some problems when I use it. I don't know if it is a small bug)
The default function in Keil C51 uses the 0 register group. When the interrupt function uses using N, N =, 3 may be correct, but n = 0, the program already has a bug (this bug is not displayed only when the interrupt function and the called function do not change the value of R0-r7 ))
One conclusion is that if using N is used in the interrupt function, the interrupt no longer saves the value of the R0----R7.
It can be inferred that a high-priority interrupt function and a low-priority interrupt function both use using N, (n =, 2, 3) WHEN n is the same, how hidden this bug is. (This is something that people cannot imagine)
Functions using different register groups (except in special cases) cannot be called each other
Using "keyword tells the compiler to switch between register bank
If the interrupt program is not important, the using keyword can be ignored.
If a function is called from the interrupt program, and this interrupt is forced to use using
When compiling a called function, the compiler must tell it
1)
Pseudo commands must be used before Functions
# Pragma noaregs
Before entering the Function
# Pragma restore
Or
# Pragmas aregs
In this way, "absolute address location" is not used"
2)
# Pragma registerbank (N)
Use this parameter to tell the currently used bank
Remove mov R7, ar7 with the noaregs command
Service interruption routine
/* Timer 0 overflow interrupt service routine */
Timer0_int () interrupt 1 using 1 {
Unsigned char temp1;
Unsigned char temp2;
/* Executable C statements */
}
Called function
# Pragma save // rember current registerbank
# Pragma registerbank (1) // Tel C51 base address of current registerbank.
Void func (char X) {// called from Interrupt Routine
// With "using1"
/* Code */
}
# Pragma restore // put back to original registerbank
If the interrupt service routine uses using, the function called by the interrupt service routine must be
Registerbank (N)
A function called by ISR may also be called by background programs.
For function "reentrant" (reentrant)
The basic structure of the 8051 series MCU includes 32 I/O Ports (4 groups of 8-bit ports), two 16-bit timer counters, and full-duplex serial communication; 6 interrupt sources (2 external interruptions, 2 scheduled/Counter interruptions, 1 Serial Port input/output interruptions), two levels of Interrupt priority; 128 bytes of built-in Ram; an independent 64 K-byte addressable data and code zone. After the interruption occurs, the MCU switches to one of the five interrupt entrances and then executes the corresponding interrupt service.
Processing Program. The interrupt program entry address is placed in the interrupt vector by the compiler, And the interrupt vector is located at the lowest address of the program code segment. Note that the serial input/output interrupt here shares an interrupt vector. 8051 of the interrupt vector table is as follows:
Interrupt source interrupt vector
---------------------------
Power-On Reset 0000 h
External Interrupt 0 0003 H
Timer 0 overflow 000bh
External Interrupt 1 0013 H
Timer 1 Overflow 001bh
0023 H disconnection from the serial port
Timer 2 Overflow 002bh
Interrupt and using are both key words 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 relationship is as follows:
The 8051
Enable bit 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 interruption
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 accumulators A, status registers, register B, data pointers, and default registers. As long as they are used in the interrupt program, the compiler will push them to the stack and end them at the end of the interrupt program. The C51 supports up to 27 interrupt sources for all 5 8051 standard interruptions from 0 to 4 and in the 8051 series (enhanced.
The using keyword is used to specify the register group used by the interrupt service program. Usage: Using is followed by a number ranging from 0 to 3, corresponding to four groups of working registers. Once a working register group is specified, the default working register group will not be pressed to the stack, which will save 32 processing cycles, because both the inbound and outbound stacks require two processing cycles. The disadvantage of this practice is that all call interruption processes must use the same register group specified; otherwise, an error occurs when passing parameters. Therefore, using requires flexible choice in use.