[En-Nut-Discussion] new to nutos usage

Paolo Simoncelli simonp at email.it
Mon Jun 21 12:57:32 CEST 2010


Hi all,

sorry zvonko, but i have had no good luck with LCD displays
and ethernut, here is my experience:


At first i haven't been able to make Jose's code work,

it's using the builtin driver: (quite old post ...)
http://lists.egnite.de/pipermail/en-nut-discussion/2007-March/007990.html

maybe there's an open bug for that:
http://sourceforge.net/tracker/?func=detail&aid=2995417&group_id=34079&atid=410687
(BTW i will be glad to contribute for a fix ;-) )

Next i went to the code reported on "Ethernut application note 001"
but it did not even compiled at first (some editing needed,
maybe it refers to old NutOS/Ethernut versions) anyway no luck at all :-(

So, based on appnote001 sw & hw wiring, i wrote my own code,
here follows a basic example, i have left the appnote001 comments
plus some spaghetti programming examples ;-)
sorry for the long post hope it will help ! ciao !




//  -- LCD ------------------------------------------------------------


/*
Instruction  	          Code                            Description
                         D7  D6  D5  D4  D3  D2  D1  D0
Clear display 	        0   0   0   0   0   0   0   1 	Clears display and returns cursor to the home position (address 0). 	1.64mS
Cursor home 	          0   0   0   0   0   0   1   * 	Returns cursor to home position (address 0). Also returns display being 
shifted to the original position. DDRAM contents remains unchanged. 	1.64mS
Entry mode set 	        0   0   0   0   0   1   I/D S 	Sets cursor move direction (I/D), specifies to shift the display (S). 
These operations are performed during data read/write. 	40uS
Display On/Off control 	0   0   0   0   1   D   C   B 	Sets On/Off of all display (D), cursor On/Off (C) and blink of cursor 
position character (B). 	40uS
Cursor/display shift 	  0   0   0   1   S/C R/L *   * 	Sets cursor-move or display-shift (S/C), shift direction (R/L). DDRAM 
contents remains unchanged. 	40uS
Function set 	          0   0   1   DL  N   F   *   * 	Sets interface data length (DL), number of display line (N) and character 
font(F). 	40uS
Set CGRAM address 	    0   1   CGRAM address           Sets the CGRAM address. CGRAM data is sent and received after this 
setting. 	40uS
Set DDRAM address 	    1   DDRAM address 	            Sets the DDRAM address. DDRAM data is sent and received after this 
setting. 	40uS

Read busy-flag and address counter 	0 	1 	BF 	CGRAM / DDRAM address 	Reads Busy-flag (BF) indicating internal operation is being 
performed and reads CGRAM or DDRAM address counter contents (depending on previous instruction). 	0uS
Write to CGRAM or DDRAM 	1 	0 	write data 	Writes data to CGRAM or DDRAM. 	40uS
Read from CGRAM or DDRAM 	1 	1 	read data 	Reads data from CGRAM or DDRAM. 	40uS
Remarks:

*/


// HD44780 Commandset

//  01h  	Clear display
#define LCD_CLR             0      // DB0: clear display

//  02h or 03h 	Return cursor home
#define LCD_HOME            1      // DB1: return to home position

//  04h 05h 06h 07h Entry mode set
#define LCD_ENTRY_MODE      2      // DB2: set entry mode
#define LCD_ENTRY_INC       1      //   DB1: increment
#define LCD_ENTRY_SHIFT     0      //   DB2: shift

//  08h 09h 0Ah 0Bh   0Ch 0Dh 0Eh 0Fh  Display/Cursor ON OFF
#define LCD_ON_CTRL         3      // DB3: turn lcd/cursor on
#define LCD_ON_DISPLAY      2      //   DB2: turn display on
#define LCD_ON_CURSOR       1      //   DB1: turn cursor on
#define LCD_ON_BLINK        0      //   DB0: blinking cursor

#define LCD_MOVE            4      // DB4: move cursor/display
#define LCD_MOVE_DISP       3      //   DB3: move display (0-> move cursor)
#define LCD_MOVE_RIGHT      2      //   DB2: move right (0-> left)

#define LCD_FUNCTION        5      // DB5: function set
#define LCD_FUNCTION_8BIT   4      //   DB4: set 8BIT mode (0->4BIT mode)
#define LCD_FUNCTION_2LINES 3      //   DB3: two lines (0->one line)
#define LCD_FUNCTION_RE     2      //   DB2: KS0073 Controller: Extended Register
#define LCD_FUNCTION_10DOTS 2      //   DB2: 5x10 font (0->5x7 font)
#define LCD_FUNCTION_DS     1      //   DB1: DisplayShift / DotScroll
#define LCD_FUNCTION_REV    0      //   DB0: Reverse Display

