External Links

Creative Science Centre



Presented here are two UARTS:

  • // #include "http://www.byvac.com/mBlib/flb/Library/UART/softuart.bas" [1]
  • // #include "http://www.byvac.com/mBlib/flb/Library/UART/softuart_1.bas" [2]

Soft UART 1 [2]

This is works at a fixed 9600 but the RX works on an interrupt and so can capture bytes into a buffer without poling. This uses plugin_1c. The plug in source code is not needed unless modification is required.

Constants in the library

  • SBB_TIMING 2005 This has been found by trial and error to give the best results at 9600, for lower Baud rates, it can be changed. For example 4800 would be about 4010 (double)
  • BBU.MAX 128 This is the buffer size and is set to 128 bytes


  • bbu.init(*PORTB(),1,*RC9(),*TIMER3()) (rxport,rxpin,txpoerptin,timer) This is an example of using PORTB pin 1 for RX and PORTC pin 9 for TX, using timer 3. It should be noted that this function initialises an interrupt that will be disabled on error. Should a programming error occur then this will need to be called again.
  • bbu.clear() Clears the buffer an initialises the buffer pointers
  • bbu.cib() Returns the number of bytes in the buffer
  • bbu.getc() Gets a byte from the buffer (first in first out)
  • bbu.peeks(*buf$,term) This will get the bytes in the buffer up to and including the specified term byte and put them in the supplied string buf$. The buffer contents remain unchanged. Returns 1 if it has retrieved any bytes.
  • bbu.gets$(term) This will return the bytes in the buffer up to and including term, if term is not found then all of the bytes in the buffer will be returned. Unlike bbu.peeks() the buffer is emptied.
  • bbu.see() this will print all of the bytes in the buffer and empty it. Used for debugging as it will also show non-printable characters.
  • bbu.putc(b) Sends byte b to the TX pin.
  • bbu.puts(*s$) Sends string s$ to TX pin.

Soft UART [1]

The library here allows the creation of TX and RX on any pins, thus creating an extra UART. So what is the limitation?

On TX there is NONE and it will work up to 115200 Baud. The minor downside comes with receiving, ideally a byte should be able to be received at any time and that will go into a buffer, just as the other two UARTS do. However that requires an interrupt with a very small latency in order to capture the start of the start bit.

The latency of the ByPic interrupt is about 500uS which is too slow but all is not lost. The implementation uses a blocking* function that will return when a specified byte has been received. This could be a special byte like 'break' or simply a CR, thus turning the function into something that gets a line of data.


This is when a function will take all of the CPU time until it is finished and so needs to be used  sensibly.

// #include "http://www.byvac.com/mBlib/flb/Library/UART/softuart.bas"

There is also a zip file containing the source code to the plug in if required.

The above uses two plug-ins that can receive and transmit, these are used beause of the tight timing required.

How to use

Initialise using bbu.init for example

constant RXPORT {PORTB(PORT),5} // port and pin
constant TXPORT {PORTB(PORT),6}


Any timer can be specified. The last number on the end is the Baud rate where

0 = 2400
1 = 9600
2 = 14400
3 = 28800
4 = 19200
5 = 57600
6 = 115200

Sending Data

bbu.puts(s$) // sends a string

bbu.putbytes(*bytes$, n) // sends n number of bytes from the supplied string address


Receiving Data


The supplied string address will receive the data and the function will return either a) when the byte specified in term has been received (this will also be included in the string) or b) when the string is full. The size of the string which is automatically specifoed in the first 4 bytes is used to determine when the string is full.

Get a line of text example

dim a$[128]

Will return when CR is received.