# STM32 UART character encoding issues (can't decode using either ASCII or UTF-8)

first some specifics:

STM32F411 Nucleo board, Atollic TrueSTUDIO v9.1.0, Debian linux 9.6.

I am sending a telemetry string over the UART using the HAL. I am using the following code to construct and transmit the data:

sprintf(str, "#, %d, %d, %s\n", csvString.range, csvString.lux, csvString.time);
HAL_UART_Transmit(&huart2, str, strlen(str), 100);


where '#' is the telemetry sentence start character, and the data follows a pre-formatted CSV type structure for easy manipulation on the receiving side. If I do a simple

cat /dev/ttyACM0


I can see the output, which looks like:

#, 21, 114, 01:58:001


so that looks like it's working well. However when I attempt to use a simple python script to parse this information in, I get a mess. It appears to be an encoding problem. The python that I'm using looks (as an excerpt) like this:

ser = serial.Serial('/dev/ttyACM0', 115200, timeout=2, parity = serial.PARITY_EVEN, bytesize = serial.EIGHTBITS, stopbits = serial.STOPBITS_ONE)

if ser.isOpen():
ser.close()

ser.open()
ser.flushInput()
ser.flushOutput()

ser.close()


and the result I get out of this reading of 100 bytes off the UART (just a sniff to see if things are working properly) looks like:

#\t\x920\t\x8a1\x13\t\xa22\xa7\xb2:\x820\xe1#\t\x922\t\x8a1\x13\t\xa22\xa7\xba:\x821\xe1#\t\x921\t\x8a1&\t\xa22\xa7\xba:\x821\xe1#\t\x923\t\x8a1&\t\xa22\xa7\xba:\x821\xe1#\t\x921\t\x8a1&\t\xa22\xa7\xba:\x821\xe1#\t\x920\t\x8a1\x13\t\xa22\xa7\xba:\x82


There is an obvious repeating pattern in this, which looks like it lines up with the telemetry sentences. I can't use some of the other methods in python to read off the UART easily because they can't detect newline characters in this.

It's obviously an encoding problem, but I'm not sure how to solve this as:

• I do not know how to (even after searching) verify the transmit encoding used by the STM32 HAL/Compiler
• I am not a talented software person

• Help me determine what the encoding being sent is
• Give an example of how to decode it so that I can then write code to parse things as I need to

Thanks!

EDIT: To address a comment suggesting evaluating the UART data using an oscilloscope, I can not do this as I am using the UART bridge on the STLink part of the STM32 Nucleo board. I am not currently able to switch to the other UART as those pins are in use. It would also not account for why I can see the data properly formatted if I display the output of the device in a terminal session (the above mentioned cat /dev/ttyACM0). Thank you for your suggestion.

• If an uart looks rubbish, check the baudrate. There is no encoding in an uart, it send what you put in. – Jeroen3 Nov 19 '18 at 6:53
• It's certainly not an encoding problem in the sense of ASCII vs UTF-8 vs ISO-8859-1. For the characters you are using, there's no difference between these encoding. My guess is it should be parity = serial.PARITY_NONE (instead of parity = serial.PARITY_EVEN). – Codo Nov 19 '18 at 7:03
• Maybe it is a python encoding thing, but I am not an expert in this. If you first try to receive the data with a simple terminal programm like (Hterm, ...) you can see if the transmission is working. – A.R.C. Nov 19 '18 at 7:12
• Also, make sure your clock is what you believe it to be – Scott Seidman Nov 20 '18 at 0:45
• Is the UART ever idle, or is it transmitting continuously? – duskwuff -inactive- Nov 20 '18 at 1:32

If I do a simple

cat /dev/ttyACM0

I can see the output

So it is working with the default settings of /dev/ttyACM0. You can find out what they are with the stty command. On my PC I get

root@berendilinux:~# stty -a </dev/ttyUSB0
speed 9600 baud; rows 0; columns 0; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S;
susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; discard = ^O; min = 1; time = 0;
-parenb -parodd -cmspar cs8 hupcl -cstopb cread clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany -imaxbel -iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke -flusho -extproc
root@berendilinux:~#


Run stty -a </dev/ttyACM0 on your host, and whatever rate it reports would be the baudrate to put in the Python program.

Read man stty for the meaning of the flags. My output contains

-parenb cs8 -cstopb


that means no parity, 8 bits, 1 stop bit. Parity is rarely used these days, some hardware does not support it in 8 bits mode at all.