Hi,
I'm playing with small project based on JM60 and developed in CW 10.1.
Rough description:
uC reads four 8-bit registers from peripherial (HCTL-2032 Quadrature-decoder/counter) connected to rotary encoder and display result on LCD.
To this point everything works fine. I can observe register contetnt on LCD in four groups eg. 255-255-255-255 (B4-B3-B2-B1)
Now I'm trying to convert this 8-bit groups to unsigned long int (eg 0xFF FF FF FF) and then to ASCII using :
unsigned long int result_unsigned_int;
char out_ASCII[11];
result_unsigned_int=(BYTE4*0x1000000)+(BYTE3*0x10000)+(BYTE2*0x100)+BYTE1;
sprintf(out, "%lu", result);
WriteStringToLCD(out);
It works in ordinary c complier on PC but it doesn't in CW - something stucks nothing happens
Can you tell me why? (Is there some restricions in sprintf in CW)
PS
Of course I use same WriteStringToLCD() to display other inforation and it works fine....
Regards
已解决! 转到解答。
What do you mean with stuch? Does sprintf not return? if that is the case I would try to increase the stack space.
There are different versions in different libraries provided, some support floating point, some not. But all of the
versions do support printing long. Especially the floating point versions need quite a bit of stack space.
Daniel
Why would you use sprintf() in an embedded application?
void gpfunc_getDecStr (uint8* str, uint8 len, uint32 val) { uint8 i; for(i=1; i<=len; i++) { str[len-i] = (uint8) ((val % 10UL) + '0'); val/=10; } str[i-1] = '\0'; }
That simple snippet takes 76 bytes on my S12. Personally, I have no particular urge to blow several kb of flash and RAM to do the very same thing with sprintf(), in a much slower fashion.
What do you mean with stuch? Does sprintf not return? if that is the case I would try to increase the stack space.
There are different versions in different libraries provided, some support floating point, some not. But all of the
versions do support printing long. Especially the floating point versions need quite a bit of stack space.
Daniel
gooral,
Are BYTE_X variables long integers? If not, then result
result_unsigned_int=(BYTE4*0x1000000)+(BYTE3*0x10000)+(BYTE2*0x100)+BYTE1;
^^ is always not higher than 0xFFFF on C target machines with 16-bits int's. You need to convert at least BYTE_4 and BYTE_3 or those two >0xFFFF multiplier constants to long, else it won't work when int is 16 bits wide.
It might not be the most efficient way to code it, but I think that the original code should work.
BYTE3/BYTE4 do not need to be longs because they are multiplied with long constants, so the multiplication gets performed with enough bits anyhow.
Hmm on a second thought the BYTE2*0x100 summand is problematic. The issue is that multiplication result tyoe is probably an signed int (probably, as it depends on the not given type of BYTE2), not of type unsigned int (or long, unsigned long).
And if it is int, then it gets sign extended to a long...
To fix that, use 0x100u or else the highest bit of BYTE2 may count as -2^^16...
I tipically write it with shifts, and then an explicit cast to (unsigned) long is necessart when shifting by 16 or more bits.
Anyhow I guess the issue in the end is too little stack space allocated.
Daniel
BTW: It's also a bit uncommon that a variable called result_unsigned_int has a type of unsigned long :smileyhappy:.
Compilerguru,
yes, it's not the case using Codewarrior S12(X), that char * 0x10000 or short * 0x10000 are chopped to 16bits. I'm not sure if this should be the same using other compilers. I believed that constant isn't long without L suffix, even if it is more than 0xFFFF. Is it? In all compilers? You must be right, I should consult C specs.
So what result from above should give for char BYTE4..1 set to 0xF4,0xF3..0xF1?
a).BYTEn are unsigned char's:
byte4 * 0x1000000 should give 0xF4000000, of course if constant is treated as long.
byte3 * 0x10000 , should give 0x00F30000
byte2 * 0x100 gives int = 0xF200, which is then sign extended to long givinh 0xFFFFF200
byte1 directly converted to long gives 0x000000F1.
The sum should be 0xF4F2F2F1
b) BYTEn are signed char's:
byte4 * 0x1000000 should give 0xF4000000
byte3 * 0x10000 , should give 0xFFF30000
byte2 * 0x100 gives int = 0xF200, which is then sign extended to long givinh 0xFFFFF200
byte1 directly converted to long gives 0xFFFFFFF1.
The sum should be 0xF3F2F1F1
Thanks for discussion!
I spent last exening and half of night to solve this - without results....
To avoid a possible problems with result claculation (mentioned abow - BYTEx are unsigned char so it works fine). I tried to convert a direct declared variable result_insigned_int=0xFFFFFFFF and convert it using sprintf(out,"%lu",result_unsigned int)
out is declared as:
char out[11];
Maybe it is something with stack size as CompilerGuru wrote...digging in stack settings will be difficult for me - I'm begginer
Could you try to run this simple code on your 8-bit uC(my is JM60):
unsigned long int in=0xFFFFFFFF;
char out[11];
sprintf(out,"%lu",in);
What you get in out? As I wrote abow it works in simulation mode but stucks in BDM.....
Hi,
Looks like the solution has been found!
I've followed ComplierGuru suggestion and I've changed Stack size in Project.prm from 0x80 to 0x100 and now it works perfect.
I wondering why old stack size wasn't enough. I don't use interrupts and any complicated calculations aren't performed in my project...
Thanks for advise! Another usefull lesson....
Are you sure that you are passing the right variable, Result is not defined - - above and does not contain the result of the putting of the 4 bytes together - - - - FYI, I tend to define a union and then place the bytes directly - - faster code.
Jim P
You have right, but this is only my mistake in listing - of course should be:
result_unsigned_int=(BYTE4*0x1000000)+(BYTE3*0x10000)+(BYTE2*0x100)+BYTE1;
sprintf(out, "%lu", result_unsigned_int);
I also try to simulate in CW and it works fine - out gets correct values.
I try to debug via BDM - I set breakpoint after sprintf and - variable result_unsigned_int has correct value but out doesn't change (has its initial value). When debugger starts process sprints it stuck......
My code obviously isn't optimal I know that
Bytes in union..., I'll try to implement this......
Something like itoa() for unsigned long int would be usefull (I'm using _itoa to convert decoder register values to ascii before displaing on LCD
Out is not defined, I assume same mistake
I am old hat type of programmer before standard lib's came about - - - - I have never liked the overhead of the printf, format, or sprintf - - - -
I have a routine that takes a nibble and outputs the hex code
this is called by the rountine to output a byte (twice)
the byte routine is called twice by the routine that outputs a 16 bit - - - etc.
routines are called out_nibble, out_byte, out_int - - and of course can simply add out_long
and in my case output directly to the serial output ring buffer for being sent out over a RS232 link to the program on the PC for debug and check out.
Out_byte does a left shift for the top bits.
Out_Int has the value passed as a union so it simply calls Out_byte with upper and then lower byte.
Thus do not have to fight the lib functions - - - and get the data sent where I want it to be faster.
Jim P