There are usually two ways to achieve delay: one is hardware delay, which requires the use of timers/counters. This method can improve the CPU's work efficiency and achieve precise delay; the other is software delay, which mainly uses a loop body.
1 Using timers/counters to achieve precise delays
Single-chip microcomputer systems usually use 11.059 2 MHz, 12 MHz or 6 MHz crystal oscillators. The first one is easier to generate various standard baud rates, and the latter two have a machine cycle of 1 μs and 2 μs respectively, which is convenient for accurate delay. This program assumes that a crystal oscillator with a frequency of 12 MHz is used. The longest delay time can reach 216=65 536 μs. If the timer works in mode 2, it can achieve extremely short time accurate delay; if other timing modes are used, the time to reload the initial value of the timing must be considered (reloading the initial value of the timer takes 2 machine cycles).
In practical applications, timing often uses interrupts. If appropriate loops are performed, a delay of several seconds or even longer can be achieved. Using a timer/counter to delay is the best solution from the perspective of program execution efficiency and stability. However, it should be noted that after the interrupt service program written in C51 is compiled, the PUSH ACC, PUSH PSW, POP PSW and POP ACC statements will be automatically added, which will take up 4 machine cycles when executed; if there is a count value plus 1 statement in the program, it will take up another 1 machine cycle. The time consumed by these statements should be taken into account when calculating the initial value of the timing, and subtracted from the initial value to achieve the purpose of minimum error.
2 Software Delay and Time Calculation
In many cases, the timer/counter is often used for other purposes, and at this time, the only way to delay is by software. Here are several methods of software delay.
2.1 Short delay
You can define a series of different delay functions in a C file by using a function with a _NOP_() statement, such as Delay10us(), Delay25us(), Delay40us(), etc., and store them in a custom C file. When needed, call them directly in the main program. For example, a delay function with a delay of 10 μs can be written as follows:
void Delay10us( ) {
_NOP_( );
_NOP_( );
_NOP_( );
_NOP_( );
_NOP_( );
_NOP_( );
}
The Delay10us() function uses a total of 6 _NOP_() statements, each of which takes 1 μs to execute. When the main function calls Delay10us(), it first executes a LCALL instruction (2 μs), then executes 6 _NOP_() statements (6 μs), and finally executes a RET instruction (2 μs). Therefore, it takes a total of 10 μs to execute the above function. This function can be used as a basic delay function and called in other functions, that is, nested calls [4], to achieve a longer delay; but it should be noted that if the Delay10us() function is directly called 4 times in Delay40us(), the delay time obtained will be 42 μs, not 40 μs. This is because when executing Delay40us(), a LCALL instruction (2 μs) is first executed, then the first Delay10us() is executed, and when the last Delay10us() is executed, it returns directly to the main program. Similarly, if there are two levels of nested calls, such as calling Delay40us() twice in Delay80us(), the LCALL instruction (2 μs) must be executed first, and then the Delay40us() function (84 μs) must be executed twice, so the actual delay time is 86 μs. In short, only the innermost function executes the RET instruction. This instruction returns directly to the parent function or the main function. For example, if Delay10us() is called 8 times directly in Delay80μs(), the delay time is 82 μs. By modifying the basic delay function and making appropriate combined calls, the above method can achieve delays of different times.
2.2 Delaying by nesting assembly program segments in C51
In C51, assembly language statements can be nested through the preprocessing instructions #pragma asm and #pragma endasm. The assembly language written by the user follows #pragma asm and ends before #pragma endasm.
For example: #pragma asm
…
Assembly language program segment
…
#pragma endasm
The delay function can set the entry parameter, and the parameter can be defined as unsigned char, int or long. According to the transmission rules of parameters and return values, the parameters and function return values are located in R7, R7R6, R7R6R5. The following points should be noted when applying:
#pragma asm and #pragma endasm are not allowed to be nested;
The preprocessing directive #pragma asm should be added at the beginning of the program, and only comments or other preprocessing directives can be placed before this directive;
When using the asm statement, the compilation system does not output the target module, but only outputs the assembly source file;
asm can only use lowercase letters. If asm is written in uppercase, the compiler system will treat it as a normal variable;
#pragma asm, #pragma endasm, and asm can only be used within a function.
Combining assembly language with C51 and giving full play to their respective advantages is undoubtedly the best choice for microcontroller developers.
2.3 Using an oscilloscope to determine the delay time
Use an oscilloscope to measure the execution time of the delay program. The method is as follows: Write a function to implement the delay, set a certain I/O line such as P1.0 to a high level at the beginning of the function, and clear P1.0 to a low level at the end of the function. Call the delay function in a loop in the main program, and use an oscilloscope to measure the high level time on the P1.0 pin to determine the execution time of the delay function. The method is as follows:
sbit T_point = P1^0;
void Dly1ms(void) {
unsigned int i,j;
while (1) {
T_point = 1;
for(i=0;i<2;i ){
for(j=0;j<124;j ){;}
}
T_point = 0;
for(i=0;i<1;i ){
for(j=0;j<124;j ){;}
}
}
}
void main (void) {
Dly1ms();
}
Connect P1.0 to an oscilloscope and run the above program. You can see that the waveform output by P1.0 is a square wave with a period of 3 ms. Among them, the high level is 2 ms and the low level is 1 ms, that is, the execution time of the for loop structure "for(j=0;j<124;j ) {;}" is 1 ms. By changing the number of loops, different delay times can be obtained. Of course, you can also use other statements instead of for loops to achieve delay. What is discussed here is only the method of determining the delay.
2.4 Using the disassembly tool to calculate the delay time
The delay time is calculated using the disassembly tool in Keil C51. In the disassembly window, the target application can be displayed as a mixed code of the source program and the assembler or the assembly code. To illustrate this method, the "for (i=0;i
C:0x000FE4CLRA//1T
C:0x0010FEMOVR6,A//1T
C:0x0011EEMOVA,R6//1T
C:0x0012C3CLRC//1T
C:0x00139FSUBBA,DlyT //1T
C:0x00145003JNCC:0019//2T
C:0x00160E INCR6//1T
C:0x001780F8SJMPC:0011//2T
It can be seen that there are 8 statements from 0x000F to 0x0017. By analyzing the statements, it can be found that not every statement is executed DlyT times. The core loop has only 6 statements from 0x0011 to 0x0017, with a total of 8 machine cycles. The first loop first executes the two statements "CLR A" and "MOV R6, A", which requires 2 machine cycles. Each loop requires 8 machine cycles, but the last loop requires 5 machine cycles. DlyT core loop statements consume (2 DlyT×8 5) machine cycles. When the system uses 12 MHz, the accuracy is 7 μs.
When the while (DlyT--) loop body is used, the value of DlyT is stored in R7. The corresponding assembly code is as follows:
C:0x000FAE07MOVR6, R7//1T
C:0x00111F DECR7//1T
C:0x0012EE MOVA,R6//1T
C:0x001370FAJNZC:000F//2T
The execution time of the loop statement is (DlyT 1) × 5 machine cycles, that is, the delay accuracy of this loop structure is 5 μs.
Through experiments, it is found that if while (DlyT--) is changed to while (--DlyT), the following code is obtained after disassembly:
C:0x0014DFFE DJNZR7,C:0014//2T
It can be seen that at this time there is only one sentence of code, which takes up a total of 2 machine cycles, with an accuracy of 2 μs, and the loop body takes DlyT×2 machine cycles; but it should be noted that the initial value of DlyT cannot be 0.
Note: When calculating the time, you should also add 2 machine cycle times for function calls and function returns.
Part II
Disclaimer: The author is a beginner in single-chip microcomputer programming. In the spirit of exploration, he thoroughly analyzed the delay code, calculated the error, and adjusted it according to the machine cycle occupied by different codes. As for the practical significance of adjusting the time error of about 0.01ms for practical applications, I dare not talk about it. However, after reading the green part of this article, you can clearly understand the design method of the delay program.
Example program paragraph:
;System frequency: 6MHz
Delay: MOV R5,#25; 5ms delay - MOV instruction takes 1 machine cycle time
Delay1: MOV R6,#200; 200ms delay
Delay2: MOV R7,#166; 1ms delay constant
Delay3: NOP; empty instruction, do nothing, stay for 1 machine cycle
DJNZ R7, Delay3; R7 minus 1 is assigned to R7. If R7 is not equal to zero at this time, it will go to Delay3 for execution. ——2 machine cycle time
DJNZ R6,Delay2
DJNZ R5,Delay1
The analysis is as follows:
1. First, calculate the machine period T = 12*1/f = 2μs.
2. Note that DJNZ R7, Delay3 needs to take up 3 machine cycles each time it is executed, including the time of NOP and DJNZ itself. 6μs. So 1ms takes 1ms*1000/6μs=166.67, so take 166.
3. Note that DJNZ R6, Delay2 is executed once after 166 cycles (the time is the MOV machine cycle itself, 3*2=6μs). DJNZ R5, Delay1 is not executed until 166*200 times, when R6=0.
4. DJNZ R5, Delay1 loops back when R5 is not 0. The time is also 6μs.
5. Total time: 166*200*25*6μs 200*25*6μs 25*6μs=5010150μs, totaling 5.01015ms (programmers have encountered similar escape loops. This program ignores the time to execute MOV and only calculates the time taken for the loop, that is, 166*200*25*6/1000000=4.98ms, approximately 5ms).
Program improvements:
Remove the NOP command and integerize the delay constant required for 1ms.
Delay: MOV R5,#25; 5ms delay - MOV instruction takes 1 machine cycle time
Delay1: MOV R6,#200; 200ms delay
Delay2: MOV R7,#250 ;1ms delay constant
Delay3: ;NOP ;Null instruction, do nothing, stay for 1 machine cycle
DJNZ R7, Delay3; R7 minus 1 is assigned to R7. If R7 is not equal to zero at this time, it will go to Delay3 for execution. ——2 machine cycle time
DJNZ R6,Delay2
DJNZ R5,Delay1
At this time, the total time is: 250*200*25*4μs 200*25*6μs 25*6μs=5030150μs. The time occupancy error is larger than that before improvement, so it can be corrected by R7-30150/(25*200*4)=248 (because R7=250 takes 2 machine cycles, 4μs, which is equal to R7-1.5075, reducing the time to less than 5ms, and making up the remaining time, taking 248). So: The total time is: 248*200*25*4μs 200*25*6μs 25*6μs=4990150μs, which needs to be supplemented: 5000000-4990150=9850μs, 9850/2=4925 machine cycles. Adding a MOV R4, #200, 4 NOPs, requires another 4920 machine cycles, which can be reduced to 24*205=4920. How to create a function and adjust it according to the actual code is as follows:
Delay: MOV R5,#25; 5ms delay - MOV instruction takes 1 machine cycle time
Delay1: MOV R6,#200; 200ms delay
Delay2: MOV R7,#250 ;1ms delay constant
Delay3: ;NOP ;Null instruction, do nothing, stay for 1 machine cycle
DJNZ R7, Delay3; R7 minus 1 is assigned to R7. If R7 is not equal to zero at this time, it will go to Delay3 for execution. ——2 machine cycle time
DJNZ R6,Delay2
DJNZ R5,Delay1
NOP
NOP
NOP
NOP
MOV R3, #6
Delayadd: MOV R4,#205
MOV R2, #0H
DJNZ R3,Delayadd
Analysis: 205*24 is adjusted to 205*6. This is because the Delay loop is a 4-machine cycle code, so 24/4=6. Please calculate: 205*6*4=4920;4920 5=4925. The time is added up just right. At this time, the time calculation is: 248*200*25*4μs 200*25*6μs 25*6μs=4990150μs 4925*2μs=5000000μs, a total of 5ms.
Theoretically, it is not worse than 1μs (this is just for scientific discussion, the author is not sure about the specific error of the crystal oscillator frequency).
Previous article:Microcontroller knowledge - structure and related companies
Next article:stm8 series input capture
- Naxin Micro and Xinxian jointly launched the NS800RT series of real-time control MCUs
- How to learn embedded systems based on ARM platform
- Summary of jffs2_scan_eraseblock issues
- Application of SPCOMM Control in Serial Communication of Delphi7.0
- Using TComm component to realize serial communication in Delphi environment
- Bar chart code for embedded development practices
- Embedded Development Learning (10)
- Embedded Development Learning (8)
- Embedded Development Learning (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Intel promotes AI with multi-dimensional efforts in technology, application, and ecology
- ChinaJoy Qualcomm Snapdragon Theme Pavilion takes you to experience the new changes in digital entertainment in the 5G era
- Infineon's latest generation IGBT technology platform enables precise control of speed and position
- Two test methods for LED lighting life
- Don't Let Lightning Induced Surges Scare You
- Application of brushless motor controller ML4425/4426
- Easy identification of LED power supply quality
- World's first integrated photovoltaic solar system completed in Israel
- Sliding window mean filter for avr microcontroller AD conversion
- What does call mean in the detailed explanation of ABB robot programming instructions?
- STMicroelectronics discloses its 2027-2028 financial model and path to achieve its 2030 goals
- 2024 China Automotive Charging and Battery Swapping Ecosystem Conference held in Taiyuan
- State-owned enterprises team up to invest in solid-state battery giant
- The evolution of electronic and electrical architecture is accelerating
- The first! National Automotive Chip Quality Inspection Center established
- BYD releases self-developed automotive chip using 4nm process, with a running score of up to 1.15 million
- GEODNET launches GEO-PULSE, a car GPS navigation device
- Should Chinese car companies develop their own high-computing chips?
- Infineon and Siemens combine embedded automotive software platform with microcontrollers to provide the necessary functions for next-generation SDVs
- Continental launches invisible biometric sensor display to monitor passengers' vital signs
- Please recommend a camera and FPGA development board for image processing
- Design of microstrip antenna using Python and HFSS co-simulation (full text with more than 260 lines of code)
- How to choose GPRS spring antenna?
- Current Output DAC vs. Voltage Output DAC
- Main application characteristics of MCS-51 microcontroller
- Renesas Synergy S1 Series Microcontroller (MCU) R7FS1JA
- [NUCLEO-L552ZE Review] +Serial port printing is finally successful!
- FPGA clean code is a core skill for programmers
- Board-to-board connector manufacturers recommend
- Today at 10:00 am TI Award Live: Low-power wireless technology for building automation sensor applications