Rev 409 | Blame | Compare with Previous | Last modification | View Log | Download
/*******************************************************************************************************
Title : C include file for the HD44780U LCD library (lcd_io.c)
Author: Chris efstathiou hendrix@otenet.gr
Date: 1/Jul/2002
Software: AVR-GCC with AVR-AS
Target: any AVR device
Comments: This software is FREE.
DESCRIPTION
Basic routines for interfacing a HD44780U-based text lcd display
Based on Volker Oth's lcd library (http://members.xoom.com/volkeroth),
Peter Fleury's work <pfleury@gmx.ch> http://jump.to/fleury .
and the very good lcd page at www.myke.com
With this driver you can select from 2 different I/O modes.
1) MODE 6 - 6 or 7 pin I/O mode
2) MODE 2 - 2 pin I/O mode with an additional 74LS174
3) MODE 7 - multiple lcd unit mode
MODE 6 INFORMATION
mode 6 now needs only 6 pins as long the pins can function as output
freeing two bits to be used as general i/o.
R/W pin on the lcd must be connected to ground.
Also the pins can be scattered all over the place (any pin in any port).
( the other pins of the port(s) are not affected )
Be carefull not to change the status of the E lcd pin by using the outp()
command (both in PORT(X) and DDR(X) ) elsewhere in your program otherwise
your program will crash and you will have a lot of fun for the whole family.
Use sbi() and cbi() commands instead.
MODE 7 INFORMATION
mode 7 supports up to 3 lcd units and all the characteristics of mode 6
except that lcd reading is not possible.
The lcd diplays can be of different type.
MODE 2 INFORMATION
mode 2 uses only 2 pins in any combination you want as long the pin
can function as output.
You also need to make a very simple cirquit (really silly) with 74LS174.
See the included JPG photo for the schematic.
Also the pins can be scattered all over the place (any pin in any port).
( the other pins of the port(s) are not affected )
YOU MAY NOT! MULTIPLEX THE DATA AND CLOCK PINS WITH OTHER DEVICES
The pins are automatically set as outputs when you call an lcd function
Be carefull not to change the status of the CLOCK and DATA pins by using the outp()
command (both in PORT(X) and DDR(X) ) elsewhere in your program otherwise
your program will crash and you will have a lot of fun for the whole family (again!).
Use sbi() and cbi() commands instead.
MEMORY MAPPED MODE IS NOT SUPPORTED BY THIS DRIVER !!!
CAUTION!!! FOR SLOW LCD UNITS INCREASE THE "LCD_DELAY_TIME" VALUE!!!
The driver does not read anything back from the lcd because that way i only need 6
I/O lines and furthermore i can use the output only port found in MEGA103.
Since i dont read anything back, i just wait for commands to be executed
so below i define the time to wait for the two categories of commands of HD44780 .
The two CATEGORIES are:
1) 2ms for clear screen and return home commands (nominal value=1,52 ms)
and it is derived from "LCD_DELAY_TIME" .
2) 50us for all other commands (nominal value=37 us)
Even the slowest units will work reliably with LCD_DELAY_TIME=160.
The Longer delay needed for CATEGORY 1 is calculated from the "LCD_DELAY_TIME" value.
The specifications for HD44780 @ 270KHZ are 37 us for CATEGORY 2 and 1,52 ms for CATEGORY 1
LCD MODULE INFORMATION!
The maximum time required by each instruction for the slowest lcd units is
4.1 msecs for clearing the display or moving the cursor/display to the "home position",
160 usecs for all other commands. (i use 50 because i use good units)
Usual HD44780 Pins connections
1 = Ground
2 = Vcc
3 = Contrast Voltage
4 = "R/S" _Instruction/Register Select
5 = "R/W" _Read/Write LCD Registers (Connected to GND for this driver to work!)
6 = "E" Clock
7 - 14 = Data I/O Pins 0 to 7 (0=7, 1=8,... 7=14 )
15 - GND for the BACKLIGHTING (Check to be sure because some units have it for VCC)
16 - VCC for the BACKLIGHTING (Check to be sure because some units have it for GND)
CONNECTION TABLE AS USED IN THIS lcd_io.h FILE
|^^^^^^^^^^^^^^^^^^^^^^^^^^|
| port_pin0->lcd_D4_pin11 |
| port_pin1->lcd_D5_pin12 |
| port_pin2->lcd_D6_pin13 |
| port_pin3->lcd_D7_pin14 |
| port_pin4->lcd_RS_pin4 |
| port_pin5->lcd_E_pin6 |
| lcd_E_pin5->GND |
^^^^^^^^^^^^^^^^^^^^^^^^^^^
*******************************************************************************************************/
#ifndef LCD_IO_H
#define LCD_IO_H
/*############################################################################################*/
/* CONFIGURATION BLOCK STARTS HERE. Change these definitions to adapt setting */
/*############################################################################################*/
/* GLOBAL SETTINGS (settings described here are aplyied everywhere) */
#ifndef F_CPU
#define F_CPU 3686400L /* CPU CLOCK FREQUENCY */
#endif
#define LCD_IO_MODE 6 /* 6 = 6 PIN I/O, 2 = 2 PIN I/O, 7 = multi lcd mode */
#define LCD_AUTO_LINE_FEED 0 /* 1 = Auto line feed, 0 = no Auto line feed */
#define LCD_DELAY_TIME 100 /* Read the INTRO about this */
/***********************************************************************************************/
#if LCD_IO_MODE == 2
/*
CONFIGURATION OF BELOW LINES ONLY NECESSARY IN 2 PIN MODE
If you plan to use just one port for all pins then just edit "LCD_PORT"
otherwise you must specify the port of each lcd signal. the port(s) must be able
to function as output. It can be any combination!
USE CAPITAL LETTER FOR PORT DESIGNATION! (A,B,C,D...etc.)
*/
#define LCD_CHARS_PER_LINE 20 /* visible chars per lcd line */
#define LCD_LINES 4 /* visible lines */
#define LCD_PORT B
#define LCD_CLOCK_SIGNAL_PORT LCD_PORT /* Put your lcd clock port here (A,B,C...etc.) */
#define LCD_CLOCK_PIN 0 /* Put your lcd clock pin here */
#define LCD_DATA_SIGNAL_PORT LCD_PORT /* Put your lcd data port here (A,B,C...etc.) */
#define LCD_DATA_PIN 1 /* Put your lcd data pin here */
#endif
/***********************************************************************************************/
/* END OF 2 PIN CONFIGURATION BLOCK */
/***********************************************************************************************/
#if LCD_IO_MODE == 6
/*
CONFIGURATION OF BELOW LINES ONLY NECESSARY IN MODE 6
If you plan to use just one port for all pins then just edit "LCD_PORT"
otherwise you must specify the port of each lcd signal. the port(s) must be able
to function as output. It can be any combination!
PUT YOUR LCD PORT LETTER HERE USING CAPITAL LETTER (A,B,C,D...etc)
*/
#define LCD_CHARS_PER_LINE 20 /* visible chars per lcd line */
#define LCD_LINES 4 /* visible lines */
#define LCD_MULTIPLEX_ENABLE 0 /* 1= the DDR's used are saved and restored */
#define LCD_READ_REQUIRED 0 /* 0=use delay, 1=read busy flag (7 pins needed) */
#define LCD_PORT B
#define LCD_DATA4_PORT LCD_PORT /* port for data 0 pin */
#define LCD_D4_PIN 0 /* AVR port pin number */
#define LCD_DATA5_PORT LCD_PORT /* port for data 1 pin */
#define LCD_D5_PIN 1 /* AVR port pin number */
#define LCD_DATA6_PORT LCD_PORT /* port for data 2 pin */
#define LCD_D6_PIN 2 /* AVR port pin number */
#define LCD_DATA7_PORT LCD_PORT /* port for data 3 pin */
#define LCD_D7_PIN 3 /* AVR port pin number */
#define LCD_RS_SIGNAL_PORT LCD_PORT /* port for RS line */
#define LCD_RS_PIN 4 /* AVR port pin number */
#define LCD_E_SIGNAL_PORT LCD_PORT /* port for Enable line */
#define LCD_E_PIN 5 /* AVR port pin number */
/* YOU NEED TO EDIT "LCD_RW_SIGNAL_PORT" AND "LCD_RW_PIN" ONLY IF "LCD_READ_REQUIRED == 1" */
#if LCD_READ_REQUIRED == 1
#define LCD_RW_SIGNAL_PORT LCD_PORT /* port for R/W line */
#define LCD_RW_PIN 6 /* AVR port pin number */
#endif
#endif
/***********************************************************************************************/
/* END OF 6 PIN CONFIGURATION BLOCK */
/***********************************************************************************************/
#if LCD_IO_MODE == 7
/*
CONFIGURATION OF BELOW LINES ONLY NECESSARY IN MODE 7
If you plan to use just one port for all pins then just edit "LCD_PORT"
otherwise you must specify the port of each lcd signal. the port(s) must be able
to function as output. It can be any combination!
PUT YOUR LCD PORT LETTER HERE USING CAPITAL LETTER (A,B,C,D...etc)
*/
#define NUMBER_OF_LCD_UNITS 2 /* 2 or 3. if you set it to 1, mode 6 will be selected */
#define LCD_0_CHARS_PER_LINE 20 /* visible chars per lcd line */
#define LCD_0_LINES 4 /* visible lines */
#define LCD_1_CHARS_PER_LINE 20 /* visible chars per lcd line */
#define LCD_1_LINES 4 /* visible lines */
#if NUMBER_OF_LCD_UNITS >=3
#define LCD_2_CHARS_PER_LINE 20 /* visible chars per lcd line */
#define LCD_2_LINES 4 /* visible lines */
#endif
#define LCD_PORT B
#define LCD_DATA4_PORT LCD_PORT /* port for data 0 pin */
#define LCD_D4_PIN 0 /* AVR port pin number */
#define LCD_DATA5_PORT LCD_PORT /* port for data 1 pin */
#define LCD_D5_PIN 1 /* AVR port pin number */
#define LCD_DATA6_PORT LCD_PORT /* port for data 2 pin */
#define LCD_D6_PIN 2 /* AVR port pin number */
#define LCD_DATA7_PORT LCD_PORT /* port for data 3 pin */
#define LCD_D7_PIN 3 /* AVR port pin number */
#define LCD_RS_SIGNAL_PORT LCD_PORT /* port for RS line */
#define LCD_RS_PIN 4 /* AVR port pin number */
#define LCD_0_E_SIGNAL_PORT LCD_PORT /* port for Enable line */
#define LCD_0_E_PIN 5 /* AVR port pin number */
#define LCD_1_E_SIGNAL_PORT LCD_PORT /* port for Enable line */
#define LCD_1_E_PIN 6 /* AVR port pin number */
/* EDIT THE BELOW LINES IF YOU USE 3 LCD UNITS */
#if NUMBER_OF_LCD_UNITS >=3
#define LCD_2_E_SIGNAL_PORT LCD_PORT /* port for Enable line */
#define LCD_2_E_PIN 7 /* AVR port pin number */
#endif
#endif /* LCD_IO_MODE == 7 */
/*############################################################################################*/
/* CONFIGURATION BLOCK ENDS HERE. */
/*############################################################################################*/
/* you shouldn't need to change anything below this line */
/* Some clever thinking triks */
#if LCD_IO_MODE == 7 && NUMBER_OF_LCD_UNITS == 1
#undef LCD_IO_MODE
#define LCD_IO_MODE 6
#define LCD_READ_REQUIRED 0
#define LCD_E_SIGNAL_PORT LCD_0_E_SIGNAL_PORT
#define LCD_E_PIN LCD_0_E_PIN
#define LCD_CHARS_PER_LINE LCD_0_CHARS_PER_LINE
#define LCD_LINES LCD_0_LINES
#undef LCD_MULTIPLEX_ENABLE
#define LCD_MULTIPLEX_ENABLE 0
#undef LCD_READ_REQUIRED
#define LCD_READ_REQUIRED 0
#undef LCD_1_CHARS_PER_LINE
#undef LCD_1_LINES
#undef LCD_1_E_SIGNAL_PORT
#undef LCD_1_E_PIN
#elif LCD_IO_MODE == 7 && NUMBER_OF_LCD_UNITS > 1
#define LCD_0 0
#define LCD_1 1
#define LCD_2 2
#endif /* #if LCD_IO_MODE == 7 && NUMBER_OF_LCD_UNITS == 1 */
/*-----------------------------------------------------------------------------------*/
/* HD44780 PARAMETERS */
/*-----------------------------------------------------------------------------------*/
#define LCD_LINE_LENGTH 0x40 /* internal line length */
#define LCD_START_LINE1 0x00 /* DDRAM address of first char of line 1 */
#define LCD_START_LINE2 0x40 /* DDRAM address of first char of line 2 */
#define LCD_START_LINE3 0x14 /* DDRAM address of first char of line 3 */
#define LCD_START_LINE4 0x54 /* DDRAM address of first char of line 4 */
/* instruction register bit positions */
#define LCD_CLR 0 /* DB0: clear display */
#define LCD_HOME 1 /* DB1: return to home position */
#define LCD_ENTRY_MODE 2 /* DB2: set entry mode */
#define LCD_ENTRY_INC 1 /* DB1: 1=increment, 0=decrement */
#define LCD_ENTRY_SHIFT 0 /* DB2: 1=display shift on */
#define LCD_ON 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-> 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_10DOTS 2 /* DB2: 5x10 font (0->5x7 font) */
#define LCD_CGRAM 6 /* DB6: set CG RAM address */
#define LCD_DDRAM 7 /* DB7: set DD RAM address */
#define LCD_BUSY 7 /* DB7: LCD is busy */
/* set entry mode: display shift on/off, dec/inc cursor move direction */
#define LCD_ENTRY_DEC 0x04 /* display shift off, dec cursor move dir */
#define LCD_ENTRY_DEC_SHIFT 0x05 /* display shift on, dec cursor move dir */
#define LCD_ENTRY_INC_ 0x06 /* display shift off, inc cursor move dir */
#define LCD_ENTRY_INC_SHIFT 0x07 /* display shift on, inc cursor move dir */
/* display on/off, cursor on/off, blinking char at cursor position */
#define LCD_DISP_OFF 0x08 /* display off */
#define LCD_DISP_ON 0x0C /* display on, cursor off */
#define LCD_DISP_ON_BLINK 0x0D /* display on, cursor off, blink char */
#define LCD_DISP_ON_CURSOR 0x0E /* display on, cursor on */
#define LCD_DISP_ON_CURSOR_BLINK 0x0F /* display on, cursor on, blink char */
/* move cursor/shift display */
#define LCD_MOVE_CURSOR_LEFT 0x10 /* move cursor left (decrement) */
#define LCD_MOVE_CURSOR_RIGHT 0x14 /* move cursor right (increment) */
#define LCD_MOVE_DISP_LEFT 0x18 /* shift display left */
#define LCD_MOVE_DISP_RIGHT 0x1C /* shift display right */
/* function set: set interface data length and number of display lines */
#define LCD_FUNCTION_4BIT_1LINE 0x20 /* 4-bit interface, single line, 5x7 dots */
#define LCD_FUNCTION_4BIT_2LINES 0x28 /* 4-bit interface, dual line, 5x7 dots */
#define LCD_FUNCTION_8BIT_1LINE 0x30 /* 8-bit interface, single line, 5x7 dots */
#define LCD_FUNCTION_8BIT_2LINES 0x38 /* 8-bit interface, dual line, 5x7 dots */
#define LCD_MODE_DEFAULT ((1<<LCD_ENTRY_MODE) | (1<<LCD_ENTRY_INC) )
/*-----------------------------------------------------------------------------------*/
/* function prototypes */
/*-----------------------------------------------------------------------------------*/
extern void lcd_init(void);
extern void lcd_command(unsigned char cmd);
extern void lcd_gotoxy(unsigned char lcd_x, unsigned char lcd_y);
extern void lcd_clrscr(void);
extern void lcd_clrline(unsigned char line);
extern void lcd_home(void);
extern void lcd_putc(unsigned char c);
extern void lcd_puts(const unsigned char *s);
extern void lcd_puts_p(const unsigned char *progmem_s);
extern void lcd_puts_e(unsigned char *eeprom_s);
extern void lcd_puti(int value, unsigned char dot_position);
extern unsigned int lcd_getxy(void);
/*
1) Suppose we want to display a 16 bit var with a rvalue 0f 325
2) We give the command lcd_puti(var_name, 0); were var=325
The display will show 325
3) alternatives:
a) We give the command lcd_puti(var_name,1);
The display will show 32,5
b) We give the command lcd_puti(var_name,2);
The display will show 3,25
c) We give the command lcd_puti(var_name,3);
The display will show 0,325
d) We give the command lcd_puti(var_name,4);
The display will show 0,0325
e) We give the command lcd_puti(var_name,1); var=-325
The display will show -32,5
f) We give the command lcd_puti(var_name,3); var=-325
The display will show -0,325
*/
/*
** macros for automatically storing string constant in program memory
*/
#ifndef P
#define P(s) ({static const char c[] __attribute__ ((progmem)) = s;c;})
#endif
#define lcd_puts_P(__s) lcd_puts_p(P(__s))
#endif //LCD_IO_H
/*######################################################################################################*/
/* T H E E N D */
/*######################################################################################################*/