EmbeddedRelated.com
Forums

Initialization of LCD 16*2 with rcm3720

Started by blacklor67 June 23, 2006
Hello,
I try to initialize my lcd 16*2 wich is connected with rcm3700 but
I've got some difficulty.
This is the file to do it:
/********************************************************************
lcd_demo.c
Z-World, 2000

The is a sample program for connecting to an LCD (which uses the
HD44780 controller, or an equivalent), using the Rabbit 2000
external I/O rabbit port.

This file contains information for a 4 bit interface. The 4 bit
interface uses one of the parallel I/O.

This is the initialization sequence for a 2 by 16 character LCD
programmed in 4 bit mode (chosen in order to reduce the number of
I/O pins):
delay for power up - allow LCD to reset
command: 4 bit mode
command: 2 lines, 5x7 character size, and 4 bit mode again
command: turn on display and cursor - non blinking
command: incr address and shift cursor with each character
Note: each command must be followed by a delay to allow the display
to respond.

Connection list:
Jackrabbit Pin LCD Signal
PA0 J3-3 DB4
PA1 J3-4 DB5
PA2 J3-5 DB6
PA3 J3-6 DB7

PA6 J3-9 RS Register Select: 0=command, 1a
PA7 J3-10 E normally low: latches on high to low transition

DB0 - DB3 of the LCD are grounded as is the R/W pin. Since we are
using 4 bit mode DB0 - DB3 are not used by the controller. We will
only be writing so we ground the R/W pin

Since Port A is used to control the LEDs on the expansion board, they
will be controlled by the data values which you program.

VEE is used to control brightness - the simplest thing to do is ground
it. If you need to control the brightness you can connect a
potentiometer between ground and -5V with the arm going to the VEE
pin. Check the specs on the LCD before doing this as some may require
a different connection. VCC is +5 and VSS is ground.
********************************************************************/
// Set a default of declaring all local variables "auto" (on stack)
#class auto
/********************************************************************
msDelay - delay some number of milliseconds
input parameter: int number of milliseconds to delay
return value: none
errors: none
********************************************************************/
nodebug
void msDelay(unsigned int delay)
{

auto unsigned long done_time;

done_time = MS_TIMER + delay;
while( (long) (MS_TIMER - done_time) < 0 );
/*
costate {
waitfor(DelayMs(delay));
}
*/
}

