c++cstringarmusart

How to send float to USART data register (ARM-M4)?


EDIT: The issue is only on STM32CubeIDE, on Keil-MDK it works.

I have been trying to send a message using the USART port of STM32F411 MCU. I wrote a function which takes char* and ellipsis as input. Ideally you would convert the numbers into a string/character and put into a char buffer and send a charater at a time to the USART->DR. Here is the function:

void Serial::write_byte(int data)
{
    Serial::port->DR = (data & 0xff);
    while (!(Serial::port->SR & (1 << 7))); //wait for Tx buff to get empty
}

void Serial::write(char *msg, ...)
{
    char buff[256];
    va_list args;
    va_start(args, msg);
    vsprintf(buff, msg, args);
    for (unsigned int i = 0; i < strlen(buff); i++)
    {
        Serial::write_byte(buff[i]);
    }
}

The above function works with integer numbers and characters. But when I do the following:

float R = (int16_t(raw[0] << 8 | raw[1]))/4096.0;
Debug.write("XG : %f\n",R);

The output on the serial terminal is : XG : (No number)

To note that I tried various ways available in C & C++ :

  1. Using sprintf

       int16_t R = int16_t(raw[0] << 8 | raw[1]);
       char str[10];
       sprintf(str,"%f",(R/4096.0));
       Debug.write("XG : %s\n",str);
    

    The output is : XG : 0, Even with %.4f it shows 0.

  2. Using std::string

    int16_t R = int16_t(raw[0] << 8 | raw[1]);
    //  goes into unknow state , mcu stops
    std::string msg = "Roll : " + std::to_string(R/4096.0) + "\n";
    Debug.write_string(msg);
    sleep_ms(1000);
    

    In this case there is no output. I checked with the debugger and this is the place where it gets stuck: Halts here

Apart from the code I also changed the FPU settings in STM32CubeIDE, here are the current settings: fpu_settings

So far I referred to various SO questions and tutorials, but It has never worked for me.

I would appreciate your help and guidance!


Solution

  • Okay so digging up the issue from all the available QAs and all, I found out the intimated settings are not working for me, and that my code has no issues in implementations! Note that this is not an issue on Keil MDK, it is only on STM32CubeIDE.

    So just for the folks who might face similar issues with float in STM32CubeIDE, there are forums which say to add a linker-flag -u _printf_float, other say to change the _estack value in linker files (which says end address as 2001ffffH, but it should be 20020000H), unfortunately none of them worked for me.

    What worked for me was to change the MCU-Settings; where I changed the Floating-poin ABI to Software Implementation and checked the Use float with printf(incase you are using newlib-nano, for standard C/C++ it would be disabled anyway). Here is how: fpu-settings