Arm Mbed OS support forum

UART will not go down to 1200 baud

How do I get the baud rate to go down to 1200 baud? I am trying to set the uart 6 to 1200 baud with 7bits, Even parity add 1 stop bit. When I set the baud rate to 1200 baud it never goes below 5555 baud as measured on an oscilloscope. I confirmed this rate by setting my terminal program to 5555 baud and it displays the text that is sent. Sample code below.

include "mbed.h"
UnbufferedSerial  rs232(PC_6,PC_7,1200);
int main()
{
    rs232.format(7,SerialBase::Even,1);
    printf("Is this working\n");
    while (true) {
       
    }
}

If this is a custom board, have you set HSE_VALUE in custom_targets.json to the correct value?

Thank you for your reply. I apologize for not including the board information. This test was performed on a NUCLEO-F411RE development board. Any baud rate from 2400 to 115200 works fine. Setting the baud rate to 1200 resulted in the 5555 baud rate instead of 1200.

I tried to expand my experiment a bit by testing on a NUCLEO-L476RG development board. This board works down to 2400 baud. The weird part is when I set the baud rate to 1200, the resultant baud rate ends up being about 70422 as shown in the image. The code used for the test is below. I am using Mbed Studio 1.3.1 and mbed-os 6.6.0. I have tried down to mbed-os 6.2.1 with same results. Any ideas as to what I am missing?

#include "mbed.h"
InterruptIn mybutton(USER_BUTTON);
//Nucleo L476RG
DigitalOut tx_success(LED3,0);
UnbufferedSerial sdi12(PC_12,PD_2,1200);
//Nucleo F411RE or Nucleo F401
//DigitalOut tx_success(PA_15,0);
//UnbufferedSerial  sdi12(PC_6,PC_7,1200);

bool buttonPressed {false};

void butInterrupt(){
	buttonPressed=true;
}

int main()
{
    mybutton.rise(&butInterrupt);
    while (true) {
        if (buttonPressed){
            buttonPressed=false;
            ThisThread::sleep_for(100ms);
            tx_success=!tx_success;
            for(int i=1;i<=10;i++){
                sdi12.write("U", 1);
                ThisThread::sleep_for(10ms);
            }
        }
        ThisThread::sleep_for(1s);
    }
}

I switched back to the NUCLEO-F411RE and tested 4800 and 2400 baud. They also work fine. It just seems to be the 1200 baud setting that doesn’t work on either the NUCLEO-F411RE or NUCLEO-L476RG development boards.

This seems to be a bug. I don’t know how to add the bug tag to this topic after the fact.

I have tried 3 different NUCLEO development boards, STM32L476, STM32F411, and STM32F401. I have tried this on Mbed OS 6.2, 6.6 as well as 5.15 with RawSerial. I am using Mbed Studio 1.3.1 to program the boards.

I have tried the following baud rates 115200, 57600, 38400, 28800, 19200, 9600, 4800, 2400 and 1200. Every baud rate, except 1200, works on all 3 boards and all tested versions of Mbed OS. Setting the baud rate to 1200 does not result in a baud rate of 1200.

The STM32L476 set to 1200 ends up with a baud rate of 70422.
The STM32F411 set to 1200 ends up with a baud rate of 5555.
The STM32F401 set to 1200 ends up with a baud rate of 18393.

FYI, it looks like the Cortex M4 chip does not support 1200 baud with it’s UART. Using STMCubeIDE will not allow 1200 to be entered for a baud rate. This issue has nothing to do with Mbed OS.

You may want to check that mbed-os/serial_api.c at master · ARMmbed/mbed-os · GitHub returns HAL_OK.

1200baud is indeed quite low and the device’s reference manual will tell you what can be achieved.

You can try adjusting the PLL of your device to lower the input frequency of the uart’s baudrate generator. But this will impact the overall performances of your device. STMCube indeed can help quickly running down the math.

The Cortex M4 chip on the STM32F411RE does support 1200 baud with it’s USART. It will support it by default with USART2 which is connected to the APB1 bus. This bus has a prescaler clock divider set to /2 which will allow a speed down to 1200 baud.

USART6 on the STMF411RE is connected to the APB2 bus which has it’s prescaler clock divider set to /1 by default. I ended up setting it to /2 with the following function taken from STMCube32IDE to get around my problem. I still am verifying that the other devices that use the APB2 bus still work as expected at this slower clock speed before I continue.

bool SystemClock_Config(void)
{
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

    /** Initializes the CPU, AHB and APB buses clocks
    */
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
    //RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; //Default prescaler set to /1
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; // Set prescaler to divide by 2

    return (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) == HAL_OK);
}

Hope this helps someone else.

Thank you Wilfried Chauveau for the information on the HAL_OK check.