As we can see in the previous article, using a for loop to delay in the DelayX10us() function will produce a fixed error of 10 machine cycles, of which X passing the value, calling the function, and the sub-function returning a total of 5 machine cycles, which is a fixed error for any call to a sub-function with parameters. The for loop determines that x>0 and jumps to produce an additional error of 5 machine cycles.
improve
According to the content mentioned in "Designing Accurate Delay Functions in the Microcontroller Keil C Development Environment", the for loop can be changed to while(--x) to eliminate the extra 5 machine cycle errors caused by the for loop.
Note: You should use while(--x) so that the corresponding generated assembly statement is DJNZ. If you use while(x--), several extra instructions will be generated, making this delay function inaccurate.
The modified procedure is as follows:
//Inaccurate delay 10*X us, fixed error 5us
//@12.000MHz 12T
void DelayX10us(unsigned char x)
{
unsigned char i;
do
{
_nop_();
i=3;
while(--i);
} while (--x);
}
Disassembly analysis
As before, using the optimization level 8, the disassembled code is as follows:
Calculate the delay time:
x | Fixed delay | Loop Delay | total |
1 | 5 | (1+1+2*3+2)*1 | 15 |
10 | 5 | (1+1+2*3+2)*10 | 105 |
100 | 5 | (1+1+2*3+2)*100 | 1005 |
It can be seen that the error has been reduced to 5us.
Official millisecond-level delay analysis
For the improved DelayX10us function, the maximum value of X is 255, so its maximum delay is 255*10=2550us=2.55ms. What if you want to get a longer delay? It should be noted here that you cannot simply change X to unsigned int to get a longer delay, because 8051 is an 8-bit microcontroller. For the 16-bit int type, it needs to be divided into high 8 bits and low 8 bits for operation, and the sentence "while(--x);" will not only take 2 machine cycles. So we redefine a millisecond delay function. The official STC delay 1ms program is as follows:
//@12.000MHz, STC official version
void Delay1ms() //No machine cycle is assigned here
{
unsigned char i, j;
i = 2;
j = 239; //Please note the position of j assignment
do
{
while (--j);
} while (--i);
}
According to the previous method, the number of delay cycles t = function call LCALL + ij assignment + loop + return RET = 2 + 1+1+(239*2+2)*2 +2= 966 [Thanks to group member Smiles for pointing out the 2 omitted assignment cycles]. It is quite different from the expected 1000 machine cycles. Why?
It should be noted that the variable j is assigned a value outside the loop. When the outer loop is executed for the second time (i=1), j will not be assigned a value of 239, so 239*2 cannot be used for calculation. Here, a trick of overflow is used. The simple analysis process is as follows:
After i=2, j=239 is assigned (2 machine cycles), it enters the inner loop and executes "while(--j);" 239 times, j=0, and then exits. From the previous analysis, we know that the assembly code of "while(--j);" is DJNZ instruction, which is a 2-cycle instruction, and the number of cycles is t1=2+239*2.
Then it executes to the outer loop "while(--i);", 2 machine cycles, i=1, DJNZ instruction jumps to the inner loop to continue execution, cycle number t2=2.
After entering the inner loop again, j=0. The DJNZ command first decrements the register by 1 and then determines whether it is 0. Therefore, after executing --j, j overflows to 0xFF (decimal 255), which is not equal to 0. The statement "while(--j);" continues to execute until j is decremented to 0 again and then jumps out. The number of cycles t3=256*2.
Go to the outer loop again, "while(--i);", i=0, jump to the end of the function and prepare to return. Cycle number t4=2.
The number of function call and return cycles is t5 = 2 + 2. There is no parameter passing when calling the function, so there is no assignment cycle.
The total number of cycles t=t1+t2+t3+t4+t5=2+239*2+2+256*2+2+4=1000. Just right!
Millisecond delay function transformation
Now we transform the official function that can only delay 1ms into one that can delay multiple ms. According to the previous method, we put a do..while loop in the delay code.
do
{
i = 2; j = 239;
do { while (--j); }
while (--i); }
while (--x);
At this time, the number of delayed machine cycles = 1+2+(2+239*2+2+256*2+2+2)*X+2=998*X+5, and the multiple is not 1000, so there is an error. When x=1, t=1003; when x=10, t=9985; when x=100, t=99805, there is an error of nearly 200us, so we change the machine cycle in the brackets to 1000, and just change j=240, so that the total number of cycles T=1+2+(2+240*2+2+256*2+2+2)*X+2=1000*X+5, with a fixed error of 5us. The modified code is as follows:
/**
* Crystal oscillator 12MHz, delay 1*x ms in 12T mode, fixed error 5us.
*/
void DelayX1ms(unsigned char x)
{
unsigned char i, j;
do
{
i = 2;
j = 240;
do
{
while (--j);
} while (--i);
} while (--x);
}
By following this model, you can write any delay program with a fixed error of 5us.
In addition, for a delay of a few microseconds, it is recommended to use _nop_() delay. Considering portability, it is not recommended to write multiple _nop_() directly in the program to delay. Write all delay functions in Delay.h and Delay.c files, and the rest of the program will all call this library. If you need to change it later, such as changing to STC's 1T microcontroller, the delay needs to be modified, and you only need to change these two files.
Finally, attached is the delay function library I am using. The fixed error of all X times delay = 5us.
#ifndef __DELAY_H__
#define __DELAY_H__
typedef unsigned char UINT8
//Define default settings: crystal 12MHz, mode 12T
#define FSOC_12M_MOD_12T
/**
* Crystal oscillator 12MHz, delay in 12T mode.
*/
#ifdef FSOC_12M_MOD_12T
#define NOP() _nop_()
#define Delay1us() NOP()
#define Delay2us() NOP();NOP()
#define Delay5us() NOP();NOP();NOP();NOP();NOP()
#endif
void DelayX10us(UINT8 X);
void DelayX1ms(UINT8 X);
void DelayX10ms(UINT8 X);
void DelayX1s(UINT8 X);
#endif
/**
*************************************************** **********
****** Copyright(C), 2010-2016, NULL Co.,Ltd ******
*************************************************** **********
*@Tittle: General delay function
*@Version : v1.1
*@Author : Liy
*@Dat: 2016-08-10 15:03:15
*@Desctription: Delay function library
*@History:
* #v1.1 2016-08-10 15:03:41
* 1. Delete the fixed delay function and only keep the X times delay;
* 2. Optimize the time of X-times delay function, and control the error of all X-times delay functions to 5us.
* #v1.0 2016-08-03 16:44:18
* 1. Complete the commonly used delay functions in 12MHz and 12T modes
*************************************************** **********
*************************************************** **********
*/
#include "Delay.h"
/**
* Crystal oscillator 12MHz, delay in 12T mode
*/
#ifdef FSOC_12M_MOD_12T
/**
* Crystal oscillator 12MHz, delay 10*X us in 12T mode, fixed error 5us.
* X maximum value 255
*/
void DelayX10us(UINT8 X)
{
UINT8 i;
do
{
_nop_();
i = 3;
while (--i);
} while (--X);
}
/**
* Crystal oscillator 12MHz, delay 1*X ms in 12T mode, fixed error 5us.
* X maximum value 255
*/
void DelayX1ms(UINT8 X)
{
UINT8 i, j;
do
{
i = 2;
j = 240;
do
{
while (--j);
} while (--i);
} while (--X);
}
/**
* Crystal oscillator 12MHz, delay 10*X ms in 12T mode, fixed error 5us.
* Number of cycles N=((2+(114*2+2)+(256*2+2)*19+2))*X+5
* X maximum value 255
*/
void DelayX10ms(UINT8 X)
{
UINT8 i, j;
do
{
i = 20;
j = 114;
do
{
while (--j);
} while (--i);
} while (--X);
}
/**
* Crystal oscillator 12MHz, delay 10*X s in 12T mode, fixed error 5us.
* Number of cycles N=(1+3+(((123*2+2)*1+(256*2+2)*153) +2 ) + ((256*2+2)*256+2)*7+2)*X+5
* X maximum value 255
*/
void DelayX1s(UINT8 X)
{
UINT8 i, j, k;
do
{
NOP();
i = 8;
j = 154;
k = 123;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
} while (--X);
}
#endif
OK, now that I have a brief understanding of assembly and the software delay is basically accurate, that’s it.
Previous article:Universal infrared remote control signal analysis program based on STC12 series microcontroller (I)
Next article:Research on 8051 Series MCU Software Precision Delay (Part 1)
- Popular Resources
- Popular amplifiers
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- CGD and Qorvo to jointly revolutionize motor control solutions
- CGD and Qorvo to jointly revolutionize motor control solutions
- Keysight Technologies FieldFox handheld analyzer with VDI spread spectrum module to achieve millimeter wave analysis function
- Infineon's PASCO2V15 XENSIV PAS CO2 5V Sensor Now Available at Mouser for Accurate CO2 Level Measurement
- Advanced gameplay, Harting takes your PCB board connection to a new level!
- Advanced gameplay, Harting takes your PCB board connection to a new level!
- A new chapter in Great Wall Motors R&D: solid-state battery technology leads the future
- Naxin Micro provides full-scenario GaN driver IC solutions
- Interpreting Huawei’s new solid-state battery patent, will it challenge CATL in 2030?
- Are pure electric/plug-in hybrid vehicles going crazy? A Chinese company has launched the world's first -40℃ dischargeable hybrid battery that is not afraid of cold
- EEWORLD University - Basic Knowledge of Welding
- micropython update: 2020.4
- [Fudan Micro FM33LG0 Series Development Board Review] Fudan Microchip uses J-Scope waveform software to accelerate product development
- How to make a circle of vias regularly?
- Boost and buck-boost DC-DC converters help wireless charging designs
- I never dared to think about not adding return vias before!
- [Power amplifier case] Do you know what a nanogenerator is? High voltage and wireless drive applications of LEDs in capacitors
- RFID Principle
- Please help me analyze the circuit diagram
- Common filter circuits