C51 Serial Communication - Timing Interrupt Achieves Timeout Receiving Series Data (Recommended)

brief introduction

objective

Implements a series of non-fixed length data receipts and returns the corresponding data (the underlying framework for data analysis)

design idea

  1. With T0 timer, counting + 1
  2. After receiving a frame of data (1Byte), the Serial Interrupt Service function counts the timer T0 to zero (similar to feeding a dog) and creates a counting flag
  3. A frame of data (1Byte) is approximately 1.04ms long [9600bps, 1,0,1]. When the serial interrupt data is received, no valid data is received for a short period of time and enters the interrupt service function, then the T0 counter is not cleared 0, continuously accumulating
  4. When more than a fixed time is continuously detected, a series of data is considered complete at this time.
  5. Fixed time intervals typically set a frame length of 3-5 times (1.04ms)

Code Design

  1. The main function is temporarily processed to return the received string
  2. UART interrupt service function processing:
    Receive a byte, open the T0 counter software flag, clear the counter once (the counter has been + 1 in the T0 timer)
void uart_ISR() interrupt 4
{
	static unsigned int recv_Cnt = 0;
	
	if(RI)
	{
		RI = 0;
		timer_start = 1;			//1. Turn on the T0 software counter to start counting when a frame of data is received
		recv_buf[recv_Cnt] = SBUF;
		recv_Cnt++;		
		if(recv_Cnt >= MAX_LENGTH)		//Exceeded open array protection processing, remaining pinch
		{
			recv_Cnt = MAX_LENGTH;
		}
		ctimer_Cnt = 0;				//3. After receiving a frame of data, clear the T0 count unit to zero, similar to feeding a dog. But T0 has been accumulating
		if(recv_done)				//5. After a series of data transfers is completed, the actual length is output to generate the array recv_buf[], parsed by main function processing
		{
			recv_done = 0;
			cRealLen = recv_Cnt;
			recv_flag = 1;
			recv_Cnt = 0;
			
		}
	}
}
  1. T0 Timer Interrupt Service Function Processing:
    Received a byte data arrival flag from the serial port and started counting + 1. Determine the cumulative number of cycles counted to determine that a series of data has been sent
void Timer0_ISR() interrupt 1
{	
	TR0 = 0;	//Turn off timer first when entering T0 interrupt
	if(timer_start)
	{
		ctimer_Cnt++;					//2. After receiving a frame of data, the timer unit begins counting
//		sendByte(ctimer_Cnt);
		if(ctimer_Cnt > MAX_RECV_TIME)		//4. When a string of data is received, there is no data in the next frame, and ctimer_Cnt has been accumulating,
		{									// When the timer is greater than 3ms and a string of data is considered to have been received, the completion flag is set to 1
			ctimer_Cnt = 0;
			recv_done = 1; 		
		}
	}		
	TL0 = 0x66;		//Loading Initial Value
	TH0 = 0xFC;
	TR0 = 1;		//Turn on timer T0
}
  1. Debugging Test
    If you follow the above code to ma, you will find a problem: Serial port send data error!
    Yes, there is something wrong with the above code!

    4. Logical Analysis
    a. Exceptions are: for each string of data sent, one more frame is returned, and more data happens to be the first byte
    b. Locate the processing within the UART interrupt service function to see that the end processing has an exception and the data is incomplete.
    c. Problem Location: Exit UART interrupt service function after last byte transfer is complete. The timeout is determined by placing a flag at 1 in the T0 interrupt service function to indicate that there is no data in the next frame. However, the UART interrupt service function is not available at this time.
    d. When actually borrowing serial assistant operation, it is the second send that is valid! Buffer recv_found from printf intermediate data Buf[] is constantly refreshed.

    5. Causes of Code Errors
    Individual Habitual Actions - Use the counting variables within the function as local variables and establish markers at the end of conditional judgment. Habitually sets up a prompt flag for the judgment timeout in T0 and returns it to the UART service function for processing, but it does not actually enter.

6. Update Code

void uart_ISR() interrupt 4
{		
	if(RI)
	{
		RI = 0;
		timer_start = 1;			//1. Turn on the T0 software counter to start counting when a frame of data is received
		recv_buf[recv_Cnt] = SBUF;
		recv_Cnt++;		
		if(recv_Cnt >= MAX_LENGTH)		//Exceeded open array protection processing, remaining pinch
		{
			recv_Cnt = MAX_LENGTH;
		}
		ctimer_Cnt = 0;				//3. After receiving a frame of data, clear the T0 count unit to zero, similar to feeding a dog. But T0 has been accumulating	
	}
}
void Timer0_ISR() interrupt 1
{	
	TR0 = 0;	//Turn off timer first when entering T0 interrupt
	if(timer_start)
	{
		ctimer_Cnt++;					//2. After receiving a frame of data, the timer unit begins counting
		if(ctimer_Cnt > MAX_RECV_TIME)		//4. When a string of data is received, there is no data in the next frame, and ctimer_Cnt has been accumulating,
		{									// When the timer is greater than 3ms and a string of data is considered to have been received, the completion flag is set to 1
			ctimer_Cnt = 0;			
			recv_flag = 1;
			cRealLen = recv_Cnt;	//5. After a series of data transfers is completed, the actual length is output to generate the array recv_buf[], parsed by main function processing				
			recv_Cnt = 0;					
		}
	}		
	TL0 = 0x66;		//Loading Initial Value
	TH0 = 0xFC;
	TR0 = 1;		//Turn on timer T0
}

@@@@Here's a question: About writing data beyond a given memory region:

if(recv_flag)
		{
			recv_flag = 0;
			timer_start = 0;		//Turn off the timer to prevent T0 from executing all the time
			for(i = 0; i < cRealLen; i++)
			{
				P1 = 0xFF;
				recv_buf[i] += 1;
				sendByte(recv_buf[i]);
				cLedDis = _crol_(0xFE,i);
				P1 &= cLedDis;
				set_buzz(BUZZ_TYPE1);
				Delay_xms(1000);
			}
			
//			sendString(recv_buf); 	// Return All
			clr_recvbuffer(recv_buf);

For example, the code block for my main function while(1) in the figure above.

  1. If the function sendString() is called directly, it exceeds MAX_immediately LENGTH, this string can still be returned to the serial port completely.
  2. If the upper bound of the array range is assigned to cRealLen, the data returned to the serial port after the main function is executed has only the contents of the open area.

    Analysis:
    1. The buffer register SBUF passes a complete string, and when writing to the array, characters that exceed the array space are stored in a continuous memory address.
    2. The function sendString() is a parameter which is a pointer variable. When a pointer array is used as a parameter, the function name is actually substituted with the array's first address, element 0
    3. Continuous storage of excess characters.
void sendString(unsigned char *dat)

summary

1. "Timing interrupt + timeout reception", which has strong versatility, is recommended.
2. Be cautious about inertial thinking. Function module locations for local and global variable processing are important
2. The next chapter describes how to use header detection step by step --> Receive and parse user-defined protocols, from simple to deep.

Tags: C Single-Chip Microcomputer

Posted on Tue, 23 Nov 2021 01:03:18 -0500 by DjNaF