Accumulating the number of timed interruptions to make the LED light flash -- learning notes of "teach you the program framework of single chip microcomputer by hand - Wu Jianhong"

Keywords: Single-Chip Microcomputer

Disclaimer: This article is my notes on learning "teach you the program framework of single chip microcomputer hand in hand - Wu Jianhong"
Original link: Section 4: accumulate the number of timed interrupts to make the LED light flash.

original text

Section 4: accumulate the number of timed interrupts to make the LED light flash.

Opening remarks:
In the previous section, it is mentioned that the timing is realized by accumulating the number of main cycles. With the increase of the number of tasks in the main function, in order to ensure the accuracy of delay time, the set upper limit threshold const should be continuously modified_ time_ level . How can we solve this problem? This section teaches you to solve this problem by accumulating the number of timed interrupts. This section will teach you four knowledge points:
The first point: the time delay is realized by accumulating the number of timed interrupts
Second point: Show Hongge's most complete practical program framework. In the main function loop, the switch statement is used to switch the state machine, and the interrupt times are accumulated in the timed interrupt. The combination of these two is the most essential framework idea of writing code.
Third point: remind you that int and long variables in C language are data composed of several bytes. For variables that may be changed at the same time in the main function and interrupt function, this variable should close the corresponding interrupt before being changed in the main function, change this variable, and then open the interrupt, otherwise it will leave an imperceptible vulnerability. Of course, this is not necessary in most projects, but in some very demanding projects, some core variables must do so.
The fourth point: how to set the initial value of timing interrupt. There is no need to calculate the time strictly according to the formula. Generally, an empirical value is the maximum initial value minus 1000.
For details, please see the source code explanation.

(1) Hardware platform: Based on Zhu Zhaoqi 51 single chip microcomputer learning board.

(2) Function: let an LED flash.

(3) The source code is explained as follows:

#include "REG52.H"

#define const_time_level 200  

void initial_myself();    
void initial_peripheral();
void delay_long(unsigned int uiDelaylong);
void led_flicker();
void T0_time();  //Timing interrupt function

sbit led_dr=P3^5;  

unsigned char ucLedStep=0; //Step variable
unsigned int  uiTimeCnt=0; //Delay counter for counting the number of timed interrupts


void main() 
{
  initial_myself();  
  delay_long(100);   
  initial_peripheral(); 
  while(1)   
  {
     led_flicker();   
  }

}

void led_flicker() //Zone 3 LED flashing application
{
 
 switch(ucLedStep)
 {
    case 0:
/* Note 1:
* uiTimeCnt Accumulate the number of timed interrupts. Each timed interrupt will add one to the interrupt function.
* Only when its number is greater than or equal to the set upper limit const_time_level,
* Will change the state of the LED, otherwise the CPU will exit the led_flicker() task, continue to quickly scan other tasks,
* This program structure can achieve the purpose of multi task parallel processing. This is the core framework of Hongge in all development projects.
*/
         if(uiTimeCnt>=const_time_level) //Time out
         {

/* Note 2:
* ET0=0;uiTimeCnt=0;ET0=1;----Why prohibit timed interrupts before resetting uiTimeCnt?
* Because uiTimeCnt is of type unsigned int, it is essentially composed of two bytes.
* In C language, uiTimeCnt=0 looks like an instruction. In fact, after compilation, it has more than one assembly instruction.
* Since this variable is also accumulated in the timing interrupt function, if the timing interrupt is not prohibited,
* If the uiTimeCnt variable has not been completely cleared in the main() function
* A timed interrupt occurs suddenly, and this variable is changed in the interrupt. This situation is in some high demand
* There will be an undetectable vulnerability in the project, which will bring hidden dangers to the project. Of course, most ordinary projects,
* Can not be so strict, can not prohibit timed interrupt. Here is just to remind beginners of this situation.
*/
            ET0=0;  //Disable timed interrupt
            uiTimeCnt=0; //Time counter reset
            ET0=1; //Start timing interrupt
            led_dr=1;    //Let the LED light up
                        ucLedStep=1; //Switch to the next step
          }
          break;
    case 1:
          if(uiTimeCnt>=const_time_level) //Time out
          {
            ET0=0;  //Disable timed interrupt
            uiTimeCnt=0; //Time counter reset
            ET0=1;   //Start timing interrupt
            led_dr=0;    //Let the LED go out
            ucLedStep=0; //Return to the previous step
           }
           break;
 
 }

}


