0,0 → 1,384 |
/******************************************************************************************************* |
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 */ |
/*######################################################################################################*/ |
|
|