1

I am trying to create a log function on stm32. I am trying to create a quite long string by converting multiple data values. Everything seems to work, but there is 1 position, that no matter what I do, I get 0 all the time:

 sprintf((char*)buffer_tx_pc, "Timestamp: %ld\n\r"
                                             "Relay_mux_1: %d,  Relay_mux_2: %d,  Relay4: %d,  Relay2: %d\n\r"
                                             "STPM34_1:         V1=%.3f,    I1=%.3f,    V2=%.3f,    I2=%.3f\n\r"
                                             "STPM34_2:         V1=%.3f,    I1=%.3f,    V2-%.3f,    I2=%.3f\n\r"
                                             "STPM34_3: Mux1&9  V1=%.3f,    I1=%.3f,    V2=%.3f,    I2=%.3f\n\r"
                                             "STPM34_3: Mux2&10 V1=%.3f,    I1=%.3f,    V2=%.3f,    I2=%.3f\n\r"
                                             "STPM34_3: Mux3&11 V1=%.3f,    I1=%.3f,    V2=%.3f,    I2=%.3f\n\r"
                                             "STPM34_3: Mux4&12 V1=%.3f,    I1=%.3f,    V2=%.3f,    I2=%.3f\n\r"
                                             "STPM34_3: Mux5&13 V1=%.3f,    I1=%.3f,    V2=%.3f,    I2=%.3f\n\r"
                                             "STPM34_3: Mux6&14 V1=%.3f,    I1=%.3f,    V2=%.3f,    I2=%.3f\n\r"
                                             "STPM34_3: Mux7&15 V1=%.3f,    I1=%.3f,    V2=%.3f,    I2=%.3f\n\r"
                                             "STPM34_3: Mux8&16 V1=%.3f,    I1=%.3f,    V2=%.3f,    I2=%.3f\n\r\n\r",
                                             systick_timestamp,5, 8, 10, 4,
                                             (double)stpm34_voltage_buffer[0], (double)stpm34_current_buffer[0],
                                             (double)stpm34_voltage_buffer[1], (double)stpm34_current_buffer[1],
                                             (double)stpm34_voltage_buffer[2], (double)stpm34_current_buffer[2],
                                             (double)stpm34_voltage_buffer[3], (double)stpm34_current_buffer[3],
                                             (double)stpm34_voltage_buffer[4], (double)stpm34_current_buffer[4],
                                             (double)stpm34_voltage_buffer[5], (double)stpm34_current_buffer[5],
                                             (double)stpm34_voltage_buffer[6], (double)stpm34_current_buffer[6],
                                             (double)stpm34_voltage_buffer[7], (double)stpm34_current_buffer[7],
                                             (double)stpm34_voltage_buffer[8], (double)stpm34_current_buffer[8],
                                             (double)stpm34_voltage_buffer[9], (double)stpm34_current_buffer[9],
                                             (double)stpm34_voltage_buffer[10], (double)stpm34_current_buffer[10],
                                             (double)stpm34_voltage_buffer[11], (double)stpm34_current_buffer[11],
                                             (double)stpm34_voltage_buffer[12], (double)stpm34_current_buffer[12],
                                             (double)stpm34_voltage_buffer[13], (double)stpm34_current_buffer[13],
                                             (double)stpm34_voltage_buffer[14], (double)stpm34_current_buffer[14],
                                             (double)stpm34_voltage_buffer[15], (double)stpm34_current_buffer[15],
                                             (double)stpm34_voltage_buffer[16], (double)stpm34_current_buffer[16],
                                             (double)stpm34_voltage_buffer[17], (double)stpm34_current_buffer[17],
                                             (double)stpm34_voltage_buffer[18], (double)stpm34_current_buffer[18],
                                             (double)stpm34_voltage_buffer[19], (double)stpm34_current_buffer[19]);

Some explanation of values:

  • uint64_t timestamp is just system tick timer value;
  • Relay_mux_1, Relay_mux_2, Relay_4, Relay_2 suppose to be just a
    uint8_t number from 1 to 16.
  • float stpm34_voltage_buffer[20] voltages array
  • float stpm34_current_buffer[20] currents array

I print correct values everywhere, except for Relay_mux_1:, on that one I get 0 all the time (that why I am passing just random numbers 5, 8, 10, 4 to test it). buffer_tx_pc is just uint8_t pointer. What could cause this problem? I also tried replacing %d of Relay_mux_1 with some random string value "Relay_mux_1: 55, Relay_mux_2: %d, Relay4: %d, Relay2: %d\n\r" then I get 0 all the time on Relay_mux_2. What is the problem here and how do I get that 0 ?

UPDATE: I tried using PRIu64 like comments suggested:

sprintf((char*)buffer_tx_pc, "Timestamp: %" PRIu64 "\n\r" ...

but I get even weirder result:

Timestamp: lu
Relay_mux_1: 2292, Relay_mux_2: 0, Relay4: 5, Relay2: 8

14
  • 2
    Why use "%ld" with uint64_t timestamp instead of "%" PRIu64?
    – chux
    Commented Jan 10 at 8:30
  • always used it that way, never knew about PRIu64. Going to do some research then
    – Dominykas
    Commented Jan 10 at 8:32
  • My guess is that the timestamp part is the problem. Have you tried to remove that and see if the rest works? %ld is probably not correct for systick_timestamp
    – 4386427
    Commented Jan 10 at 8:32
  • 1
    yeah, good call, without timestamp it works. Then the question is why printing uint64_t causes this?
    – Dominykas
    Commented Jan 10 at 8:34
  • 1
    yeah now I don't get warning, so changing %ld to PRIu64 fixed this warning
    – Dominykas
    Commented Jan 10 at 8:50

1 Answer 1

1

Code has at least these issues:

Potential specifier mismatch

"%ld" matches unsigned long.
"%" PRIu64 from <inttypes.h> matches uint64_t.

Alternatively, try a cast.

sprintf((char*)buffer_tx_pc, "Timestamp: %llu\n\r", 
    (unsigned long long) systick_timestamp);

Unneeded (double) casts

OP reports "when passing array elements as floats, I goat warning that %f expects double." and "float stpm34_voltage_buffer[20] voltages array".

To well diagnose, we need a mcve.

Potential buffer overrun

sprintf((char*)buffer_tx_pc, ... %.3f ...", ... ) is scary code as "%.3f" of a single float value may be dozens of bytes long.

Instead, use snprintf() to avoid buffer overrun and use "%.3g" to keep individual float/double values from taking up too much space.

Many arguments

The 40+ arguments is certainly a questionable coding style, yet in itself, I do not see as a direct issue.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.