![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
sysysy
Joined: 17 Nov 2010 Posts: 38 Location: 121
|
2x16 LCD Problem with PIC16f877A |
Posted: Wed Nov 17, 2010 7:53 am |
|
|
Hi,
I am trying to interface the 2x16 (HD44780) LCD with the 16f877A PIC.
Below is the problem that i encountered.
I am using the CCS Version 4.038.
Procedure:
1. Hardware interfacing. Gnd, Vdd, Vee(with 10k pot) are connected, i manage to see the whole black rectangular block in lcd first line ---> OK
2. RS, RW,En, DB4 - DB 7 are connected to PIC pins. ---> OK
3. With using CCS build-in driver (LCD.c), i try to show something with add a main function and few statement ---> OK
4. For example: lcd_putc("\fTesting");
Most of the time, LCD display not valid output (_o<-<-ooo), just very few times, valid output (Testing) word just will display out. ---> (Fail)
5. In addition, even in lcd_init() there, we already initialize that lcd is 2 line. but how come still only first line same like original shown?
As a result, there is ntg show when i trying to show
lcd_putc("\nSecond Line"); --->(Fail)
*(I do trying to adjust the pot, but still see nothing.)
This is the 2 main problem that i encountered.
Can you give me any suggestion to solve this? (I have stucked here for 2 days already)
Below is the code:
Code: |
#include <16F877A.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
// Un-comment the following define to use port B
// #define use_portb_lcd TRUE
struct lcd_pin_map { // This structure is overlayed
BOOLEAN enable; // on to an I/O port to gain
BOOLEAN rs; // access to the LCD pins.
BOOLEAN rw; // The bits are allocated from
BOOLEAN unused; // low order up. ENABLE will
int data : 4; // be pin B0.
} lcd;
#ifdef __pch__
#locate lcd = 0xf83
#else
#locate lcd = 8
#endif
#define set_tris_lcd(x) set_tris_d(x)
#define lcd_type 2 // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40 // LCD RAM address for the second line
BYTE const LCD_INIT_STRING[6] = {0x20 | (lcd_type << 2),0xc, 1, 6};
// These bytes need to be sent to the LCD
// to start it up.
// The following are used for setting
// the I/O port direction register.
struct lcd_pin_map const LCD_WRITE = {0,0,0,0,0}; // For write mode all pins are out
struct lcd_pin_map const LCD_READ = {0,0,0,0,15}; // For read mode data pins are in
BYTE lcd_read_byte() {
BYTE low,high;
set_tris_lcd(LCD_READ);
lcd.rw = 1;
delay_cycles(1);
lcd.enable = 1;
delay_cycles(1);
high = lcd.data;
lcd.enable = 0;
delay_cycles(1);
lcd.enable = 1;
delay_us(1);
low = lcd.data;
lcd.enable = 0;
set_tris_lcd(LCD_WRITE);
return( (high<<4) | low);
}
void lcd_send_nibble( BYTE n ) {
lcd.data = n;
delay_cycles(1);
lcd.enable = 1;
delay_us(2);
lcd.enable = 0;
}
void lcd_send_byte( BYTE address, BYTE n ) {
lcd.rs = 0;
while ( bit_test(lcd_read_byte(),7) ) ;
lcd.rs = address;
delay_cycles(1);
lcd.rw = 0;
delay_cycles(1);
lcd.enable = 0;
lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0xf);
}
void lcd_init() {
BYTE i;
set_tris_lcd(LCD_WRITE);
lcd.rs = 0;
lcd.rw = 0;
lcd.enable = 0;
delay_ms(15);
for(i=1;i<=3;++i) {
lcd_send_nibble(3);
delay_ms(5);
}
lcd_send_nibble(2);
for(i=0;i<=3;++i)
lcd_send_byte(0,LCD_INIT_STRING[i]);
}
void lcd_gotoxy( BYTE x, BYTE y) {
BYTE address;
if(y!=1)
address=lcd_line_two;
else
address=0;
address+=x-1;
lcd_send_byte(0,0x80|address);
}
void lcd_putc( char c) {
switch (c) {
case '\f' : lcd_send_byte(0,1);
delay_ms(2);
break;
case '\n' : lcd_gotoxy(1,2); break;
case '\b' : lcd_send_byte(0,0x10); break;
default : lcd_send_byte(1,c); break;
}
}
char lcd_getc( BYTE x, BYTE y) {
char value;
lcd_gotoxy(x,y);
while ( bit_test(lcd_read_byte(),7) ); // wait until busy flag is low
lcd.rs=1;
value = lcd_read_byte();
lcd.rs=0;
return(value);
}
void main()
{
lcd_init();
lcd_putc("\fTesting");
}
|
I would feel glad if anyone willing to help.
Thanks. |
|
![](templates/subSilver/images/spacer.gif) |
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Wed Nov 17, 2010 10:53 am |
|
|
Place a while(true) at the end of main.
Code: |
void main()
{
lcd_init();
lcd_putc("\fTesting");
while(true)
{
}
}
|
|
|
![](templates/subSilver/images/spacer.gif) |
sysysy
Joined: 17 Nov 2010 Posts: 38 Location: 121
|
|
Posted: Wed Nov 17, 2010 10:56 am |
|
|
Wayne_ wrote: | Place a while(true) at the end of main.
|
Try this before, but it does not work.
![Crying or Very sad](images/smiles/icon_cry.gif) |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
![](templates/subSilver/images/spacer.gif) |
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Thu Nov 18, 2010 2:59 am |
|
|
sysysy wrote: | Wayne_ wrote: | Place a while(true) at the end of main.
|
Try this before, but it does not work.
![Crying or Very sad](images/smiles/icon_cry.gif) |
Just because your code does not work with the while loop in does not mean you can leave it off. Without it your pic will go into sleep mode which may shut down your outputs, timers, clock etc, depending on configuration.
With the while loop it won't so you won't be chasing your own tail.
Leave it in then you will only have the 1 problem to fix. |
|
![](templates/subSilver/images/spacer.gif) |
sysysy
Joined: 17 Nov 2010 Posts: 38 Location: 121
|
|
Posted: Thu Nov 18, 2010 6:39 am |
|
|
Thanks Wayne.
u've taught me 1 more thing
PCM_Programmer,
i tried the driver, it does not work at all.
by the way, i have 2 question here:
1. when we use 4 bit mode, is it pins db0 to db3 from lcd must connect to ground or optional?
2.when the invalid character display on lcd, what is that mean? delay problem or? (for example, when i wanna display "ABC", but the lcd display
"o/<") |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9174 Location: Greensville,Ontario
|
|
Posted: Thu Nov 18, 2010 7:07 am |
|
|
I think you might want to try 8 bit mode for the display interface.
It's the simplest way to prove hardware and software as no 'drivers' are involved, no fancy code,etc.
Just wire up the LCD to an 8 bit port and set it to say 55x( 'U').
If that works, create a simple loop to send several letters,numbers,etc.
Once you've got it working perfect, rewire to 4bit mode,use the 'flex' driver, and test it out.
Build upon small sucessful steps. |
|
![](templates/subSilver/images/spacer.gif) |
sysysy
Joined: 17 Nov 2010 Posts: 38 Location: 121
|
|
Posted: Thu Nov 18, 2010 7:26 am |
|
|
hi Temtronic,
Thanks for your suggestion. Anyway, do you have 8 bit driver code?
I try to write for it before, not so sure, and does not work. I don't how to send the data to those 8pins (db0 to db7).
3Anyway, below is my code.
I make it very very simple (based on my own understanding from lcd), and some part just copy from other driver example, because I don't know how to write.
Code: |
#include <16F877A.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#define use_portb_lcd TRUE
struct lcd_pin_map {
int data : 8;
} lcd;
#if defined use_portb_lcd
//#locate lcd = getenv("sfr:PORTB") // This puts the entire structure over the port
#ifdef __pch__
#locate lcd = 0xf81
#else
#locate lcd = 6
#endif
//#define set_tris_lcd(x) set_tris_b(x)
#define RS PIN_B0
#define RW PIN_B1
#define EN PIN_B2
void WRT_COMM(char COMM)
{
output_low(RS);
output_low(RW);
lcd.data = COMM;
output_high(EN);
delay_cycles(1);
output_low(EN);
delay_ms(2);
//while ( bit_test(lcd_read_byte(),7) ) ;
}
void WRT_DATA(char DATA)
{
output_high(RS);
output_low(RW);
lcd.data = DATA;
output_high(EN);
delay_cycles(1);
output_low(EN);
delay_ms(2);
//busy();
}
void lcd_init()
{
set_tris_b(0);
set_tris_d(0);
WRT_COMM(0x38);
//WRT_COMM(0x38);
//WRT_COMM(0x38);
WRT_COMM(0x0E);
WRT_COMM(0x01);
WRT_COMM(0x06);
WRT_COMM(0x80);
}
void main()
{
lcd_init();
printf("Testing");
while(1);
}
|
Anyone can take a look and give some suggestion?
Thanks a lot. |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Nov 18, 2010 1:39 pm |
|
|
I don't want to work on your 8-bit driver code, but I will try to help you
get the flex driver working.
1. What's the manufacturer and part number of your LCD ?
Also post a link to the webpage for the LCD.
2. Is the LCD installed on a PIC board ? Did you buy the board, or did
you build it yourself ? If you bought the board, post the manufacturer
and part number of the board.
3. Have you ever made this PIC and board do a simple thing, such as
blinking an LED ? Do you know that the board works ?
4. Post a list of the pin connections between the PIC and the LCD.
Don't just post this:
Quote: | RS, RW,En, DB4 - DB 7 are connected to PIC pins. ---> OK |
Post the pin number on the PIC, and the pin number on the LCD for
each connection.
5. Use a voltmeter or oscilloscope to measure the Contrast voltage
on the lcd. What voltage do you see ?
---------------------
Quote: | 1. when we use 4 bit mode, is it pins db0 to db3 from lcd must connect to ground or optional? |
Those pins should be unconnected. The LCD has built-in pull-up resistors
on those pins, so the LCD pulls them up to a logic high level. The pins
are not floating. They are at a safe logic level.
Quote: | 2. when the invalid character display on lcd, what is that mean? delay problem or? (for example, when i wanna display "ABC", but the lcd display
"o/<") |
It could be a timing problem in the lcd driver program. It could be that
your LCD has special timing requirements. It could be a power supply
problem on your board (power supply voltage is too low, or not regulated
at a stable voltage). Or something else. |
|
![](templates/subSilver/images/spacer.gif) |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|