/* LCD interface program for using the Atmel AVR to run a Hitachi HD44780 LCD controller */ /* Copyleft (!C) Mark A. Post, mark@eyetap.org, http://www.eyetap.org/~post */ /* Code Version 0.5 alpha, October 1, 2004 */ /* Tested on an AT90S8515 AVR and HD44780-based 2x24 LCD from Active Surplus */ /* Known bugs: polling LCD busy line, reading in general (AVR problem?) */ /* Feel free to notify me of any other problems encountered */ #include #define PINA PINC #define PINB PIND /**********************/ /* Pinout Connections */ /**********************/ /* Most HD44780-based displays use the same pin arrangement. This table shows the pin numbers, their function, and the AVR connections that are used for this program. The AVR ports are named PA0 for port A pin 0, etc, as on an Atmel STK500 board LCD pins are usually in-line starting at board corner, or in a 14-pin ribbon header Use a high-resistance ~1Mohm potentiometer for contrast control, between GND and Vcc AVR ports Function LCD Pins GND (0V) Ground 1 (GND) VTG (+5V) Vcc 2 (Vcc) (pot 0V-5V) Contrast 3 (Vcont) -- connect to GND PB2 (CTRL2) Register Select 4 (RS) PB1 (CTRL1) Read/Write 5 (R/W) PB0 (CTRL0) Edge Enable 6 (E) PD0 (DATA0) Data Bit 0 (LSB) 7 (D0) PD1 (DATA1) Data Bit 1 8 (D1) PD2 (DATA2) Data Bit 2 9 (D2) PD3 (DATA3) Data Bit 3 10(D3) PD4 (DATA4) Data Bit 4 11(D4) PD5 (DATA5) Data Bit 5 12(D5) PD6 (DATA6) Data Bit 6 13(D6) PD7 (DATA7) Data Bit 7 (MSB) 14(D7) Note that PORTA is initialized as an input for switches, and PORTC is initialized as an output for LEDS. This allows for input and output from the AVR itself, e.g. from the STK500 active-low switch/LED headers. */ /***************/ /* AVR Defines */ /***************/ //Speed of microcontroller (in Hz) //The STK500 defaults to 3.68MHz, delay function takes about 3 cycles //This number, though, is based on tests of delay(), and is approximate //#define AVR_FREQ 800000 #define AVR_FREQ 368000 //Convert time in fraction of a second to cycles #define FRACSEC(fs) AVR_FREQ/(fs) #define SECONDS(fs) AVR_FREQ*(fs) //General delay periods #define LCD_WRITE_DELAY FRACSEC(400) #define LCD_LINE_DELAY SECONDS(1) //Data Direction Register Values #define DDR_INPUT 0x00 #define DDR_OUTPUT 0xff /***************/ /* LCD Defines */ /***************/ //LCD dimensions -- used to set text properly #define LCD_COLUMNS 24 #define LCD_ROWS 2 #define LCD_GREYZONE 16 //LCD port mappings -- dependent on AVR wiring #define LCD_DATA_DDR DDRA #define LCD_DATA PORTA #define LCD_DATA_IN PINA #define LCD_CTRL_DDR DDRB #define LCD_CTRL PORTB //HD44780 control pins, bits mapped to EE, R/W, and RS //assuming LCD_CTRL pin0=Edge Enable, pin1=Read/Write, pin2=Reg Select #define LCD_CTRL_EE 0x01 #define LCD_CTRL_READ 0x02 #define LCD_CTRL_WRITE 0x00 #define LCD_CTRL_CHAR 0x04 #define LCD_CTRL_CMD 0x00 //HD44780 command set and command flags, //assuming LCD_DATA pin0 is least significant bit (D0) #define LCD_CLEAR_DISPLAY 0x01 #define LCD_RETURN_HOME 0x02 #define LCD_ENTRY_MODE_SET(flags) (0x04|flags) #define LCD_EMS_CURSOR_RIGHT 0x02 #define LCD_EMS_CURSOR_LEFT 0x00 #define LCD_EMS_DISPLAY_SHIFT 0x01 #define LCD_DISPLAY_CONTROL(flags) (0x08|flags) #define LCD_DC_DISPLAY_ON 0x04 #define LCD_DC_CURSOR_ON 0x02 #define LCD_DC_DISPLAY_OFF 0x00 #define LCD_DC_CURSOR_OFF 0x00 #define LCD_DC_BLINK_CURSOR 0x01 #define LCD_DISPLAY_SHIFT(flags) (0x10|flags) #define LCD_DS_DISPLAY 0x08 #define LCD_DS_CURSOR 0x00 #define LCD_DS_RIGHT 0x04 #define LCD_DS_LEFT 0x00 #define LCD_FUNCTION_SET(flags) (0x20|flags) #define LCD_FS_DATA_LENGTH_8BIT 0x10 #define LCD_FS_DATA_LENGTH_4BIT 0x00 #define LCD_FS_DISPLAY_2LINES 0x08 #define LCD_FS_DISPLAY_1LINE 0x00 #define LCD_FS_FONT_5x10DOT 0x04 #define LCD_FS_FONT_5x8DOT 0x00 #define LCD_SET_CGRAM_ADDRESS(addx) (0x40|(addx&0x3f)) #define LCD_SET_DDRAM_ADDRESS(addx) (0x80|(addx&0x7f)) #define LCD_BUSY_BIT 0x80 #define NEXT_LINE 0xC0 /*****************/ /* AVR Functions */ /*****************/ /* Delay function */ void delay(unsigned long N) { unsigned long n; if(N == 0) return; for (n=0; n