Ok, I have one uart interface (TXD GPIO 14, RXD GPIO 15). I want at least one more uart interface.

Possible solutions:

  • Bit banging: Use two unrelated spare GPIOs. I understand that timing is a problem on a standard linux. Would it be reliable with very low baudrate?

  • Switching: RPI decides when to talk to which device. Using e.g. CD4066BC.

  • spi to 2 x uart bridge: Didn't find a suitable part (availability, price, dil package)

  • usb to uart: Expensive

Are there other options? I'm inclined to switching, if it can be done. What would you advise?


A USB UART, such as FTDI, isn't really expensive. All your other options sound like they will cost you more in parts and time than the ~$13 it might cost you, and be unreliable or slow. Just go for the fast and trouble-free option, such as:


Sparkfun sells one too. In fact, maybe you can just pull one out of some old USB device or buy one from a junk store that doesn't know what it does.

I messed with an SPI to UART adapter for an Arduino project, there was no existing library so I wrote my own. In the end it worked ok, but if I could have just dropped in a $15 part I would have. In fact given the time it cost me I should have just got a mega with 4 serial ports.

Alternatively if you want lots of serial ports you could look at RS485 serial, which is similar to 232 (though not compatible), which supports multi-drop, ie several interfaces over the one line.

  • 1
    This is also easies option from software point of view. FTDI has Linux driver support out of the box. All other option will require painstaking driver work. – Ber Mar 20 '13 at 8:18
  • The cp2102 is my favorite usb uart chip. A quick amazon search reveals them for $6.99 (edit actually $1.50) with a cable included! Can't beat that! – portforwardpodcast Apr 6 '15 at 8:37

If you decide to skip adding extra hardware and just go the bit-banging route, this isn't as difficult as some picture it.

First off, your communication thread must go realtime:


struct sched_param param;               
param.sched_priority = sched_get_priority_max(SCHED_FIFO);
        return -1;

From now on, your thread will not be pre-empted for 950ms out of each second*, unless it returns control willingly (through sched_yield(), or usleep()) in timely manner, which will not make it pre-empted ever. With 850MHz CPU your bit-banging loop will be running idle most of the time even at fastest speeds.

Now unfortunately the requirement to return control from time to time means while your thread is sleeping, whatever your "opposing party" sends, would be lost forever. But for that purpose you could use transmission control. Either allocate some more GPIO for CTS line which you pull down before yielding and back up upon restoring control:

  bcm2835_gpio_write(CTS_PIN, LOW);
  bcm2835_gpio_write(CTS_PIN, HIGH);

or (IMHO preferably) use XON/XOFF transmission control - send the XOFF character over RS232 before sleeping, XON after you resume operation. The default ASCII codes for these are '\x13' for XOFF/"stop sending" and '\x11' for XON/"resume sending".

Of course your remote device must obey these. If it doesn't, some data will be lost.


I found what you are looking for: an I2C/SPI slave to UART/IrDA/GPIO bridge.

They come in single and dual version (so 1 or 2 extra UARTs). They (NXP) also (for the other side in case needed) have I2C/SPI master to UART/IrDA/GPIO bridges.

More information can be found about these chips here and the master counterpart.

Maxim also has chips that do the exact same thing.


USB to UART bridges are cheap and readily available, but have really lousy timing characteristics. Newark sells an "Embedded Pi" board which has an STM32F ARM processor that you can write bare-metal code on. That chip has three UARTs on it, and I think they can go pretty fast; if you were to use one to communicate with the Raspberry Pi that would leave two available for other purposes. Disclaimer: I've bought one of these boards, but have as yet simply used the Raspberry Pi itself to handle by I/O needs directly.

If you want lots of slower UARTs, the STM32F on the Embedded Pi board could probably handle a fair number, especially if you're willing to write some Arm assembly language. If there are two groups of 16 I/O pins available on a single board it might be possible to have 16 simultaneous software UARTs all working at once at a pretty decent baud rate (have a periodic interrupt at 3x or 5x the baud rate which stores 16-bit latched values from the receive port to a buffer, and outputs 16-bit precomputed values from a buffer to the transmit port; if you do this, then provided the average servicing time for the software UARTs isn't too great, it won't matter if there is an occasional worst-case hit (e.g. all sixteen ports receiving a byte simultaneously).

This approach can actually work out remarkably efficiently for receiving, since the "common case" code doesn't even have to look at individual UARTs. Suppose that you're sampling data at 5x, and the last 47 bytes of the buffer are duplicated immediately preceding it. Assuming data is written to the buffer in ascending order, you can then check whether any byte has been fully received on any of the 16 channels by simply saying:

bytes_ready = (armed_flag & data[rxptr] & ~data[rxptr-47] & ~data[rxptr-46] & ~data[rxptr-45] & ~data[rx_ptr-44]);

If bytes_ready is zero, no data has been received. Otherwise, if e.g. bit 2 of bytes_ready is set, that means that a received data byte may be found in bit 2 of data[rx_ptr-40], data[rx_ptr-35], data[rx_ptr-30], etc. Once one grabs the data, clear bit 2 of armed_flag and arrange for it to get re-set after about 44 samples.

This approach will require a bit of work on those samples where a byte of data is fully received (and potentially a lot of work if all 16 channels have a byte of data arrive at once) but on most samples the amount of work will be very slight. If one had 64 I/O pins, one could handle up to 32 UARTs using this approach without adding any extra work to the "common" case.


A microcontroller like a Picaxe could take serial data in on one pin and output serial data on a certain pin appropriately. This would effectively give you more serial outputs if you were prepared to have to tell the Picaxe which pin to output on. It could also do the same, but in reverse, so it could receive serial data from multiple devices and send it to the Raspberry Pi. Another option could be to make connected devices require a qualifier. This means that Device 1 would have to receive the data 'd1', for example before it will listen to further data on the serial line. Device 2 could have 'd2' as its qualifier. This would mean that to say 'hello' to Device 1, you'd just have to send 'd1hello' on the UART line.

Picaxes are fairly cheap, you can get them over at http://www.techsupplies.co.uk/ and they come in numerous sizes with different numbers of pins and so on.


If the communication to the several UART slave devices does not need to occur in parallel, you could share the one available UART port between them. You could use transistors to enable only the RxD/TxD connections to the device you currently wish to talk to. These transistors can be controlled by other Raspberry Pi GPIO pins.


The Raspberry Pi 4 supports up to 4 UART interfaces now that need to be enabled by means of an device tree overlay. You can find how to do this and which Pins are used here for now:


The RPi foundation is still preparing the documentation for this.


I had the same problem. I need connect to 2-4 GSM modules and I found hardware solution: http://www.instructables.com/id/SPI-to-4-x-UART-Bridge-MULTIUART/

This solution are base on PIC24FJ64GA306. You can replace PIC with Atmel mcu, but You must create new PCB :)


Have a look over https://www.kickstarter.com/projects/1915118535/uart-hat-for-raspberry-pi i hope it may solve your problem

  • 1
    Since this isn't a product that's actually available, that makes this a poor choice. – Jacobm001 Apr 6 '15 at 3:36
  • 1
    Worse still, seems like the company who did the KS project folded without delivering the goods. – WineSoaked Nov 30 '15 at 16:41

Your Answer

