cancel
Showing results for 
Search instead for 
Did you mean: 

After UART send the bytes from the buffer, \0 is also received.

RPG
Senior

Why I get \0 at the end of the transmission?

I imaging the \0 is a NUL termination character but I have seen from the terminal that sometimes is not received or arrives with a big delay.

Could somebody tell me anything about it?

Thanks in advance.

25 REPLIES 25

Are you sure that's due to the microcontroller sending, or is it the way your Python receives?

This is always the trouble when trying to develop both ends of a link at the same time - you never know whether problems are due to one end of the link, or the other, or both!

You have too many unknowns all at once!

I'd suggest taking Python out of the equation, and just using a terminal app to see what's being sent.

Better still, if you have one, an analyser on the microcontroller's output.

"I am quite new"

New to what, exactly?

You said this code was inherited from a "previous developer" - can you contact her?

Do you have colleagues or tutors who can help you with this?

Trying to debug stuff remotely is very hard, especially when we have no idea what you have, or what you're doing - someone local would be far more effective

From the terminal is working the same way. So, don't think is Python.

I am quite new to embedded programming.

No I am unfortunately alone. But thank you for the support so far and the effort you put on it.

@Raúl Pérez Gómez​  "From the terminal is working the same way"

What terminal are you using?

Please give a fuller description of exactly what happens.

Screenshots might help.

perhaps take a few steps back to just a simple, basic application which sends strings through the UART?

Or maybe go back to the original scheme - with disabling the transmitter - and just make your Python tolerant of receiving a NUL at the end of the transmission?

(I'd guess that the PC would see a Framing error on that NUL? does Python give you access to that?)

This is the original code for receiving/sending the data (without disabling the TX):

/**
  * @brief This function handles USART1 global interrupt / USART1 wake-up interrupt through EXTI line 25.
  */
void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */
	//check if RXNE interrupt
	if(USART1->ISR & USART_ISR_RXNE) //if RX is not empty
	{
		// Reset timer 15
		TIM15->CNT = 0;
 
		// Check if first byte
		if(!USART1_receiving)
		{
			USART1_receiving = 1;			// Receiving data
			usartReceiveMessageLength = 0;	// Reset message length
			TIM15->CR1 |= (TIM_CR1_CEN);	// Enable timer 15
		}
 
		//fetch the data received
		USART1_ReceiveBuffer[usartReceiveBufferPointer++] = USART1->RDR;
		usartReceiveMessageLength++; // Increment message length
 
		// Reset buffer pointer if overflow
		if(usartReceiveBufferPointer >= usartReceiveBufferLength)
			usartReceiveBufferPointer = 0;
	}
 
	//check if TXE interrupt
	if(USART1->ISR & USART_ISR_TXE) //if TX is empty
	{
		// Check if first byte
		if(!USART1_transmitting)
		{
			USART1_transmitting = 1;		// Transmitting data
			USART1_transmitDataPointer = 0;	// Reset transmit pointer
		}
 
		// Transmit RS422 buffer
		if(USART1_transmitDataPointer < USART1_transmitDataLength)
			USART1->TDR = COM_TransmitBuffer[USART1_transmitDataPointer++];
		else
			__HAL_UART_DISABLE_IT(&huart1, UART_IT_TXE);
	}
 
	// Check if TC interrupt
	if(USART1->ISR & USART_ISR_TC)
	{
		USART1_transmitting = 0;					// Done transmitting data
		__HAL_UART_DISABLE_IT(&huart1, UART_IT_TC);	// Disable flag
		USART1->CR1 &= ~USART_CR1_TE;				// Disable transmitter
		USART1->ICR |= USART_ICR_TCCF;				// Reset flag
	}
  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */
 
  /* USER CODE END USART1_IRQn 1 */
}

This is the code to start the transmission:

// Start transmission
		if(global_Configuration.responseMessageEnable)
		{
			__HAL_UART_ENABLE_IT(&huart1, UART_IT_TXE);
			__HAL_UART_ENABLE_IT(&huart1, UART_IT_TC);
			USART1->CR1 |= USART_CR1_TE;
		}

When I send a command from the terminal I get the response back. But there are \0 bytes represented by '.' in the terminal.

That's not intended to be there. See the picture below:

0693W00000QKg0MQAT.pngWhen I send a second command it looks also right but the \0 bytes still there:

0693W00000QKg2XQAT.png 

When I comment the line:

USART1->CR1 &= ~USART_CR1_TE; // Disable transmitter

The dot is not appearing but the commands response is not working find as you can see from the picture:

0693W00000QKg5HQAT.png 

I have looked at the content of COM_TransmitBuffer with live expressions and it shows the right content and not the mixed up. So, that's not the problem. And the \0 are not part of COM_TransmitBuffer.

If I try with another command is even more evident. Is like the first 6/7 bytes are still coming from the previous command response.

This is the init method for USART1:

void MX_USART1_UART_Init(void)
{
 
  /* USER CODE BEGIN USART1_Init 0 */
 
  /* USER CODE END USART1_Init 0 */
 
  /* USER CODE BEGIN USART1_Init 1 */
 
  /* USER CODE END USART1_Init 1 */
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 19200;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_ENABLE;
  huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
  huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_RXOVERRUNDISABLE_INIT|UART_ADVFEATURE_DMADISABLEONERROR_INIT;
  huart1.AdvancedInit.OverrunDisable = UART_ADVFEATURE_OVERRUN_DISABLE;
  huart1.AdvancedInit.DMADisableonRxError = UART_ADVFEATURE_DMA_DISABLEONRXERROR;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_DisableFifoMode(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART1_Init 2 */
 
  /* USER CODE END USART1_Init 2 */
 
}

I have found this but cannot find how to set that bit into 0:

Section 27.3.1 of the STM32F1 reference manual says:

"A Break character is interpreted on receiving “0�?s for a frame period. At the end of the break frame the transmitter inserts either 1 or 2 stop bits (logic “1�? bit) to acknowledge the start bit."

Further down in 27.3.2 Break Characters it says

"Setting the SBK bit transmits a break character. The break frame length depends on the M bit (see Figure 279).

If the SBK bit is set to ‘1’ a break character is sent on the TX line after completing the current character transmission. This bit is reset by hardware when the break character is completed (during the stop bit of the break character). The USART inserts a logic 1 bit at the end of the last break frame to guarantee the recognition of the start bit of the next frame."

That's something different.

This is not about Break "characters" - this is about how the PC interprets the line going off when you disable the transmitter.

what could be a solution for that?

Piranha
Chief II

Probably the receiver has no pull-up on it's Rx line and, when the MCU releases the Tx pin, the whole line is floating. If the line goes low, such a situation could be interpreted as a start bit + 0x00 data byte. You can test/solve it by enabling a pull-up on MCU's Tx pin.

And yes - you need to understand why the original code disabled the transmitter at all.