2
\$\begingroup\$

I am trying to build a simple baud rate changer with a Blue pill stm32f103 using the HAL API.

What I'm hoping to achieve: One old terminal to that's locked at 9600 baud. One old thermal printer that has a max of 300 baud.

The project consist of 2 "Blue pills", one that just puts of a character stream at 9600. The other Blue pill takes the stream in at 9600 and dumps every 4 bytes into a register for UART 3. Using hardware flow control, the contents are dumped into UART2 which is 300 baud.

It works well as long as its a continuous stream but when I stop the primary transmitter I need the downstream UARTs to stop transmitting. I have tried using the RXNE, TXE and TC flags but they do not work as expected. When I stop the transmission from primary stream, UART2 ( 300 baud), goes into "TIME OUT" and just continuously prints whatever is left in its buffer.

    while (1) {

    if (__HAL_UART_GET_FLAG(&huart3, UART_FLAG_RXNE) == 0) {    // 0 = Empty
        HAL_GPIO_WritePin(BluePill_LED_GPIO_Port, BluePill_LED_Pin,GPIO_PIN_SET);
        HAL_Delay(100);
    }
    HAL_UART_Receive(&huart3, (uint8_t*) uart1_buf, uart_buf_len, 500);

    strcpy(uart2_buf, uart1_buf); // copy the contents of UART1 buffer to UART2 buffer
    if (__HAL_UART_GET_FLAG(&huart2, UART_FLAG_RXNE) == RESET) {
        HAL_GPIO_WritePin(BluePill_LED_GPIO_Port, BluePill_LED_Pin,GPIO_PIN_SET);
        HAL_Delay(200);
    }

    HAL_UART_Transmit(&huart2, (uint8_t*) uart2_buf, uart_buf_len, 1000);
    if (!(__HAL_UART_GET_FLAG(&huart2, UART_FLAG_TXE))) {
        HAL_GPIO_WritePin(BluePill_LED_GPIO_Port, BluePill_LED_Pin,GPIO_PIN_RESET);
        HAL_Delay(200);
    }
}

This code is modified for testing purposes. As you can see I was thinking I could get the LED to come on when the flag conditions were met but the LED doesn't come on. One other odd thing is the although the LED doesn't come on, the HAL_Delay is for sure being executed.

Maybe someone could shed some light on what I'm doing wrong. Thanks

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Try thinking about the code how it executes. It always sends the whole buffer even if nothing is received. And the final byte takes so long to transmit that by the code checks TXE it is never indicating empty. And strcpy copies strings, i.e. until a terminating NULL byte is found. If such byte is never found in the buffer, then it might overwrite other variables, heap, and stack. \$\endgroup\$
    – Justme
    Commented Sep 29, 2020 at 4:39
  • \$\begingroup\$ Back up. Use a single board as two only add complexity with no clear benefit. Understand that you cannot eternally translate a faster baud rate into a slower one, as you will run out of buffer memory; something needs to limit the input to give the output a chance to catch up. \$\endgroup\$ Commented Sep 29, 2020 at 4:47

1 Answer 1

1
\$\begingroup\$

Due to the difference in speed, a buffer should probably be used (as mentioned in the comments). So the below code assumes that code for such a buffer (probably ring buffer) exists with this API:

bool buffer_is_empty();           // returns true if buffer is empty
bool buffer_is_full();            // returns true if buffer is full
uint8_t buffer_remove_byte();     // removes and returns the oldest byte added to the buffer
void buffer_add_byte(uint8_t b);  // adds a byte to the buffer

The main loop works byte by byte:

  • If a byte is available on UART3, receive it and add it to the buffer
  • If UART2 is ready and the buffer is not empty, remove a byte and transmit it

It could look like so:

uint8_t ch;

while (1) {

    if (__HAL_UART_GET_FLAG(&huart3, UART_FLAG_RXNE) != 0) {  // not empty
        HAL_UART_Receive(&huart3, &ch, 1, 1);
        if (!buffer_is_full()) {
            buffer_add_byte(ch);
        } else {
            // buffer overflow - discard byte
        }
    }

    if (!buffer_is_empty() && __HAL_UART_GET_FLAG(&huart2, UART_FLAG_TXE) != 0) {
        ch = buffer_remove_byte();
        HAL_UART_Transmit(&huart2, &ch, 1, 1);            
    }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.