/*******************************************************************
UsDelay - delay some number of micro seconds - very approximate!!
about 11usec per iteration with the 7.3MHz crystal. The formula
used here was determined experimentally.
********************************************************************/
void UsDelay ( int iDelay )
{ auto int i;
//iDelay /= 3;
for ( i=0; i }

/*************************** 4 bit functions ***********************/
#define DATA 0x40 // RS is at PA7, RS=1 Data
#define COMMAND 0x00 // RS=0 Command
int iDataFlag;

/*******************************************************************
WriteNibble - send a single nibble to the LCD
********************************************************************/
void WriteNibble ( char cNib )
{ cNib &= 0x0F; // remove upper 4 bits
cNib |= iDataFlag; // insert data flag for RS

WrPortI ( PADR, &PADRShadow, cNib|0x80 ); // assert E
msDelay ( 1 );
WrPortI ( PADR, &PADRShadow, cNib ); // remove E

}

/*******************************************************************
for those who prefer assembly code.........
#asm
WriteNibble::
; character is in HL
ld a, L ; get the character
and 0x0F ; insure upper nibble is zero
ld hl, iDataFlag ; get address of data flag
or (hl) ; insert Data/Command bit
or 0x80 ; assert E
ioi ld (PADR),a ; ship data value and E
and 0x7F ; remove E
ioi ld (PADR),a ; ship data value without E
ret
#endasm
*******************************************************************/

/******************************************************************
WriteByte - send two nibbles to the LCD, upper nibble first
*******************************************************************/
void WriteByte ( char cNib )
{ auto int i;
i = cNib; // temp store
cNib >>= 4; // put upper nibble into lower 4 bits
WriteNibble ( cNib ); // send upper nibble
UsDelay (100);
// msDelay(1);
WriteNibble ( i ); // send lower nibble
msDelay(2);
// UsDelay (100);
}

/*********************************************************************
LCD_Init - Initialize the LCD for the following operating parameters:
4 bit mode, 2 lines, 5x10
turn on display and cursor: non-blinking
incr address and shift cursor with each character
*******************************************************************/
void LCD_Init ()
{
WrPortI(PADR, &PADRShadow, 0xFF); //set to output all high
WrPortI(SPCR, &SPCRShadow, 0x84); //ignore SMODE pins, set to output

WrPortI(PECR, &PECRShadow, PECRShadow&0x00); //clear all bits to pclk/2
WrPortI(PEFR, &PEFRShadow, PECRShadow&0x00); //clear all bits to
normal function
WrPortI(PEDR, &PEDRShadow, 0x40); //set bits 6 output high and
//set bits rest output low
WrPortI(PEDDR, &PEDDRShadow, PEDDRShadow|0x40); //set bits 6 to output
BitWrPortI(PEDR, &PEDRShadow, 0, 6); //Output enable signal for
level-converter

iDataFlag = COMMAND; // show command mode
msDelay ( 1000 ); // wait for LCD to reset itself

WrPortI ( PADR, &PADRShadow, 0x03 ); // Function Set
msDelay ( 5 );
WrPortI ( PADR, &PADRShadow, 0x03 ); // Function Set
msDelay ( 125 );
WrPortI ( PADR, &PADRShadow, 0x03 ); // Function Set
msDelay ( 5 );
WrPortI ( PADR, &PADRShadow, 0x02 ); // 4-bit mode
msDelay ( 5 );
WriteByte ( 0x28 ); // 4 bit mode, 2 lines, 5x7
msDelay ( 5 );
WriteByte ( 0x08 ); // turn on display and cursor: non-blinkin
msDelay ( 5 );
WriteByte ( 0x01 ); // incr address and shift cursor with each character
msDelay ( 5 );
WriteByte ( 0x06 );
msDelay ( 5 );
WriteByte ( 0x0F );
msDelay ( 5 );
WriteByte ( 0x01 );
msDelay ( 5 );
}

/*********************************************************************
Display - display a line of text on the LCD
argument: address of null terminated text string
*******************************************************************/
void Display ( char *szp )
{ iDataFlag = DATA; // next bytes are data
while ( *szp ) WriteByte ( *szp++ );
}

void Clear ( void )
{ iDataFlag = COMMAND; // set up for command
WriteByte ( 0x01 ); // clear the display
msDelay (5); // insure at least 4 msec
}

void Line2 ( void )
{ iDataFlag = COMMAND; // set up for command
WriteByte ( 0xC0 ); // set RAM address to Line 2
//note: this value may vary for different displays
msDelay (5); // insure at least 4 msec
}
void main ()
{

LCD_Init ();
// IMPORTANT - the initialization sequence should only
// be executed once after powerup. Multiple executions
// will cause the display to malfunction.
Clear();

while (1) {
Clear();
Display ( "0123456789" );

msDelay (5000);

Clear();
Display ( "This is a test!" );
msDelay (5000);

Line2 ();
Display ( "This is line TWO!" );
msDelay (5000);
}

}

Please, help me to find the mistake.
Thanks.

What exactly does "some difficulty" mean? ;-)

I looked at some old code and saw that I sent that initial byte out to
the display a few times. I think I actually remember that from the
data sheet for one of those character based displays. You can
probably find some init code for a module that uses that controller
pretty quickly. A quick look came up with
http://ee.cleversoul.com/lcd_project_source.html
Not sure if it's the same controller ic...

-- Dave