#define LCD_EXT             3      // DB3: Extended Register Set
#define LCD_EXT_FONT        2      //   DB2: Fontwidth: 5 / 6 Pixel
#define LCD_EXT_INVCURS     1      //   DB1: Normal / Inverted Cursor
#define LCD_EXT_4LINES      0      //   DB0: 1/2 Lines (normal) or 4Lines

#define LCD_CGRAM           6      // DB6: set CG RAM address

#define LCD_DDRAM           7      // DB7: set DD RAM address
// reading:
#define LCD_BUSY            7      // DB7: LCD is busy



//  Initializing the LCD
//  Some definitions first. As we find in the schematic, the LCD data port is connected to
//  the upper 4 bits of port D.

#define LCD_DATA_DDR DDRD
#define LCD_DATA_PORT PORTD

//  The two control lines are connected to bits 2 and 3 of port E.

#define LCD_CTRL_DDR DDRE
#define LCD_CTRL_PORT PORTE
#define LCD_CTRL_E PE3
#define LCD_CTRL_RS PE2
#define LCD_CTRL_RW PE4

//  The LCD backlight is controlled by bit 6 on port B. (no backlight for now ...)

// #define LCD_LIGHT_DDR DDRB
// #define LCD_LIGHT_PORT PORTB
// #define LCD_LIGHT_BIT PB6

//  Various delays

#define LCD_PWRON_DELAY 10
#define LCD_INIT_DELAY 4
#define LCD_LONG_DELAY 2
#define LCD_SHORT_DELAY 1



//  Controlling the LCD
//  The initialization routine already uses other subroutines to send data bytes and
//  instructions to the LCD controller. Remember, that we drive the LCD in 4 bit mode. A
//  special routine named LcdSendNibble will send the upper four bits of a character
//  variable to the LCD data port. It sets the data lines and toggles the enable line.

static inline void LcdSendNibble(u_char nib)
{
     outp((inp(LCD_DATA_PORT) & 0x0F) | (nib & 0xF0), LCD_DATA_PORT);
     sbi(LCD_CTRL_PORT, LCD_CTRL_E);
     asm volatile("nop\n\tnop");
     cbi(LCD_CTRL_PORT, LCD_CTRL_E);
}



//  Another routine called LcdSendByte sends a complete byte to the LCD controller by
//  calling LcdSendNibble twice.

static inline void LcdSendByte(u_char ch, u_char xt)
{
     LcdSendNibble(ch & 0xF0);
     LcdSendNibble(ch << 4);
     NutDelay(xt);
}



//  Finally two additional routines are provided to either send an instruction or a data byte.
//  Note, that only instructions need a specific delay time.

static void LcdWriteCmd(u_char cmd, u_char xt)
{
     cbi(LCD_CTRL_PORT, LCD_CTRL_RS);
     LcdSendByte(cmd, xt);
}

void LcdWriteChar(u_char ch)
{
     sbi(LCD_CTRL_PORT, LCD_CTRL_RS);
     LcdSendByte(ch,LCD_SHORT_DELAY);
}


void LcdWriteS(char *ch)
{
int i;
char c;

     i=0;
     while((c=ch[i++])>0){		
         LcdWriteChar(c);
     }
}


//  One of the most often used instructions to be send to the display is the clear
//  command, which blanks the display. A special routine LcdClear will do this.

void LcdClear(void)
{
     LcdWriteCmd(LCD_HOME,LCD_LONG_DELAY);
}


//  The initialization routine uses another command routine named LcdSwitch, which
//  switches on and off certain mode bits in the LCD controller.

void LcdSwitch(u_char on, u_char off)
{
//      switch_control |= on & LCD_SWITCH_ALL;
//      switch_control &= ~(off & LCD_SWITCH_ALL);
//      LcdWriteCmd(switch_control, LCD_SHORT_DELAY);
}


//  When calling LcdWriteChar instead of LcdWriteCmd, the characters of the specified
//  codes are displayed and the cursor is automatically advanced to the next character
//  position. In addition to the normal 7 bit ASCII character set the controller can display
//  many other characters. It is even possible to define up to 8 custom characters, which
//  however isn't explained in this application note.



