Data coverage problem when serial port uses DMA to send data

        In STM32 and other single-chip microcomputers, in order to improve the execution efficiency of the program, when using the serial port, DMA is often used to send and receive data. In this way, the CPU only needs to put the data in the send buffer area to leave.

        However, since a reference call is used in serial port transmission, that is, when data is transmitted, the pointer to be sent is passed, rather than a copy of the data. The advantage of this is convenience and speed, but at the same time, when the data has not been sent, the next string of data cannot be put into the sending buffer, otherwise, the data coverage problem will occur, that is, the latter The string data covers the data that has not been sent before.

        This kind of data coverage problem generally occurs when two or more strings of data are continuously sent, and the first one has not been sent yet, and the latter one will overwrite the previous data.

        If it is judged before each transmission whether the last data has been sent or not, if it is not sent and waited, the efficiency of the CPU will be reduced; or, if the delay is used before or after each serial port sending function, then Such a problem can be solved, but if it does, then there is no point in using DMA.

        So in order to solve this problem, I thought of a way to create a double buffer, and paste the code directly:

void SendDataToPrinter(uint8_t* pData, uint16_t dataLen)
{
    uint8_t ret = 0;
	static uint8_t num = 0;
	static uint8_t buffer1[256] = {"\r\n"};
	static uint8_t buffer2[256] = {0};
	
    / / When using DMA to send, establish a double buffer to send alternately to prevent data overwriting
	if(num == 0)
	{
		ret = DMA_USART1_Transmit(buffer1, strlen((const char*)buffer1));
		if (ret == 0)
		{
			num++;
			memset(buffer2, 0, sizeof(buffer2));
			strcat((char*)buffer2, (char*)pData);
		}
		else
		{
			strcat((char*)buffer1, (char*)pData);
		}
	}
	else
	{
		ret = DMA_USART1_Transmit(buffer2, strlen((const char*)buffer2));
		if (ret == 0)
		{
			on one--;
			memset(buffer1, 0, sizeof(buffer1));
			strcat((char*)buffer1, (char*)pData);
		}
		else
		{
			strcat((char*)buffer2, (char*)pData);
		}
	}
    
}

       In the above code, the function SendData() is an external call, and the parameters are the string to be sent and the length of the data to be sent. The function DMA_USART1_Transmit() is the real transmission function. In this function, it will return 0 if the transmission is successful. If there is data currently being sent, it will return 1, and the other return is the transmission error.

        The idea of ​​this part of the code is, when sending, first send the data in buffer1, when sending the data of buffer1, then the data that needs to be sent are stored in buffer2, when the sending of buffer1 is completed, the data of buffer2 is sent, At this time, all the data passed in are stored in buffer1. In this way, the data coverage problem of the single buffer can be effectively solved by using the alternate sending method and using the double buffer.






Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326912105&siteId=291194637