cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F103 UART Tx interrupt

nps
Associate II
Posted on February 07, 2015 at 13:30

Hell all,

I have two UARTS connected to two devices (say A and B). Both UARTs Tx and Rx is interrupt based. When I receive a message from A (ASCII-Z string) and the same message is sent to B, I am getting the message twice. Here is the example

1. Message sent by A '':03 21'' (NULL terminated).

2. Message received by B '':03 21<0>03 21''

I checked by sending a different message (not the one received from A), say ''Hello'' and this is transmitted properly to B. I am using two receive and two transmit buffers of sufficient length. Message received from A (A's receive buffer) is copied to B's transmit buffer and to trigger transmission, the first character is sent and thereafter the Tx interrupt sends the all the characters till NULL. I can post code snippets if one has time to spare. What could be the problem? Tx interrupt code is pasted below.

 if (USART_GetITStatus(USART1, USART_IT_TC) == SET )

 {

   if (g8_usrt1_tx_buf[g16v_usrt1_tx_index] != '\0')

       USART_SendData(USART1,g8_usrt1_tx_buf[g16v_usrt1_tx_index++]);

    else

    {

        USART_ClearITPendingBit (USART1, USART_IT_TC);

      g8v_usrt1_tx_progress_flag = 0;

    }

  }

// routine which triggers sending is given below

void start_tran_usrt1 (char *mptr)

{

    while (g8v_usrt1_tx_progress_flag == 1);    // wait here till flag is reset. Remove this statement later

    strcpy (g8_usrt1_tx_buf, mptr);

    g8v_usrt1_tx_progress_falg = 1;

    g16v_usrt1_tx_index = 1;

    USART_SendData(USART1,g8_usrt1_tx_buf[0]);        // trigger for transmission to start

}

#stm32-interrupt-serial-transmit
2 REPLIES 2
Posted on February 07, 2015 at 13:44

Not sure I can see why you get doubles from the code as presented. It always helps when the code is sufficiently complete/concise to get the full picture or evaluate it.

I wouldn't use TC, rather TXE. I'd have the interrupt code be aware that what mode it's in, and not look at the zero byte in a stale string. I'd make sure some of the variables here where 'volatile' so the compiler didn't optimize things out.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
FF1
Associate III

Concerning this matter, to get all working properly in a STEVA-PCC009V2 board (STM32F103RBT6), I had to disable the TX interrupt as the transmission buffer was completely transmitted, otherwise you have the interrupt trigger everytime so my way was (coded in IAR IDE by means of StdPeriph driver):

1- load a previously definited buffer with the data to be transmitted

2- send the first byte of the buffer:

USART_SendData(USART1, (uint16_t)SerialBufferTx[0]);

3- enable the TX interrupt

USART_ITConfig(USART1, USART_IT_TXE, ENABLE);

Inside the interrupt handler you have to check when the tx buffer is fully transmitted and then disable the interrupt in this way you can prevent the continuously interrupt request that are originated because the TX buffer is empty, so:

void USART1_IRQHandler(void)
{
  	uint8_t SerRx = 0;
	
	// Rx IRQ check
	if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET)		// RX buffer not empty                         
	{
	  	USART_ClearITPendingBit(USART1, USART_IT_RXNE); 
		
		SerRx = (0xFF & USART_ReceiveData(USART1)) ;		// Read data from data register
		
		// ... make your stuff with the received byte(s)
	}
	
	// Tx IRQ check USART
	if( USART_GetITStatus(USART1, USART_IT_TXE) == SET )	// TX buffer not empty                         
	{
		uint8_t TxMaxCharToSend = 0;
 
                //  TxMaxChr is a global variable declared as volatile
                //  and is set into the main where I've to transmit data
		TxMaxCharToSend = TxMaxChr;	
		
		// Check if all the bytes inside the txbuffer are transmitted
		if (TxCtr >= TxMaxCharToSend)
		{
		  USART_ClearITPendingBit(USART1, USART_IT_TC);
		  USART_ITConfig(USART1, USART_IT_TXE, DISABLE); // <-- interrupt disable!!
		}
		else
		{
		  // Send one byte
		  USART_SendData(USART1, (uint16_t)SerialBufferTx[TxCtr]);
		  // Update the pointer to the next byte to transmit (at the next interrupt call)
		  TxCtr += 1;
		}
	}
}  

here is my way, may be not optimal but seems able to work nicely, if someone have a different approach please share it.

Thank!

Best regards

Fabio