views:

517

answers:

5

Hi guys, I programming a 16f84a pic in hitech C to drive a hd44780 lcd. So far I've got the lcd initialized and can write individual characters and strings to the lcd. Now I need to do something like this:

var = 250;
lcd_write_string("MyVar has value: " + var);
so the lcd should show "MyVar has value: 250"

First of all how should I concatenate a var and a string? second, the variable var contains an 8 bit binary number (0-255 in decimal). If var = 23; the 8 bit number has to be split into 2 to represent the 2 and the 3 in ascii to then be shown by the lcd. how can I do this? It seems I have to do base 10 conversions or a if tree to split all 2 digit numbers to then be shown in the lcd. Is there an easier way around this?

thanks!

+2  A: 

Why don't you just use printf("%d", var) ?

var = 250;
char *static_msg = "MyVar has value:";
char msg[sizeof(static_msg) + 4];

sprintf(msg, "%s %d", static_msg, var);
lcd_write_string(msg);
qrdl
thanks guys, qrdl's answer worked. However using printf loads external libraries and requires more memory. I got it to work like this: lcd_write_num(var/10); lcd_write_num(var % 10); but it only works for 2 digit numbers. the catch is that the 16f84a has so little memory using any of these 2 methods practically overloaded the pic. I ended up using a 16f628a and things work perfect now using qrdl's method. thanks a lot!
Juank
found another option regarding digit manipulation not concatenation. check: http://www.mikroe.com/en/books/picbook/5_chapter.htm
Juank
A: 

If the C compiler comes with the standard C library functions, then sprintf can be used similar to printf, in order to produce a string.

sprintf can be used to produce a formatted string (as char*), which could presumably be sent to the lcd_write_string function.

coobird
+1  A: 

Supposing your toolset does not include the standard C library, or that you want to figure out how to do this yourself, here's the approach I would take:

Declare a buffer of as many characters as the LCD can display. Write your fixed string into the beginning of that buffer. Determine how many characters wide your variable will be (there's some math I'm leaving out here, but it's a reasonable exercise I think). Using that length, and the length of the fixed string, figure out where in the buffer your number's digits will go. Using the same mathematical constructs as before, write the digits into that space, one by one. There's a trick of the C language (required by the standard) that lets you figure out the character value of a decimal digit by the expression '0' + digit. Hopefully, you see how that works. Finally, terminate the buffer however your lcd_write_string function expects, and call it on the buffer.

As indicated by other respondents, this essentially implements a small part of the standard library's printf family of functions. I think it's worthwhile to figure out the implementation, even if you can (and should!) use the library in production code.

Since this smells vaguely like homework, I'm not elaborating further just yet. If you need help on specific points, I'll look for updates to the question.

Novelocrat
A: 

The problem with sprintf() is you do not know how many bytes you need to allocate before calling sprintf(). I usually use the following ksprintf() as a replacement.

typedef struct __kstring_t {
  size_t l, m;
  char *s;
} kstring_t;

int ksprintf(kstring_t *s, const char *fmt, ...)
{
  va_list ap;
  int l;
  va_start(ap, fmt);
  l = vsnprintf(s->s + s->l, s->m - s->l, fmt, ap); // not working with glibc 2.0
  va_end(ap);
  if (l + 1 > s->m - s->l) {
    s->m = s->l + l + 2;
    kroundup32(s->m);
    s->s = (char*)realloc(s->s, s->m);
    va_start(ap, fmt);
    l = vsnprintf(s->s + s->l, s->m - s->l, fmt, ap);
  }
  va_end(ap);
  s->l += l;
  return l;
}

To use that:

kstring_t *str = calloc(1, sizeof(kstring_t));
ksprintf(str, "%s, %d\n", aString, aInteger);
ksprintf(str, "a second line: %s\n", aString2);
free(str->s); free(s);

ksprintf() does not work with glibc 2.0 because vsnprintf does not return the number of bytes in the string. You need to repeatedly double the memory in allocation. Linux man page "man snprintf" also gives an example. On your system, you should check the behavior of your vsnprintf(), which is C99, not C90 though.

A: 

Another way to do this would be to use lcd_write_string as a function pointer and do this:

printf(lcd_write_string,"MyVar has value: %d",var)

This works correctly on CCS Pic C compiler, if lcd_write_string is declared like

void lcd_write_string (char c);
Manuel Ferreria
This will only work if it is the CCS compiler. This is a workaround for this compiler as it can't pass a full constant string as a parameter, therefore it defines the function as a charand allows the programmer to get over this compiler deficiency, auto generating the internals loops to print it.
Manuel Ferreria