Skip to main content
d_steffen
Associate II
November 5, 2008
Question

UART TX finished interrupt needed

  • November 5, 2008
  • 12 replies
  • 2647 views
Posted on November 05, 2008 at 22:02

UART TX finished interrupt needed

This topic has been closed for replies.

12 replies

d_steffen
d_steffenAuthor
Associate II
May 17, 2011
Posted on May 17, 2011 at 09:45

I use uart interrupt and uart hardware fifo based transmitting and

receiving on the ST912FW44.

How can I get the information (an interrupt), if the

uart transmit (hw fifo used) finished, after the the last

byte is sended on the port pin output including the stop bit(s) ?

andy_ry
Associate
May 17, 2011
Posted on May 17, 2011 at 09:45

Hi! Try to use this:

while(UART_GetFlagStatus(UART0, UART_FLAG_Busy));

& RTFM!!!

BUSY: UART Busy

If this bit is set to 1, the UART is busy transmitting data. This bit remains set until the complete byte, including all the stop bits, has been sent from the shift register. This bit is set as soon as the transmit FIFO becomes non-empty (regardless of whether the UART is enabled or not).

UM0216 page 264

d_steffen
d_steffenAuthor
Associate II
May 17, 2011
Posted on May 17, 2011 at 09:45

I think you don't understand my question in

case of transmitting data with a RS485 communication.

1.) before you send any data from the uart you have

to switch on the tx enable line of the RS485 transceiver

2.) send out the data from the uart (hardware fifo, software fifo)

interrupt controlled

3.) switch off the tx enable line of the RS485 transceiver

immediately after the last stop bit from the last byte

of the transmitting frame ist sendet out from the uart

this all should be done in the uart ty interrupt handler,

the application only fills the software fifo and starts the

transmit interrupt

andy_ry
Associate
May 17, 2011
Posted on May 17, 2011 at 09:45

Quote:

The busy flag can only polled outside the interrupt function in the application.

OK. In this case you should use buffer FIFO and fill data in it in process of a transmitting on interruption. The basic program will be carried out further.

if(UART_GetITStatus(UART0, UART_IT_Transmit) != RESET)

{

for(i = 0; (i < 8) && (TxCounter < NbrOfDataToTransfer); i++)

{

UART_SendData(UART0, TxBuffer[TxCounter++]);

}

if(TxCounter != NbrOfDataToTransfer)

{

/* Clear the UART0 transmit interrupt */

UART_ClearITPendingBit(UART0, UART_IT_Transmit);

}

else

{

/* Disable the UART Transmit interrupt */

UART_ITConfig(UART0, UART_IT_Transmit, DISABLE);

}

}

d_steffen
d_steffenAuthor
Associate II
May 17, 2011
Posted on May 17, 2011 at 09:45

Hi Andy,

I can't use busy waiting, I need to control how fast as possible

after (and before) trinsmitting a RX485 tx-enable pin in the interrupt handler.

Other controllers like atmel avr have an tx emtpy or

tx finished interrupt flag.

The busy flag can only polled outside the interrupt function in the application.

akaiser9
Associate II
May 17, 2011
Posted on May 17, 2011 at 09:45

You could use a timer interrupt to poll the status. Not nice, but the UART macrocell does not appear to have any support beyond the status bit.

d_steffen
d_steffenAuthor
Associate II
May 17, 2011
Posted on May 17, 2011 at 09:45

read this for understanding RS485 communication

http://www.netrino.com/Articles/RS485Enable/index.php

npivo
Associate
May 17, 2011
Posted on May 17, 2011 at 09:45

Barricade wroute:

Quote:

1.) before you send any data from the uart you have

to switch on the tx enable line of the RS485 transceiver

...

3.) switch off the tx enable line of the RS485 transceiver

immediately after the last stop bit from the last byte

of the transmitting frame ist sendet out from the uart

this all should be done in the uart ty interrupt handler,

the application only fills the software fifo and starts the