/* Note 3:
* C51 The interrupt function format is as follows:
* void Function name () interrupt interrupt number
* {
*    Interrupt program content
* }
* The function name can be taken arbitrarily, as long as it is not a keyword that has been requisitioned by the compiler.
* The key here is the interrupt number. Different interrupt numbers represent different types of interrupts.
* The interrupt number of timed interrupt is 1. As for the interrupt number of other interrupts, you can find it
* Relevant books and materials. When entering the interrupt, you must first clear the interrupt flag and
* Close the interrupt, and then write the code. When it comes out, remember to reinstall the initial value, and
* Open interrupt.
*/
void T0_time() interrupt 1
{
 TF0=0;  //Clear interrupt flag
 TR0=0; //Off interrupt

 if(uiTimeCnt<0xffff)  //Set this condition to prevent uiTimeCnt from going out of range.
 {
     uiTimeCnt++;  //Accumulate the number of timed interrupts,
 }

TH0=0xf8;   //Initial value of reassembly (65535-2000)=63535=0xf82f
TL0=0x2f;
TR0=1;  //Open interrupt
}


void delay_long(unsigned int uiDelayLong)
{
  unsigned int i;
  unsigned int j;
  for(i=0;i<uiDelayLong;i++)
  {
     for(j=0;j<500;j++)  //Number of empty instructions in an embedded loop
         {
            ; //A semicolon is equivalent to executing an empty statement
         }
  }
}


void initial_myself()  //First zone initialization MCU
{

/* Note 4:
* The single chip microcomputer has several timers, and each timer has several working modes,
* We can't remember so many changes. What should we do?
* Remember brother Hong's words, no matter how many built-in resources a single chip microcomputer has,
* We do the system framework, only need a timer, a working mode.
* The more timers you turn on, the worse the system is. What kind of timing is needed?
* You need to reinstall the initial value after responding to the timing interrupt and continue running.
* In 51 single chip microcomputer, it is working mode 1. Other working methods are rarely used in projects.
*/
 TMOD=0x01;  //Set timer 0 to working mode 1


 /* Note 5:
* The initial value of the timer is like the water in a bucket. If this bucket is empty, think about it
* It takes a long time to fill this bucket with water. If there is more than half of the water in it, think about it
* The time to fill this bucket with water is relatively short. That is, the smaller the initial value of the timer, it will be generated once
* The longer the timer interrupt. If the initial value is too small, a timing interrupt is generated each time
* The time resolution of is too coarse. If the initial value is too large, although the time resolution of each timing interrupt is very fine,
* However, too frequent interrupts will not only affect the execution efficiency of the main function, but also accumulate the number of interrupts
* The time error will also be great. With brother Hong's years of Jianghu experience,
* I think the maximum initial value minus 2000 is a better empirical value. Of course, it doesn't matter to be bigger or smaller. Don't go
* Just two extremes.
*/
TH0=0xf8;   //Initial value of reassembly (65535-2000)=63535=0xf82f
TL0=0x2f;

 led_dr=0;  //LED off
}
void initial_peripheral() //The second area initializes the periphery
{
 EA=1;     //On total interrupt
 ET0=1;    //Allow timed interrupt
 TR0=1;    //Start timing interrupt

}

Concluding remarks:
In this section, although sparrows are small, they have all five internal organs. In this section, I have shown my most complete practical program framework.
The program in this section has only one single task with flashing LED light. What should I do if I want to add another task for parallel processing?
For more information, listen to the next chapter - buzzer driver.

(to be continued, the next section is more exciting. Don't go away)

experiment

Using a timer to increase the count value of delay accumulation can ensure the accuracy of delay. Because the function of the program is still LED flashing, the simulation effect is the same as that in the previous two sections:

Posted by gplevritis on Sun, 10 Oct 2021 16:03:48 -0700