--- In r..., "blacklor67" wrote:
>
> Hello,
> I try to initialize my lcd 16*2 wich is connected with rcm3700 but
> I've got some difficulty.
> This is the file to do it:
> /********************************************************************
> lcd_demo.c
> Z-World, 2000
>
> The is a sample program for connecting to an LCD (which uses the
> HD44780 controller, or an equivalent), using the Rabbit 2000
> external I/O rabbit port.
>
> This file contains information for a 4 bit interface. The 4 bit
> interface uses one of the parallel I/O.
>
> This is the initialization sequence for a 2 by 16 character LCD
> programmed in 4 bit mode (chosen in order to reduce the number of
> I/O pins):
> delay for power up - allow LCD to reset
> command: 4 bit mode
> command: 2 lines, 5x7 character size, and 4 bit mode again
> command: turn on display and cursor - non blinking
> command: incr address and shift cursor with each character
> Note: each command must be followed by a delay to allow the display
> to respond.
>
> Connection list:
> Jackrabbit Pin LCD Signal
> PA0 J3-3 DB4
> PA1 J3-4 DB5
> PA2 J3-5 DB6
> PA3 J3-6 DB7
>
> PA6 J3-9 RS Register Select: 0=command, 1a
> PA7 J3-10 E normally low: latches on high to low transition
>
> DB0 - DB3 of the LCD are grounded as is the R/W pin. Since we are
> using 4 bit mode DB0 - DB3 are not used by the controller. We will
> only be writing so we ground the R/W pin
>
> Since Port A is used to control the LEDs on the expansion board, they
> will be controlled by the data values which you program.
>
> VEE is used to control brightness - the simplest thing to do is ground
> it. If you need to control the brightness you can connect a
> potentiometer between ground and -5V with the arm going to the VEE
> pin. Check the specs on the LCD before doing this as some may require
> a different connection. VCC is +5 and VSS is ground.
> ********************************************************************/
> // Set a default of declaring all local variables "auto" (on stack)
> #class auto
> /********************************************************************
> msDelay - delay some number of milliseconds
> input parameter: int number of milliseconds to delay
> return value: none
> errors: none
> ********************************************************************/
> nodebug
> void msDelay(unsigned int delay)
> {
>
> auto unsigned long done_time;
>
> done_time = MS_TIMER + delay;
> while( (long) (MS_TIMER - done_time) < 0 );
> /*
> costate {
> waitfor(DelayMs(delay));
> }
> */
> }
>
> /*******************************************************************
> UsDelay - delay some number of micro seconds - very approximate!!
> about 11usec per iteration with the 7.3MHz crystal. The formula
> used here was determined experimentally.
> ********************************************************************/
> void UsDelay ( int iDelay )
> { auto int i;
> //iDelay /= 3;
> for ( i=0; i > }
>
> /*************************** 4 bit functions ***********************/
> #define DATA 0x40 // RS is at PA7, RS=1 Data
> #define COMMAND 0x00 // RS=0 Command
> int iDataFlag;
>
> /*******************************************************************
> WriteNibble - send a single nibble to the LCD
> ********************************************************************/
> void WriteNibble ( char cNib )
> { cNib &= 0x0F; // remove upper 4 bits
> cNib |= iDataFlag; // insert data flag for RS
>
> WrPortI ( PADR, &PADRShadow, cNib|0x80 ); // assert E
> msDelay ( 1 );
> WrPortI ( PADR, &PADRShadow, cNib ); // remove E
>
> }
>
> /*******************************************************************
> for those who prefer assembly code.........
> #asm
> WriteNibble::
> ; character is in HL
> ld a, L ; get the character
> and 0x0F ; insure upper nibble is zero
> ld hl, iDataFlag ; get address of data flag
> or (hl) ; insert Data/Command bit
> or 0x80 ; assert E
> ioi ld (PADR),a ; ship data value and E
> and 0x7F ; remove E
> ioi ld (PADR),a ; ship data value without E
> ret
> #endasm
> *******************************************************************/
>
> /******************************************************************
> WriteByte - send two nibbles to the LCD, upper nibble first
> *******************************************************************/
> void WriteByte ( char cNib )
> { auto int i;
> i = cNib; // temp store
> cNib >>= 4; // put upper nibble into lower 4 bits
> WriteNibble ( cNib ); // send upper nibble
> UsDelay (100);
> // msDelay(1);
> WriteNibble ( i ); // send lower nibble
> msDelay(2);
> // UsDelay (100);
> }
>
> /*********************************************************************
> LCD_Init - Initialize the LCD for the following operating parameters:
> 4 bit mode, 2 lines, 5x10
> turn on display and cursor: non-blinking
> incr address and shift cursor with each character
> *******************************************************************/
> void LCD_Init ()
> {
> WrPortI(PADR, &PADRShadow, 0xFF); //set to output all high
> WrPortI(SPCR, &SPCRShadow, 0x84); //ignore SMODE pins, set to output
>
> WrPortI(PECR, &PECRShadow, PECRShadow&0x00); //clear all bits to
pclk/2
> WrPortI(PEFR, &PEFRShadow, PECRShadow&0x00); //clear all bits to
> normal function
> WrPortI(PEDR, &PEDRShadow, 0x40); //set bits 6 output high and
> //set bits rest output low
> WrPortI(PEDDR, &PEDDRShadow, PEDDRShadow|0x40); //set bits 6 to output
> BitWrPortI(PEDR, &PEDRShadow, 0, 6); //Output enable signal for
> level-converter
>
> iDataFlag = COMMAND; // show command mode
> msDelay ( 1000 ); // wait for LCD to reset itself
>
> WrPortI ( PADR, &PADRShadow, 0x03 ); // Function Set
> msDelay ( 5 );
> WrPortI ( PADR, &PADRShadow, 0x03 ); // Function Set
> msDelay ( 125 );
> WrPortI ( PADR, &PADRShadow, 0x03 ); // Function Set
> msDelay ( 5 );
> WrPortI ( PADR, &PADRShadow, 0x02 ); // 4-bit mode
> msDelay ( 5 );
> WriteByte ( 0x28 ); // 4 bit mode, 2 lines, 5x7
> msDelay ( 5 );
> WriteByte ( 0x08 ); // turn on display and cursor: non-blinkin
> msDelay ( 5 );
> WriteByte ( 0x01 ); // incr address and shift cursor with each
character
> msDelay ( 5 );
> WriteByte ( 0x06 );
> msDelay ( 5 );
> WriteByte ( 0x0F );
> msDelay ( 5 );
> WriteByte ( 0x01 );
> msDelay ( 5 );
> }
>
> /*********************************************************************
> Display - display a line of text on the LCD
> argument: address of null terminated text string
> *******************************************************************/
> void Display ( char *szp )
> { iDataFlag = DATA; // next bytes are data
> while ( *szp ) WriteByte ( *szp++ );
> }
>
> void Clear ( void )
> { iDataFlag = COMMAND; // set up for command
> WriteByte ( 0x01 ); // clear the display
> msDelay (5); // insure at least 4 msec
> }
>
> void Line2 ( void )
> { iDataFlag = COMMAND; // set up for command
> WriteByte ( 0xC0 ); // set RAM address to Line 2
> //note: this value may vary for different displays
> msDelay (5); // insure at least 4 msec
> }
> void main ()
> {
>
> LCD_Init ();
> // IMPORTANT - the initialization sequence should only
> // be executed once after powerup. Multiple executions
> // will cause the display to malfunction.
> Clear();
> while (1) {
> Clear();
> Display ( "0123456789" );
>
> msDelay (5000);
>
> Clear();
> Display ( "This is a test!" );
> msDelay (5000);
>
> Line2 ();
> Display ( "This is line TWO!" );
> msDelay (5000);
> }
>
> }
>
> Please, help me to find the mistake.
> Thanks.
>

I haven't read and compared the code you attached with the DC sample
source to see if you have changed anything.. If you HAVEN'T then we
can probably rule out any code problems, so this becomes a hardware
issue..

Assuming you have hooked up all the digital I/O correctly I'll bet
the problem is in the 'contrast' pin... I've worked with dozens of
these displays from many different manufactures and that contrast
voltage spec can vary widely... some even require a slightly
negative voltage... I usually hook a 10K pot to 5V and -5v and run
the wiper to the contrast pin... the contrast input requires next to
no current and if there is an RS-232 level converter on board a
cheap trick is to use one of the negative voltages it's charge pump
delivers...

--.- Dave

P.S. for those of you who really undersatnd what I've said, I had a
client whose display keep going blank.. turned out he was shorting
out one of the RS-232 pins and that drug the negative chargpump to
0V... LOL ...

--- In r..., "blacklor67"
wrote:
>
> Hello,
> I try to initialize my lcd 16*2 wich is connected with rcm3700 but
> I've got some difficulty.
> This is the file to do it:
> /******************************************************************
**
> lcd_demo.c
> Z-World, 2000
>
> The is a sample program for connecting to an LCD (which uses
the
> HD44780 controller, or an equivalent), using the Rabbit 2000
> external I/O rabbit port.
>
> This file contains information for a 4 bit interface. The 4
bit
> interface uses one of the parallel I/O.
>
> This is the initialization sequence for a 2 by 16 character LCD
> programmed in 4 bit mode (chosen in order to reduce the number of
> I/O pins):
> delay for power up - allow LCD to reset
> command: 4 bit mode
> command: 2 lines, 5x7 character size, and 4 bit mode again
> command: turn on display and cursor - non blinking
> command: incr address and shift cursor with each character
> Note: each command must be followed by a delay to allow the display
> to respond.
>
> Connection list:
> Jackrabbit Pin LCD Signal
> PA0 J3-3 DB4
> PA1 J3-4 DB5
> PA2 J3-5 DB6
> PA3 J3-6 DB7
>
> PA6 J3-9 RS Register Select:
0=command, 1a
> PA7 J3-10 E normally low: latches on
high to low transition
>
> DB0 - DB3 of the LCD are grounded as is the R/W pin. Since we are
> using 4 bit mode DB0 - DB3 are not used by the controller. We will
> only be writing so we ground the R/W pin
>
> Since Port A is used to control the LEDs on the expansion board,
they
> will be controlled by the data values which you program.
>
> VEE is used to control brightness - the simplest thing to do is
ground
> it. If you need to control the brightness you can connect a
> potentiometer between ground and -5V with the arm going to the VEE
> pin. Check the specs on the LCD before doing this as some may
require
> a different connection. VCC is +5 and VSS is ground.
>
********************************************************************/
> // Set a default of declaring all local variables "auto" (on
stack)
> #class auto
> /******************************************************************
**
> msDelay - delay some number of milliseconds
> input parameter: int number of milliseconds to delay
> return value: none
> errors: none
>
********************************************************************/
> nodebug
> void msDelay(unsigned int delay)
> {
>
> auto unsigned long done_time;
>
> done_time = MS_TIMER + delay;
> while( (long) (MS_TIMER - done_time) < 0 );
> /*
> costate {
> waitfor(DelayMs(delay));
> }
> */
> }
>
> /******************************************************************
*
> UsDelay - delay some number of micro seconds - very approximate!!
> about 11usec per iteration with the 7.3MHz crystal. The
formula
> used here was determined experimentally.
>
********************************************************************/
> void UsDelay ( int iDelay )
> { auto int i;
> //iDelay /= 3;
> for ( i=0; i > }
>
> /*************************** 4 bit functions
***********************/
> #define DATA 0x40 // RS is at PA7, RS=1 Data
> #define COMMAND 0x00 // RS=0 Command
> int iDataFlag;
>
> /******************************************************************
*
> WriteNibble - send a single nibble to the LCD
>
********************************************************************/
> void WriteNibble ( char cNib )
> { cNib &= 0x0F;
// remove upper 4 bits
> cNib |= iDataFlag;
// insert data flag for RS
>
> WrPortI ( PADR, &PADRShadow, cNib|0x80 ); // assert E
> msDelay ( 1 );
> WrPortI ( PADR, &PADRShadow, cNib ); //
remove E
>
> }
>
> /******************************************************************
*
> for those who prefer assembly
code.........
> #asm
> WriteNibble::
> ; character is in HL
> ld a, L ;
get the character
> and 0x0F ; insure
upper nibble is zero
> ld hl, iDataFlag ; get address
of data flag
> or (hl) ;
insert Data/Command bit
> or 0x80 ;
assert E
> ioi ld (PADR),a ; ship data
value and E
> and 0x7F ; remove E
> ioi ld (PADR),a ; ship data
value without E
> ret
> #endasm
>
*******************************************************************/
>
> /******************************************************************
> WriteByte - send two nibbles to the LCD, upper nibble first
>
*******************************************************************/
> void WriteByte ( char cNib )
> { auto int i;
> i = cNib; // temp store
> cNib >>= 4; // put upper nibble
into lower 4 bits
> WriteNibble ( cNib ); // send upper nibble
> UsDelay (100);
> // msDelay(1);
> WriteNibble ( i ); // send lower nibble
> msDelay(2);
> // UsDelay (100);
> }
>
> /******************************************************************
***
> LCD_Init - Initialize the LCD for the following operating
parameters:
> 4 bit mode, 2 lines, 5x10
> turn on display and cursor: non-blinking
> incr address and shift cursor with each character
>
*******************************************************************/
> void LCD_Init ()
> {
> WrPortI(PADR, &PADRShadow, 0xFF); //set to
output all high
> WrPortI(SPCR, &SPCRShadow, 0x84); //ignore
SMODE pins, set to output
>
> WrPortI(PECR, &PECRShadow, PECRShadow&0x00); //clear
all bits to pclk/2
> WrPortI(PEFR, &PEFRShadow, PECRShadow&0x00); //clear
all bits to
> normal function
> WrPortI(PEDR, &PEDRShadow, 0x40);
//set bits 6 output high and
>

//set bits rest output low
> WrPortI(PEDDR, &PEDDRShadow, PEDDRShadow|0x40); //set bits 6
to output
> BitWrPortI(PEDR, &PEDRShadow, 0, 6); //Output enable signal
for
> level-converter
>
> iDataFlag = COMMAND; // show
command mode
> msDelay ( 1000 ); // wait for
LCD to reset itself
>
> WrPortI ( PADR, &PADRShadow, 0x03 ); // Function Set
> msDelay ( 5 );
> WrPortI ( PADR, &PADRShadow, 0x03 ); // Function Set
> msDelay ( 125 );
> WrPortI ( PADR, &PADRShadow, 0x03 ); // Function Set
> msDelay ( 5 );
> WrPortI ( PADR, &PADRShadow, 0x02 ); // 4-bit mode
> msDelay ( 5 );
> WriteByte ( 0x28 ); // 4 bit mode, 2 lines, 5x7
> msDelay ( 5 );
> WriteByte ( 0x08 ); // turn on display and
cursor: non-blinkin
> msDelay ( 5 );
> WriteByte ( 0x01 ); // incr address and shift
cursor with each character
> msDelay ( 5 );
> WriteByte ( 0x06 );
> msDelay ( 5 );
> WriteByte ( 0x0F );
> msDelay ( 5 );
> WriteByte ( 0x01 );
> msDelay ( 5 );
> }
>
> /******************************************************************
***
> Display - display a line of text on the LCD
> argument: address of null terminated text string
>
*******************************************************************/
> void Display ( char *szp )
> { iDataFlag = DATA; //
next bytes are data
> while ( *szp ) WriteByte ( *szp++ );
> }
>
> void Clear ( void )
> { iDataFlag = COMMAND; // set up
for command
> WriteByte ( 0x01 ); //
clear the display
> msDelay (5); //
insure at least 4 msec
> }
>
> void Line2 ( void )
> { iDataFlag = COMMAND; // set up
for command
> WriteByte ( 0xC0 ); //
set RAM address to Line 2
> //note: this value may vary
for different displays
> msDelay (5); //
insure at least 4 msec
> }
> void main ()
> {
>
> LCD_Init ();
> // IMPORTANT - the initialization sequence should
only
> // be executed once after powerup. Multiple
executions
> // will cause the display to malfunction.
> Clear();
> while (1) {
> Clear();
> Display ( "0123456789" );
>
> msDelay (5000);
>
> Clear();
> Display ( "This is a test!" );
> msDelay (5000);
>
> Line2 ();
> Display ( "This is line TWO!" );
> msDelay (5000);
> }
>
> }
>
> Please, help me to find the mistake.
> Thanks.
>

"Some difficulty" means first that I've just one line of my lcd who is
lit. I've try many different connection but nothing works.