8 years, 1 month ago.

Serial port tx termination check

Hi, everyone!

I have to implement a RS485 interface. The main thing to do is to control a pin that have to be set to '1' during tx operations, to '0' during rx. A simple code like this one

Serial serialRS485(P0_15, P0_16);
DigitalOut modePin (P2_7);

modePin = 1;
serialRS485.putc(0x55);
modePin = 0;

isn't working as expected. Serial tx are buffered, so putc() terminates "istantaneously", and the modePin will be cleared before the actual data transmission (checked with oscilloscope). To let it work I have to use something like this

Serial serialRS485(P0_15, P0_16);
DigitalOut modePin (P2_7);

modePin = 1;
serialRS485.putc(0x55);
wait(0.00010f);
modePin = 0;

where I force a wait status before clearing the mode pin. The wait period must be proportional to the serial baudrate.

Is there a way to avoid the wait state by checking when the serial tx is terminated? Via interrupt, cyclical read of a pin, ....

Thanks MIX

1 Answer

8 years, 1 month ago.

You can use a serial TX interrupt to clear the pin, that should trigger once the transmission is complete:

void txDone() {
  modePin = 0;
}

main () {
  serialRS485.attach(txDone,Serial::TxIrq);
  modePin = 1;
  serialRS485.putc(0x55);
}

One possible issue is that this may trigger when the buffer is empty rather than when the transmission is complete. So it may always been 1 byte early no matter how long the message.

On most UARTs you can check if data is currently being sent by checking the Transmitter empty flag of the UART status register, that will indicate whether data is in the process of being sent out or not. Unfortunately that is not accessible using the mbed API which means you'll need to work look at the register directly, the code to do that will be processor dependent and require you to know which UART within the device you are using.

Accepted Answer

So you say that I can't fully trust the IRQ solution. I will take a look in the processor datasheet (still a LPC1768) to check for hints about UART flags. Thanks!

- EDIT -

I made a quick'n'dirty

modePin = 1;
serialRS485.putc(0x55);
while(LPC_UART1->LSR & 0x00000040) == 0){}
modePin = 0;

So I'm checking Transmitter Empty bit on Line Status Register of UART1; it becomes '1' when the buffer is empty (all data sent). It's working as expected, so I'm ok with it. I've tested the IRQ solution, too; it worked, but since you told me that it can happen that the interrupt occurs before termination (never happened in my test), I preferred the status ping solution.

posted by Massimo Cristofolini 05 Mar 2016