8-bit single-chip microcomputer handles the problem of 16-bit data error--2020.10.23

The main control chip used in the recent project is an 8-bit MCU, but after writing 3 lines of code, an unsolvable bug appeared, and the instructor told me that the engineer who went to Huawei before also encountered this He doesn't know exactly how to solve the problem, well, he can only rely on himself. First, let me tell you that there is no problem with the initial configuration, but I have been looking for a bug in these 3 lines of code for a week. Not much nonsense, here is the code.

unsigned short int time_count = 0;
int main()
{
    
    	
	tim0_init();/* 5ms定时器初始化 */
	uart1_init();/* 串口1初始化 */
	printf("uart init ok!\r\n");
	while(1)
	{
    
    
		if(time_count >= 400)
		{
    
    	
			time_count = 0;
			printf("time is end!\r\n");/* 时间到了 */
		}
	}
}
void tim0_isr() interrupt 1/* 5ms定时器中断 */
{
    
    
	time_count++;
}

The code is very simple. A 16-bit variable is defined, which is added in the 5Ms timer interrupt. When this variable is greater than or equal to 400, that is, 2S, the time is up through the serial port printout.

However, please note that in the actual test, it is found that occasionally, occasionally, there is no regularity. After this count reaches 256, the printout time is up, and the number of occurrences is random, without any regularity.

I was stunned for an instant, there is a problem with this code? After learning C for so many years, have you fed the dog? For an instant, I was in a daze, so I asked others for advice. After a lot of thinking and tossing for a whole morning, they couldn't solve it. I can’t find it even on Baidu, but I found a lot of "Do you believe in metaphysics?" I am a three-good boy who advocates science. I don't believe it is really the so-called metaphysics. I believe that as long as you learn deeply, you can solve it.

After constant thinking and searching for information on the Internet, I contacted the manufacturer and finally found the problem.

Because it uses an 8-bit single-chip microcomputer, 8-bit, as the name suggests, one instruction cycle CPU can only process 8-bit data, in the code I defined a 16-bit variable, that is to say, when operating this variable, two Each instruction cycle, but after the end of each instruction cycle, the cpu will determine whether an interrupt is generated, so as to respond to the interrupt event.

The problem lies here. If an interrupt happens to occur when operating this 16-bit variable, there may be a problem. Well, if the direction of the problem is clarified, it is easier to find it. In the main function, the if condition is used to judge, and count_time >= 400; the general compiler basically adopts the form of difference for if condition judgment, that is, judge whether count_time-400 is greater than 0, and the condition is true, then it is established. Since the variable is 16 bits, an 8-bit CPU requires two instruction cycles, that is, twice to determine it.

For the first time, use the low 8 bits of the variable count_time-the low 8 bits of 400, and the low 8 bits of 400 are (0b10010000). If the timer interrupt comes at this time, then respond to the interrupt event and add the variable count_time. If before the interrupt comes, the value of the variable count_time is 255, that is (0b11111111), then after entering the interrupt, this number will change For 256, that is (0b00000001 00000000), a high-order carry is generated. After the interrupt processing is over, continue to go back and process the main function. Since the lower 8 bits were judged last time, the higher 8 bits were judged this time. Because of the carry, the upper 8 bits of the variable are 1, and it happens that the upper 8 bits of 400 are also 1. Then it is judged that these two numbers are equal, and this if condition is established.

Some friends here may ask, why do we need to judge the lower 8 bits first? If the upper 8 bits are judged first, then this problem will not occur, this is related to the compiler, because the storage mode adopted by the 51 microcontroller It is big-endian mode, that is, the high-order data is stored in the high-order address. When fetching data from the starting address of this variable, the data at the lower address is first fetched, that is, the lower byte of the variable, so the lower 8 bits are judged first.

The problem has been found so far, it is easier to solve it, the code is as follows:

int main()
{
    
     
 unsigned short int time = 0;
 tim0_init();/* 5ms定时器初始化 */
 uart1_init();/* 串口1初始化 */
 printf("uart init ok!\r\n");
 while(1)
 {
    
    
  time = time_count;
  if(time == time_count)
  {
    
    
	if(time >= 400)
	 {
    
       
	    time_count = 0;   
	    printf("time is end!\r\n");/* 时间到了 */
	 }
  }
 }
}

This is fine, first assign this value to a temporary variable, and then determine whether the two values ​​are equal. The purpose of the judgment is to prevent a carry after the assignment. If it does, then the two numbers are not equal , The condition is not established, waiting for the next cycle to come, it will be equal, because the timer interrupt has just occurred, and will not immediately enter the interrupt, so this can solve the situation that the time does not reach 2s and enters.

So far, the problem is solved. Therefore, we still have to believe in science. The so-called metaphysics in our mouth is nothing but ignorance, haha.

If there is any error, please correct me in time, thank you!

Guess you like

Origin blog.csdn.net/weixin_42952614/article/details/109251285