#include <avr/io.h>
/*
* Permission to use, copy, modify, distribute and sell this software and its documentation for any purpose is hereby granted without fee, provided that the below copyright notice appears in all copies and that both the copyright notice and this permission notice appear in supporting documentation. Livingston Electronics makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty.
*
*
* 8 BIT
LCD control program
* Written by Carl W. Livingston
* Modified in a attempt to get working by some other guy
* Copyright Carl W. Livingston
*
microcarl@roadrunner.com
* AVR Freaks member - microcarl
* January 02, 2007
* */
/* //// From the
LCD perspective \\\\
LCD:R/W <-- PORTD:4
LCD:RS <-- PORTD:5
LCD:E <-- PORTD:6
N/A <-> PORTD:7
LCD:R/W <-- PORTD:4
LCD:RS <-- PORTD:5
LCD:E <-- PORTD:6
LCD:Vee <-- CONTRAST
LCD:DB0 <-- PORTB:0
LCD:DB1 <-- PORTB:1
LCD:DB2 <-- PORTB:2
LCD:DB3 <-- PORTB:3
LCD:DB4 <-- 4.7K Ohm <-- PORTx:4
LCD:DB5 <-- 4.7K Ohm <-- PORTx:5
LCD:DB6 <-- 4.7K Ohm <-- PORTx:6
LCD:DB7 <-- 4.7K Ohm <-- PORTx:7
//// From the I/O PORTD perspective \\\\
PORTD:4 -->
LCD:R/W
PORTD:5 -->
LCD:RS
PORTD:6 -->
LCD:E
PORTD:7 <-> N/A
PORTB:0 -->
LCD:DB0
PORTB:1 -->
LCD:DB1
PORTB:2 -->
LCD:DB2
PORTB:3 -->
LCD:DB3
PORTB:4 --> 4.7K Ohm -->
LCD:DB4
PORTB:5 --> 4.7K Ohm -->
LCD:DB5
PORTB:6 --> 4.7K Ohm -->
LCD:DB6
PORTB:7 --> 4.7K Ohm -->
LCD:DB7
*/
/*************************************************************/
/*************************************************************/
// If you want to use a different I/O port for
LCD control & data,
// do it here!!!
#define LCD_DATA_OUT PORTB
#define LCD_DATA_IN PINB
#define LCD_DATA_DDR DDRB
#define LCD_CONTROL_OUT PORTD
#define LCD_CONTROL_IN PIND
#define LCD_CONTROL_DDR DDRD
// Define
LCD Read/Write as PORTx, 0x10;
#define LCD_RW 4
// Define
LCD Register Select as PORTx, 0x20;
#define LCD_RS 5
// Define
LCD Enable as PORTx, 0x40;
#define LCD_E 6
/*************************************************************/
/*************************************************************/
//
LCD busy status bit
#define LCD_BUSY 7
// LED control bit
#define LED 1
// BAUD rate control bits
#define J_1 2
#define J_2 3
#define CGRAM 6
// Turn on power to the display, no cursor
#define PWR_ON 0x0C
// Set 8 data bits
#define DATA_8 0x30
// Set 8 data bits, 4 display lines
#define LINE_8x4 0x38
// Clear display command
#define CLR_DSP 0x01
// Character generator RAM command
#define REG_MODE 0xFE
#define NULL 0x00
void LCD_Delay (unsigned int);
void LCD_PutCmd (char);
void LCD_PutChar (char);
char LCD_BusyWait (void);
void IO_INIT (void);
void LCD_INIT (void);
int main (void) {
// Initialize the Mega16 I/O
IO_INIT ();
// Initialize the HD44780
LCD controller
LCD_INIT ();
while (1) {
LCD_PutChar('b');
}
}
// Clock cycle = 67nS @ 14.7456MHz
// Delay resolution ~ 1uS @ 14.7456MHz
void LCD_Delay (unsigned int d) {
while (d-- != 0)
;
asm("nop"); // Make the delay time a bit closer to the predicted delay time.
// Experimentally setup with an Oscilloscope.
}
void LCD_PutCmd (char Cmd) {
LCD_CONTROL_OUT &= ~(1<<LCD_RS);
LCD_BusyWait();
LCD_DATA_OUT = Cmd;
asm ("nop");
LCD_CONTROL_OUT |= (1<<LCD_E);
asm ("nop"); // PWeh must be 230nS minimum
asm ("nop"); // nop = 67nS @ 14.7456MHz
asm ("nop");
asm ("nop"); // Here, E = 271nS @ 14.7456MHz
LCD_CONTROL_OUT &= ~(1<<LCD_E);
asm ("nop");
LCD_CONTROL_OUT |= (1<<LCD_RS);
}
void LCD_PutChar (char c) {
LCD_CONTROL_OUT &= ~(1<<LCD_RS);
LCD_BusyWait();
LCD_CONTROL_OUT |= (1<<LCD_RS);
LCD_DATA_OUT = c;
asm ("nop");
LCD_CONTROL_OUT |= (1<<LCD_E);
asm ("nop"); // PWeh must be 230nS minimum
asm ("nop"); // nop = 67nS @ 14.7456MHz
asm ("nop");
asm ("nop"); // Here, E = 271nS @ 14.7456MHz
LCD_CONTROL_OUT &= ~(1<<LCD_E);
}
char LCD_BusyWait (void) {
unsigned char LCDStatus;
LCD_DATA_DDR = 0x00; // Set
LCD data port to inputs
LCD_CONTROL_OUT |= (1<<LCD_RW);
asm ("nop");
do {
LCD_CONTROL_OUT |= (1<<LCD_E);
asm ("nop"); // PWeh must be 230nS minimum
asm ("nop"); // nop = 67nS @ 14.7456MHz
asm ("nop");
asm ("nop"); // Here, E = 271nS @ 14.7456MHz
LCDStatus = LCD_DATA_IN;
LCD_CONTROL_OUT &= ~(1<<LCD_E);
} while ((LCDStatus & (1<<LCD_BUSY)) == (1<<LCD_BUSY));
LCD_CONTROL_OUT &= ~(1<<LCD_RW);
LCD_DATA_DDR |= 0xFF; // Set
LCD data port to outputs
return (LCDStatus);
}
void IO_INIT (void) {
LCD_Delay (60000); // Wait for the
LCD display to boot up
// Set J_2:J_1 PULL-UPS active
LCD_CONTROL_OUT = (1<<J_2) | (1<<J_1);
// Set LCD_control J_2:J_1 to inputs
LCD_CONTROL_DDR = 0xF2;
LCD_CONTROL_OUT |= (1<<LCD_RS); // Set LCD_RS HIGH
// Delay resolution ~ 1uS @ 14.7456MHz
LCD_Delay (15000); // Need 15mS delay for
LCD to power up
// Initialize the AVR controller I/O
LCD_DATA_DDR = 0xFF; // Set LCD_DATA_OUT as all outputs
LCD_DATA_OUT = 0x00; // Set LCD_DATA_OUT to logic low
}
void LCD_INIT (void) {
// Initialize the
LCD controller
LCD_PutCmd (LINE_8x4); // Set 8 bit data, 4 display lines
LCD_PutCmd (CLR_DSP); // Power up the display
LCD_PutCmd (PWR_ON); // Power up the display
LCD_Delay (30000);
LCD_BusyWait();
}