#C51 serial communication 4-# a string of data # interrupt real-time analysis user-defined protocol (handshake receiving response)

Catalogue of series articles

Tip: you can add the directories of all articles in the series here. You need to add the directories manually
For example, the first chapter is the use of pandas, an introduction to Python machine learning

Tip: after writing the article, the directory can be generated automatically. For how to generate it, please refer to the help document on the right

preface

Tips:
1. The previous chapter tested a method: using serial port interrupt to receive data in real time under simple protocol and analyze it after verification.
2. During actual project development, after the host sends a command, the slave first shakes hands for confirmation, and responds accordingly in case of data error (such as error command).
3. This chapter continues to enrich the development and increase the master-slave response mechanism

Tip: the following is the main content of this article. The following cases can be used for reference

1, Scene

Example:
The host sends a command, the slave analyzes and answers the interrupt, and the main function handles the event

2, Programming implementation

1. Custom agreement

For example:

Frame headeraddressdata typeData lengthData areacheck
AA66AA/01~03Sum check & & XOR check

##Host type defines the command type (query, setting, device control, etc.)
Take the control nixie tube display 0x01 as an example

##Slave handshake response:
a. Correct data reply: AA66AA8000[SUM_CHECK][XOR_CHECK]
b. Sum check error reply: AA66AA8100[SUM_CHECK][XOR_CHECK]
c. XOR check error reply: AA66AA8200[SUM_CHECK][XOR_CHECK]

The value in the data area is displayed on the nixie tube, for example, only the maximum two groups are displayed

2. Code design

Step 1: confirm that a string of data is correctly received and returned based on the debugged project

Step 2: configure UART interrupt service function:
1. Judge the frame header 2. Confirm the data length 3. Data cache 4. Check and judge 5. Reply: correct or error prompt

void uart_ISR() interrupt 4
{	
	UC i;
	if(RI)
	{
		RI = 0;
		
		//Timeout receiving processing scheme
//		timer_start = 1;
//		recv_buf[recv_Cnt] = SBUF;
//		recv_Cnt++;
//		ctimer_Cnt = 0;

		//Interrupt immediate resolution processing scheme
		recv_data = SBUF;	
		switch(machine_step)
		{
			case 0:
				if(0xAA == recv_data)		//1. The frame header is consistent, and the status is + 1. Continue to detect after the next interrupt enters, otherwise it will be discarded
				{
					machine_step = 1;		
				}
				else
				{
					machine_step = 0;
				}
				break;
			case 1:
				if(0x66 == recv_data)
				{
					machine_step = 2;
				}
				else
				{
					machine_step = 0;
				}
				break;
			case 2:
				if(0xAA == recv_data)
				{
					machine_step = 3;
					recv_Cnt = 0;			//2. About to enter the data area, count is started
				}
				else
				{
					machine_step = 0;
				}
				break;
			case 3:
				sum_check = recv_data;
				xor_check = recv_data;
				recv_buf[recv_Cnt] = recv_data;	//3. Data type, save the first number
				machine_step = 4;
				break;
			case 4:
				data_length = recv_data;	//	Data length				
				sum_check += recv_data;
				xor_check ^= recv_data;
				recv_Cnt++;
				recv_buf[recv_Cnt] = recv_data; 
				machine_step = 5;
				break;
			case 5:
				sum_check += recv_data;
				xor_check ^= recv_data;
				recv_Cnt++;
				recv_buf[recv_Cnt] = recv_data;
				if(data_length < recv_Cnt)			//When not satisfied, it is still state 5
				{
					machine_step = 6;
				}				
				break;
			case 6:
				if(sum_check == recv_data)	//5. Verification judgment / / recv_data is already a new byte,
				{
					machine_step = 7;	
				}
				else
				{
					machine_step = 0;			//Sum up the errors and start judging again next time
					sum_check = 0;				//Verify that 0 is cleared, otherwise an error occurs in the next string of data in state 3
					xor_check = 0;	
					
					//7. Receive response: sum verification error prompt  
					for(i = 0; i<7; i++)
					{
						sendByte(sum_check_error[i]);
					}
					
				}
				break;
			case 7:
				if(xor_check == recv_data)		
				{
					recv_flag = 1;			//6. The data is correct and the flag is set to 1			
					cRealLen = recv_Cnt + 1;		//Buffer length (data type + data length + data area)

					//7. Receive response: correct reception
					for(i = 0; i<7; i++)
					{
						sendByte(recv_correct[i]);
					}
				}
				else
				{
					machine_step = 0;			//XOR check error, restart judgment next time

					//8. Receive response: XOR check error prompt
					for(i = 0; i<7; i++)
					{
						sendByte(xor_check_error[i]);
					}
				}
				sum_check = 0;				//Verify that 0 is cleared, otherwise an error occurs in the next string of data in state 3
				xor_check = 0;	
				machine_step = 0;			//++Remember to clear 0 somewhere	
				recv_Cnt = 0;				//It's ok to be unclear. Form a habit and clear it
				break;				
				
			default:break;
		}
		
	}
}

Among them, for the convenience of demonstration, the response prompts to allocate ROM constants in advance:

unsigned char code recv_correct[] = {0xBB,0x66,0xBB,0x80,0x00,0x80,0x80};
unsigned char code sum_check_error[] = {0xBB,0x66,0xBB,0x81,0x00,0x81,0x81};
unsigned char code xor_check_error[] = {0xBB,0x66,0xBB,0x82,0x00,0x82,0x82};

Step 3: main function processing:
Buffer data: data type + data length + data area
Function: the value in the data area is displayed on the nixie tube in hexadecimal

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++)
		{
			uart_Recv[i] = vbuf[i];
		}	
//		sendString(vbuf); //test
		sendString(uart_Recv);
		Exchange_Func();
		
		clr_recvbuffer(vbuf);		
	}
void Exchange_Func(void)
{
	if(0x01 == uart_Recv[0])		//For demonstration only, data type 01 controls nixie tube display
	{
		switch(uart_Recv[1])		//The data length represents the number of digits displayed
		{
			case 1:
				SEG_DisBuf[0] = 23;
				SEG_DisBuf[1] = 23; 		
				SEG_DisBuf[2] = uart_Recv[2] >> 4;
				SEG_DisBuf[3] = uart_Recv[2] & 0x0F;
				break;
			case 2:
				SEG_DisBuf[0] = uart_Recv[2] >> 4;
				SEG_DisBuf[1] = uart_Recv[2] & 0x0F; 	
				SEG_DisBuf[2] = uart_Recv[3] >> 4;
				SEG_DisBuf[3] = uart_Recv[3] & 0x0F;
				break;
			case 3:
				break;
			default:break;
		}
	}

3. Test verification

Measured ok

summary

1. limited to the non emulator, so in the UART interrupt service function debugging, insert a few sendByte (), facilitate observation to which step. It is found that the data is disordered because when a frame of data overflows into the service function, the called sendByte() enters the function again, and the data is overwritten.
2. The example is for convenience of demonstration. In practice, the flag bit can be set for the processing of receiving response, which is processed in the main function, and the interrupt service function works as little as possible.
3. Compared with the previous chapter, the example has the advantages of not limiting the data length and receiving and response mechanism

Previous chapter: #C51 serial communication 3-# a string of data # interrupt real-time analysis user-defined protocol (fixed length)

Posted by jordz on Thu, 02 Dec 2021 13:17:58 -0800