Half duplex UART and STM32 - Page 1
Forum section: electronics / general

author: darko31
author_rank: Regular Contributor
timestamp: August 13, 2016, 06:25:23 pm
content: Hi guys, I've got couple of questions about using half duplex UART. I want to interface STM32VL board with AX-12 servo, and I've got the transimt part working, but receive part isn't chooching as it should.For the moment I'm using STM's HAL. As I've managed to gather from various examples, by default, the uart is in TX mode. In order to get it to RX, enabling RX with HAL is with HAL_HalfDuplex_EnableTransmitter().So the function for reading data from servos goes like this, ignore the error handler, it isn't implemented yetCode:uint16_t AX12_read_data(uint8_t id){uint8_t rxBuffer={0};uint8_t length=0;uint8_t error=0;uint16_t return_value;HAL_HalfDuplex_EnableReceiver(&huart2);HAL_UART_Receive(&huart2, (uint8_t*) rxBuffer, sizeof(rxBuffer), 200);if (rxBuffer == 0xFF && rxBuffer == 0xFF){}else //Error_Handler();length = rxBuffer-2;//ax12 magic, see manualerror = rxBuffer;if (error != 0){}//Error_Handler();else if (length == 0){}//Error_Handler();else {if (length > 1){return_value = (rxBuffer << 8) + rxBuffer;return return_value;}else {return_value = rxBuffer;return return_value;}}HAL_HalfDuplex_EnableTransmitter(&huart2);return 0;}This function is called right after transmitting some command.Problem is the received data doesn't seem right, first is 255 which is right, but receiving some random numbers after that, usually zeroes.Am I missing something obvious, and what exactly does timeout parameter in uart send and receive do?

author: Kalvin
author_rank: Super Contributor
timestamp: August 13, 2016, 06:32:06 pm
content: At least here is one evil thing:if (rxBuffer == 0xFF && rxBuffer == 0xFF){}else //Error_Handler();length = rxBuffer-2; //ax12 magic, see manualerror = rxBuffer;I will leave it as an exercise for you to figure it out.

author: Kalvin
author_rank: Super Contributor
timestamp: August 13, 2016, 06:47:06 pm
content: It is a good habit to always use the braces {} with the if-statements, while-loops and for-loops:Code:if (cond1){do_something1();}else if (cond2){do_something2();}else{do_something_else();}Probably you have by now figured out why

author: darko31
author_rank: Regular Contributor
timestamp: August 13, 2016, 07:16:51 pm
content: Yeah, will add them, though it should work as it is. The code was written quick and dirty.But I've commented out all the error checking stuff, with a bit of delay after receiving bytes, and it kinda, sorta works, but for some reason now there are three 255 at the start of the message. Hm, too tired to debug it more, will continue later.

author: Kilrah
author_rank: Unknown
timestamp: August 13, 2016, 07:24:29 pm
content: Quote from: darko31 on August 13, 2016, 07:16:51 pmNope, there's at least one line that's executed when it shouldn't due to your "quick and dirty" shortcut.

author: dannyf
author_rank: Super Contributor
timestamp: August 13, 2016, 07:54:13 pm
content: Quoteagree with others: "quick and dirty" is usually deadly.

author: darko31
author_rank: Regular Contributor
timestamp: August 13, 2016, 09:11:07 pm
content: Ok, but forget the error checking and quick and dirty at the moment. Not about that.When reading from UART more bytes than expected, what's gonna be stored at those bytes, zeroes, previous values or something else?And does timeout when using UART specify how long to "wait" for bytes to arrive before ending the message?

author: Kilrah
author_rank: Unknown
timestamp: August 13, 2016, 09:40:26 pm
content: Quote from: darko31 on August 13, 2016, 09:11:07 pmThe datasheet may mention that, but it's likely unspecified i.e. random.On some STMs if you do a buffer overrun/underrun you can actually completely lock up the whole MCU, so checking the flags, handling errors and doing things right is essential.

author: dannyf
author_rank: Super Contributor
timestamp: August 14, 2016, 01:48:12 am
content: QuoteUnknown.The point is that such a situation should not have happened. The general process is to read from the receiving register / buffer to a user string, until the end of transmission is detected -> you will have to decide a protocol on what signals the end of your transmission.If you have DMA set up, it is a natural circular buffer.

author: Kalvin
author_rank: Super Contributor
timestamp: August 14, 2016, 10:38:51 am
content: Maybe you cannot see the problem, so I just make it clear for you. Sometimes this happens when one looks at his/her own code too long. Been there, too. Here we go:The original, evil code:if (rxBuffer == 0xFF && rxBuffer == 0xFF){}else //Error_Handler();length = rxBuffer-2; //ax12 magic, see manualerror = rxBuffer;Here's how the compiler will see it due to the fact that you have commented the else-clause's statement out:if (rxBuffer == 0xFF && rxBuffer == 0xFF){}else//Error_Handler();length = rxBuffer-2; //ax12 magic, see manualerror = rxBuffer;Which is equivalent to this:if (rxBuffer == 0xFF && rxBuffer == 0xFF){}elselength = rxBuffer-2; //ax12 magic, see manualerror = rxBuffer;Thus the else-clause "length = rxBuffer-2;" will be executed unless buffer's first and second value are 0xff.

author: darko31
author_rank: Regular Contributor
timestamp: August 14, 2016, 07:36:04 pm
content: Yes, I see now what were you reffering to, will sort all the error checking stuff.Thing is, AX12 return messages can have different length, so in order to check how long is the message, first you have to check value of fourth length byte.Is it okay to first read first four bytes then after reading the legth byte read appropriate ammount after? Or to have different read functions with different lengths?Also timeout to receive message from AX12 is variable by default it's 160us, or there about. Should I set that time in timeout in uart read function, or add a little delay before reading uart?