Hi all, a quick sprintf question if you don't mind...
I have hours, minutes and seconds, each held as a byte in bcd format, which have been read from an rtc. I want to use sprintf to format this into hh:mm:ss format, for display on an lcd.
As the values are in bcd, I first tried using "%x:%x:%x" but single digit values were not padded.
Second attempt was "%2x:%2x:%2x" which pads single digit values, but with spaces, not zeroes.
Third attempt was "%#2x:%#2x:%#2x" but this was worse, as sprintf wants to format 32 as 0x32 for example.
Can it be done with sprintf without resorting to bcd to decimal conversion first?
If each value is a separate byte, then it is in effect a hexadecimal value but some of the values (A-F) never used.
If you just display it as hexadecimal then it will appear just as if it were decimal.
The other option is to print each digit separately and use bit shifting to get the two nibbles:
sprintf(myStr, "%d%d", hours >> 4, hours & 0x0F);
If the encoding is more complex, say you have 4 bits of units, 2 bits of tens, and other things in the other 2 bits (12/24hr flag, etc), then bit shifting plus masking, or hexadecimal plus masking, can be used:
So the time is being printed in hh:mm:ss format. Great.
But what's wierd is this: the first use of Wire.Read() should give the seconds, the second Wire.Read() should give the minutes and the third Wire.Read() should give the hours. (This is a DS3231 RTC, but its just the same as a DS1307 in this respect.) So what should get printed is ss:mm:hh.
It is as though the sprintf function is formating the values it is given in right-to-left order instead of left-to-right. How does it know to do this?
Welcome to C. While all three function calls are going to be called, the order in whcih they are called is not guaranteed. Different compilers might do things differently.
Welcome to C. While all three function calls are going to be called, the order in whcih they are called is not guaranteed. Different compilers might do things differently.
Welcome to C. While all three function calls are going to be called, the order in whcih they are called is not guaranteed. Different compilers might do things differently.
Where did you get that from.
The order of function calls is always as written.
Looks to me like PaulRB has miss read the spec.
Mark
The order, in linear program line space, is as written. However, the order of function calls when embedded as parameters to another function call, is compiler specific:
What order are the Wire.read() functions called? In linear programming space, that sprintf function is what is executed "in order". The parameters to it, however, may be executed 1-2-3, or 3-2-1. It could even change from one situation to another due to optimisations created by the compiler.
The parameters to it, however, may be executed 1-2-3, or 3-2-1. It could even change from one situation to another due to optimisations created by the compiler.
Not by the compiler but by the function being called! and for sprintf etc thats specified as the order in which they are written. Think about it and try "writing" your own sprintf()
Thanks majenko and KeithRB. I never thought of that before, but it makes sense. A "gotcha" to remember. So if I assign the results of the 3 Wire.read () calls to variables in 3 statements, then pass those to sprintf () there can be no ambiguity over the order.
The parameters to it, however, may be executed 1-2-3, or 3-2-1. It could even change from one situation to another due to optimisations created by the compiler.
Not by the compiler but by the function being called! and for sprintf etc thats specified as the order in which they are written. Think about it and try "writing" your own sprintf()
Mark
No, because the functions are called first, then the results of those functions are passed to the sprintf function. The sprintf function does NOT call the functions - they are called BEFORE the sprintf() function - the sprintf() function has no control over the calling order - that is purely down to the compiler and how it optimises the code.
PaulRB:
Thanks majenko and KeithRB. I never thought of that before, but it makes sense. A "gotcha" to remember. So if I assign the results of the 3 Wire.read () calls to variables in 3 statements, then pass those to sprintf () there can be no ambiguity over the order.
Absolutely. If there is any chance of ambiguity then you want to nobble it as fast as possible
Not by the compiler but by the function being called! and for sprintf etc thats specified as the order in which they are written. Think about it and try "writing" your own sprintf()
You are thinking at too high a level. Down in the intermediate code after parsing, things are often implemented as various stacks and operators. It depends on how the stack works as to the order of teh function calls in function parameters.
The DS1307 library has the ability to pass in the Timekeeper register you're interested in (0 = seconds, 1 = minutes, 2 = hours). They are BCD values, so you may have to mask the nibbles. The internal register pointer uses the index to place the pointer prior to a read. It auto-increments, which is why most reads and writes to the RTC start with an argument of zero.