//  The LCD controller doesn't support cursor positioning on a specific column or row, but
//  requires a memory address. This is not a big deal on 2 line displays, but address
//  locations for the third and the second row depend on the number of columns being
//  displayed. On 4 line displays with 16 columns each, the values are:

//  #define LCD_ROW2_START 0x10
//  #define LCD_ROW3_START 0x50
#define LCD_ROW2_START 0x14
#define LCD_ROW3_START 0x54


//  Another routine called LcdSetCursor may be used to place the cursor to a specific
//  position.

void LcdSetCursor(u_char row, u_char col)
{
u_char row_start[] = { 0x00, 0x40, LCD_ROW2_START, LCD_ROW3_START };

     LcdWriteCmd(0x80 | row_start[row & 0x03] | col, LCD_SHORT_DELAY);
}



//   routine called LcdSetCursor may be used to place the cursor to a specific
//  position.

void LcdWriteAt(u_char row, u_char col, char *ch)
{
     LcdSetCursor(row,col);
     LcdWriteS(ch);
}



// A single routine is used to initialize all I/O lines and setup the LCD. Most notable is the
//  for loop somewhere in the middle of the routine. When the LCD is powered up, the
//  LCD controller will start in 8 bit mode. Switching it into 4 bit mode requires a specific
//  command sequence. The loop will send three nibbles of value 3, two of value 2 and
//  finally of value 8.

void LcdInit(void)
{
u_char i;


/*
* Set LCD read write low.
*/
     cbi(LCD_CTRL_PORT, LCD_CTRL_RW);
     sbi(LCD_CTRL_DDR, LCD_CTRL_RW);

/*
* Set LCD register select low.
*/
     cbi(LCD_CTRL_PORT, LCD_CTRL_RS);
     sbi(LCD_CTRL_DDR, LCD_CTRL_RS);

/*
* Set LCD enable low.
*/
     cbi(LCD_CTRL_PORT, LCD_CTRL_E);
     sbi(LCD_CTRL_DDR, LCD_CTRL_E);

/*
* Set direction register of LCD data port.
*/
     sbi(LCD_DATA_DDR, 4);
     sbi(LCD_DATA_DDR, 5);
     sbi(LCD_DATA_DDR, 6);
     sbi(LCD_DATA_DDR, 7);

/*
* Initialize for 4-bit operation.
*/
     NutDelay(LCD_PWRON_DELAY);
     for(i = 0;i<3; i++){
         LcdSendNibble(0x30);
         NutDelay(LCD_INIT_DELAY);
     }

     LcdSendNibble(0x20);
     NutDelay(LCD_SHORT_DELAY);

/*
* 4-bit mode, 2/4 lines, 5x7 matrix.
*/
     LcdWriteCmd(0x28,LCD_SHORT_DELAY);

/*
* Switch display, cursor and cursor blinking off.
*/
//      LcdSwitch(0, LCD_SWITCH_ALL);

/*
* Clear display.
*/
     LcdClear();

/*
* Increment cursor when writing.
*/
     LcdWriteCmd((1<<LCD_ENTRY_MODE|1<<LCD_ENTRY_INC|0<<LCD_ENTRY_SHIFT),LCD_SHORT_DELAY);

/*
* Set cursor appearance
*/
     LcdWriteCmd((1<<LCD_ON_CTRL|1<<LCD_ON_DISPLAY|1<<LCD_ON_CURSOR|1<<LCD_ON_BLINK),LCD_SHORT_DELAY);


/*
* Lit LED and switch display on.
*/
//    sbi(LCD_LIGHT_DDR, LCD_LIGHT_BIT);
//    sbi(LCD_LIGHT_PORT, LCD_LIGHT_BIT);
//    LcdSwitch(LCD_SWITCH_DISPLAY, 0);

}


//  -- END LCD --------------------------------------------------------






 
 
 --
 Caselle da 1GB, trasmetti allegati fino a 3GB e in piu' IMAP, POP3 e SMTP autenticato? GRATIS solo con Email.it http://www.email.it/f
 
 Sponsor:
 Sardegna - Stintino Club Hotel CALA ROSA, 4 stelle. Situato in parco di 4  ettari, dotato dei migliori servizi. dal 24/7 al 31/7 SETTE giorni TUTTO COMPRESO Euro 690
 Clicca qui: http://adv.email.it/cgi-bin/foclick.cgi?mid=10590&d=21-6



More information about the En-Nut-Discussion mailing list