Summary of MCU delay methods

Publisher:平凡幸福Latest update time:2018-10-10 Source: eefocus Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

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).


Reference address:Summary of MCU delay methods

Previous article:Microcontroller knowledge - structure and related companies
Next article:stm8 series input capture

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号