View previous topic :: View next topic |
Author |
Message |
davekelly
Joined: 04 Oct 2006 Posts: 53 Location: Berkshire, England
|
lcd_putc with 16x1 LCD |
Posted: Wed Nov 08, 2006 9:32 am |
|
|
Using pcm v3.249 with 16F876a
I am using a 16x1 LCD module, based on the Hitachi 44780
For this particular module, lcd_putc doesn't work 'out of the box', as the display is segmented into 2 x 8 character displays. The first 8 characters are at address 0, the second set of characters are at address 0x40.
Any simple way to get around this problem? |
|
|
dbotkin
Joined: 08 Sep 2003 Posts: 197 Location: Omaha NE USA
|
|
Posted: Wed Nov 08, 2006 9:07 pm |
|
|
Sure. You have to treat it as a 2 line x 8 char display. lcd_gotoxy(1,1) is position 1 and lcd_gotoxy(1,2) gets you to position 9. |
|
|
davekelly
Joined: 04 Oct 2006 Posts: 53 Location: Berkshire, England
|
|
Posted: Thu Nov 09, 2006 6:20 am |
|
|
The answer isn't so simple (had already tried this).
I am porting one of my old projects written several years ago with the Bytecraft compiler, where I had written all of the LCD interface routines.
I am slowly discovering why - the 16x1 LCD is such a pig! It takes quite a bit to initialize it.
If I get it all sorted into nice routines, I'll post it as library code. |
|
|
dbotkin
Joined: 08 Sep 2003 Posts: 197 Location: Omaha NE USA
|
|
Posted: Thu Nov 09, 2006 10:08 am |
|
|
You're correct that lcd_init() will need some changes to get the thing initialized properly, but I find that to be the case pretty often even with 2-line displays. Once you get the LCD working, though, I'm pretty sure lcd_gotoxy() and lcd_putc() will work. I know I've used one before, been looking for the code for that (old) project to see what I did but so far haven't found it. It's been a few years. |
|
|
davekelly
Joined: 04 Oct 2006 Posts: 53 Location: Berkshire, England
|
|
Posted: Thu Nov 09, 2006 10:11 am |
|
|
I would be interested in any code you have, as I am pulling my hair out trying to get this thing initialized.
I recall I had many problems previously, however it was many years ago.
I am at the point of changing the display to a 2 line display, and selling it to my customers as a feature upgrade!!! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Nov 09, 2006 12:47 pm |
|
|
If you search on Google for this search string:
Quote: | "16x1" lcd int #define |
or for this one,
Quote: | "16x1" lcd int char |
you will find many sample drivers. I don't think any of them have
a lcd_putc() or lcd_putch() function, as CCS does. They all write an
entire string to the LCD, starting at the left side of the display.
They use one for(;;) loop for the first 8 bytes, then they change the
address and use a 2nd for(;;) loop to do the remaining 8 bytes.
CCS doesn't allow passing pointers to constant strings, but you use
a RAM array that's 17 bytes long, to hold the string and to pass it to
a lcd_put_string() function. That might be the quickest way to get
it working.
You could modify the CCS driver, but you would have to create a
variable to keep track of the X position with lcd_putc(). The other
routines in the driver would have to be modified as well. I don't have
one of these 16x1 LCDs to test, so I don't feel like writing experimental
code that I can't physically test. Look at my first suggestion above
and maybe try that one. |
|
|
davekelly
Joined: 04 Oct 2006 Posts: 53 Location: Berkshire, England
|
|
Posted: Thu Nov 09, 2006 1:07 pm |
|
|
Thanks for the reply.
I already solved the problems a few years ago using the Bytecraft compiler, using this similar method of separating the characters into 8 character blocks.
In the port to CCS, the main problem appears to be the difficulty in initializing the display. Even with a reasonably faithful port of my original code, it still doesn't work properly.
I will try some 16x2 LCD's when I get some to play with, as they are about the same price as the 16x1 in bulk. |
|
|
davekelly
Joined: 04 Oct 2006 Posts: 53 Location: Berkshire, England
|
|
Posted: Fri Nov 10, 2006 2:43 am |
|
|
After many trials, I have found the best sequence for initializing this display:
(I have based my routines on the FlexLCD.c code as posted by PCM Programmer http://www.ccsinfo.com/forum/viewtopic.php?t=24661)
Code: |
int8 const LCD_INIT_STRING[4] =
{
0x28, // 4 bits, 16x1 line, 5x7 characters
0x0c, // Display On, cursor off, no blink
0x06, // Auto increment cursor
0x01 // Clear display
};
//----------------------------
#separate
void lcd_init(void)
{
int8 i;
output_low(LCD_RS);
#ifdef USE_LCD_RW
output_low(LCD_RW);
#endif
output_low(LCD_E);
delay_ms(15);
for (i = 0; i < 3; i++)
{
lcd_send_nibble(0x03);
delay_ms (5);
}
lcd_send_nibble (0x02); // Set to 4 bit mode
delay_ms (5);
// Now the initialization
for(i=0; i < sizeof(LCD_INIT_STRING); i++)
{
lcd_send_byte(0, LCD_INIT_STRING[i]);
// If the R/W signal is not used, then
// the busy bit can't be polled. One of
// the init commands takes longer than
// the hard-coded delay of 60 us, so in
// that case, lets just do a 5 ms delay
// after all four of them.
#ifndef USE_LCD_RW
delay_ms(5);
#endif
}
}
|
printf and lcd_putc work ok, you just have to split the string at pos 8, and effectively go to line 2 for the second half of the line.
Good luck to any other unfortunate souls who try to use this display!!! |
|
|
|