STM8S UART test in Single Wire (half duplex) mode

I received an answer from an STM engineer after my question in the forum at this link: https://community.st.com/thread/46397-stm8s001j3-uart-remap . The question was about the loss of UART_RX if remapping the TX on the pin 5 (PA3). The answer confirmed my opinion about a mistake in documentation, but the engineer suggested the use of the UART in single-wire half-duplex mode, where only the UART_TX pin is used. So, I tested this operative mode and it worked. Then, I decided to publish the full project folder (schematics and C sources) in order to expand my tutorial about the STM8S microcontroller (hope it helps).

The working prototype

Using a single wire UART means that you must “mix” the output and input line to have your communication. In the microcontroller such mixing circuit is inside the chip, but if you want to use (for example) an USB-Serial converter standard to drive the micro, you will add some hardware. Not so much: just a diode and a resistor. Look at the schematic here below:

The diode used in this case is the BAT43, a Schottky diode with low forward voltage drop. This is necessary in order to have a “zero” level inside the microcontroller VIL limits. Note that such “mixer” isn’t very good if you plan to use the serial interface at very high speed, ‘cause the “high” level comes from the pull-up (10K) only, being the serial line “open drain” like. So, the rising time of the signal depends upon the capacitive loads on the line. Using a transmission speed of 115200 BPS, means that every bit is about 8.7 uS long and the internal sampler of the UART takes 3 samples at the ideal center of the bit. I recommend to use transmission speeds not higher than 19200 BPS. In this experiment I used the quite good 9600 BPS (104 uS per bit) with 8 data bit, one stop bit, no parity.

The firmware in C language is available in a fully working folder with all the necessary files to edit / compile / debug the experiment. Please read the starting point for setting-up the working environment at my previous article here.

The program is very simple. You can use any terminal program on your PC as the controller part, setting the communication speed as mentioned before. You have just two valid commands: AT0<cr> to turn OFF the led on the microcontroller board or AT1<cr> to turn it ON. In both cases you will receive an answer “OK”<cr><lf>. Every different input will produce an answer like “Error”<cr><lf>. The max length of the command string is 4 characters. Look at the terminal window:

Firmware description

First of all, we have to set the options bytes in the STM8S001J microcontroller. We connect the SWIM interface and run the ST programmer. We now modify the AFR1 and AFR0 bits in order to remap the UART_TX on pin PA3 (pin 5). The options can be written from the C program in the micro (it’s almost like write to the EEPROM), but for this test we just use the STM programmer, before loading the test program in the microcontroller. This is the screenshot of the modified option bits:

click the image to enlarge

With the microcontroller’s options programmed in this way, we can try to start debugging the test program. The folder that contain all the files can be downloaded from this link: SingleWire.zip. Please expand the zip file using the program 7Z and the password: eficara.

Now, some details about the C source. First of all, we have to set the port PA3 to be output open-drain. When the serial TX transmits a “zero” the line is pulled down from the internal mosfet; when the TX sends a “one” the line is “open”, so the high level is supplied by the pull-up resistor (10K, see schematic). Here are the C source lines:

After this, we set the UART registers to have 9600,N,8,1 protocol in Single wire, half-duplex mode. In such mode, the micro uses only the I/O PA3 for both TX and RX.

Now we create a function to transmit a character on the serial port. Note that every character sent will be received in the same time ! So, I set a flag called echo that will be used in RX interrupt to discard the data just received (such echoed data will not be stored in RX queue).

It’s better to take a look at the RX interrupt to clarify the concept. The serial RX interrupt will save the received data in a circular buffer. If the echo flag is set, the received data is NOT stored, so it is filtered out.

The data stored in the circular RX buffer will be used to fill the command buffer that is asynchronously handled in the main program as part of TimedEvents.

If head and tail pointer of the circular buffer are different, there is some data pending, so the data is taken from the buffer and the tail index is incremented. The received data is then compared with 0x0D (the CR) and if it’s equal, the received command can be executed. Note that the program also tries to execute the program if the buffer is filled (command too long). The command execution is very simple (this is just a proof of concept !). Look at the parser:

So, the accepted commands are “AT0” and “AT1” followed by CR,  that respectively turn OFF and ON the led on PB4. You can read all of the program on the main.c and stm8_interrupt_vector.c files in the project folder. Hope it will be interesting for you. Have fun!