converting integers and fixed point to character sequence - Page 1
Forum section: electronics / general

author: NiHaoMike
author_rank: Super Contributor
timestamp: February 20, 2014, 06:09:32 am
content: How do I convert integers to ASCII character sequences for display on a LCD? I'm using a dsPIC and performance isn't critical, but is always nice. I also need to do the same for arbitrary fixed point values. (For example, one such variable might be 1/256 of a unit per LSB. And while the display code isn't performance critical, some of the DSP code that uses the fixed point values are.)

author: mariush
author_rank: Super Contributor
timestamp: February 20, 2014, 06:54:19 am
content: The compiler (xc8 and others, most of them) has built in functions that do this job for you.For example, open the XC8 user guide and search for sprintf or vsprintf ... then read the explanations for printf which explain how that function works.xc8 user guide here:http://ww1.microchip.com/downloads/en/DeviceDoc/52053B.pdfIf you don't want to add a lot of code to your program and you only need to print a number, you can make one yourself.something like thisunsigned char digit; // happy now? sigh... must get some sleep.unsigned byte digitpos = 5;unsigned int number = 12345; // your numberunsigned int temp;unsigned int remainder;temp = number;digit=0;while (temp > 0) {digitpos--;digits = temp mod 10;temp = temp / 10;}if (digitpos==5) digitpos = 4;so you have temp = 12345 , an array with 5 elements [ -, -, -, -, 0] , digitpos = 5;temp > 0, yes it's 12345 => digitpos--; => digitpos = 4; digit = 12345 mod 10 = 5; = > array is [-,-,-,-5] , temp = temp / 10 = 1234temp > 0, yes it's 1234 => digitpos--; => digitpos = 4; digit = 1234 mod 10 = 4; = > array is [-,-,-,4,5] , temp = temp / 10 = 123and so on,and then you do a for (i = digitpos, i<5, i++) print character digit [ i];The above code should work with unsigned byte, unsigned char, unsigned int variables. int is maximum 65535 (5 digits). If you want to print larger numbers, you need to increase the array and redefine the digitpos to new value ( for example for a long variable (4 bytes) the maximum value would be 4,294,967,296 so you need to be able to store 10 digits.There are other methods that use less cpu clocks, for example see the example towards the bottom of this page, which uses shift instead of divisions and precalculated tables (faster but may use more memory) :http://stackoverflow.com/questions/3694100/converting-to-ascii-in-cor this code which converts any float, integer etc into a series of characters ... so you don't need to use sprintf but you'd neet to use the math library, for log10 and pow functions (xc8 has them)http://stackoverflow.com/questions/2302969/how-to-implement-char-ftoafloat-num-without-sprintf-library-function-i/2303798#2303798

author: zapta
author_rank: Super Contributor
timestamp: February 20, 2014, 07:30:57 am
content: Quote from: mariush on February 20, 2014, 06:54:19 amThese two lines don't seem to be compatible.+1 for sprintf or utoa() and the likeshttp://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html

author: mariush
author_rank: Super Contributor
timestamp: February 20, 2014, 07:57:13 am
content: Thanks, I corrected it.I'm tired, it's almost 10 am and I worked all night... fell into the classic trap of defining an array with 5 elements as digit, when in fact it's defined as digit because you also count the 0 element.When i double checked the code before posting, I corrected that but missed the second line of code.

author: grumpydoc
author_rank: Super Contributor
timestamp: February 20, 2014, 08:32:25 am
content: QuoteIt's still wrong.Code:unsigned char digit;...digit=0;"char digit" yields an array 4 elements - digit .. digit.I hope you don't write much firmware

author: Psi
author_rank: Super Contributor
timestamp: February 20, 2014, 10:56:11 am
content: i vote for utoa() itoa() ltoa().. and all the othersmuch less complex than including all of the sprintf code

author: Rufus
author_rank: Super Contributor
timestamp: February 20, 2014, 03:20:08 pm
content: Quote from: Psi on February 20, 2014, 10:56:11 amI would vote for rolling your own with a bit more function that itoa() because you will often want to format right aligned into a fixed length string.edit: for exampleCode:voidltostr(long num, char *string, int size) {int neg = 0;if(num < 0) {neg = 1;num = -num;}string[--size] = 0;size--;do {string[size--] = "0123456789"[num % 10];num /= 10;} while(size >= neg && num != 0);if(neg)string[size--] = '-';if(size >= 0)memset(string, ' ', size + 1);}Where size is the size of the string including terminator and leading digits which don't fit in size are discarded.

author: dannyf
author_rank: Super Contributor
timestamp: February 20, 2014, 03:28:54 pm
content: I wrote a ultoa() routine to convert an unsigned long to ascii string.The same routine can also be used with a floating type.

author: grumpydoc
author_rank: Super Contributor
timestamp: February 20, 2014, 04:15:20 pm
content: QuoteYes, although it helps to be clear what happens in that case - the compiler will convert the float to an unsigned long, then call ultoa (as long as a prototype for ultoa is in scope).