transmit interrupt

All above could not be done inside UART tx interrupt handler!

At least you shoud switch on the tx enable line outside interrupt handler.

About p.3. I can not anderstand what for you want ''switch off the tx enable line ... immediately after the last stop bit from the last byte of the transmitting frame is sended out from the uart''? It is not nessasary. You may switch it off after you stop sending bytes into FIFO, even bytes steel staing in UART FIFO. Any way the bytes steel staing in FIFO will be sent out UART FIFO after that.

paulsmitton9
Associate III
May 17, 2011
Posted on May 17, 2011 at 09:45

Thanks rgreenthal!

I did think about using a timer and calculating the transmit time, but in the end I opted for the following:

Set up DMA to transmit. Put the Uart in loopback mode

Set up DMA to recieve the same length as transmitted, and then interrupt.

Set up DMA linked list to then recieve any subsequent response.

In the interrupt after the first recieve (i.e the looped back transmit),

I poll the uart until it is idle (i.e. for the duration of the stop bit)

and then turn of the transmit enable.

rgreenthal
Associate III
May 17, 2011
Posted on May 17, 2011 at 09:45

Hi

We are using RS-485 & the enable is on P6.3

And some Macros we use are:

// P6.3

// RS-485 Direction

// Actually taken care of by the OCMP2 used as a One-Shot

#define m_RS485BitDirOut() GPIO6->DR[GPIO_Pin_3 BitAddr] = GPIO_Pin_3

#define m_RS485BitDirIn() GPIO6->DR[GPIO_Pin_3 BitAddr] = 0

In the Init do

// P6.3 AltOut2 Timer1 OutComp2

// P6.3 is the RS-485 Direction Pin

SCU->GPIOOUT[6] |= 0x0080;

GPIO6->DDR |= 0x08; // P6.3 Output

m_RS485BitDirIn(); // Enable UART1 RS-485 to Rx

Then in the Tx do

__disable_interrupt();

TIM1->CR1 |= 0xA80; // force high (FLV2 + OLV2 + OC2E)

// maybe should be using UART_Mode_Tx (0x0100) and not UART_Enable_Mask (0x0001)

UART1->CR &= ~0x00000001; // disable UART1

UART1->LCR |= 0x00000004; // set even parity for local mode

UART1->DR = cData; // Load single Character to output

// Used to control an output waveform (RS-485 Direction)

// P6.3 AltOut2 Timer1 OutComp2

// P6.3 is the RS-485 Direction Pin

// At a Baud rate of 625000, we get 16 usec for a character

// For this Function we need a Minimum or 16 usec (1 char)

// Force low for 28 usec (16 usec/char)

TIM1->OC2R = TIM1->CNTRX + (18 + 10);

TIM1->CR1 &= ~0xA00; // remove (FLV2 + OLV2) force make comapare level low

UART1->CR |= 0x00000001; // enable

__enable_interrupt();

For more than One byte

// Calc number of Usec needed for the number of char Tx'ed

lTimerCounts = (lLength * 176)+120;

lTimerCounts /= 10;

// lTimerCounts = (lLength * 18) + 12; // This maybe faster REG 07/31/2008

__disable_interrupt();

TIM1->CR1 |= 0xA80; // force high (FLV2 + OLV2 + OC2E)

UART1->CR &= ~0x00000001; // disable

UART1->LCR |= 0x00000004; // set even parity for local mode

UART1->CR |= 0x00000001; // enable

// Used to control an output waveform (RS-485 Direction)

// P6.3 AltOut2 Timer1 OutComp2

// P6.3 is the RS-485 Direction Pin

// At a Baud rate of 625000, we get 16 usec for a character

// For this Function we need a Minimum or 16 usec * lLength

// Force low for ?? usec (16 usec/char)

TIM1->OC2R = TIM1->CNTRX + (short)lTimerCounts;

TIM1->CR1 &= ~0xA00; // remove (FLV2 + OLV2) force make comapare level low