Electrical – STM32 UART character encoding issues (can’t decode using either ASCII or UTF-8)

encodinghal-librarystm32stm32f4uart

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()
line = ser.readline(100)

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

Could the community please:

  • 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.

Best Answer

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.