/*============================================================================== lcd.h HITACHI HD44780 4Bit Mode LCD Driver for Small Device C Compiler Written by Ervin Jung (2010) -------------------------------------------------------------------------------- This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. In other words, you are welcome to use, share and improve this program. You are forbidden to forbid anyone else to use, share and improve what you give them. Help stamp out software-hoarding! As a special exception, if you link this library with other files, some of which are compiled with SDCC, to produce an executable, this library does not by itself cause the resulting executable to be covered by the GNU General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU General Public License. -------------------------------------------------------------------------------- defaults: -- INTERNAL NAME --+-- PIC PIN --+-- LCD PIN -- LCD_RS_PIN | RB0 | RS LCD_RW_PIN | RB1 | RW LCD_EN_PIN | RB2 | EN - | - | D0 - | - | D1 - | - | D2 - | - | D3 LCD_DATA1 | RB4 | D4 LCD_DATA2 | RB5 | D5 LCD_DATA3 | RB6 | D6 LCD_DATA4 | RB7 | D7 Busy Pin LCD_BUSY_PIN USE LCD_DATA4_TRIS AND YOU NEED DEFINE PORT TO READ BUSY FLAG ! printf("\c"); // Clear display printf("\n"); // New line example (18F4550 20Mhz PPL5): #include <pic18fregs.h> #define FOSC 48000000 // because PPL5 #include "simple_delay.h" #define LCD_USE_DEFAULTS #define LCD_ROW_COUNT 2 #include "lcd.h" void main(void) { unsigned long int n = 0; lcd_init(); printf("\cIDE for PIC18F"); while(1) { lcd_gotoxy(1,2); printf("N = %ld ", n++); } } -------------------------------------------------------------------------------- you can define custom characters from 0 to 7 (mode 5x7) custom character at code 0: 0. 000 00000 1. 000 00000 2. 000 00000 3. 000 00000 4. 000 00000 5. 000 00000 6. 000 00000 7. 000 11111 = 0x1f = 31 1. char lcd_char0[8] = {0,0,0,0,0,0,0,31}; 2. lcd_init(); 3. lcd_init_char(0, lcd_char0); 4. lcd_send_byte(1, 0); -------------------------------------------------------------------------------- #define LCD_USE_STRING_SHIFT const char buffer[] = " *** HD44780 4BIT LCD DRIVER HTTP://JUNIF.HU\0"; main() { char position = 0; while(1) { lcd_gotoxy(0,1); lcd_string_shift(&position, buffer); delay_ms(250); } } ==============================================================================*/ #ifndef __LCD_H__ #define __LCD_H__ #ifndef LCD_USE_CUSTOM #ifndef LCD_USE_DEFAULTS #ERROR YOU MUST DEFINE LCD PINS ! #endif #endif #include <stdio.h> #include "simple_delay.h" #define LCD_DELAY_1CYCLE delay_cycles(1) #define LCD_DELAY_10CYCLES delay_cycles(10) #define LCD_CMD 0 #define LCD_DATA 1 #ifdef LCD_USE_DEFAULTS #ifndef LCD_RS_PIN #define LCD_RS_PIN LATBbits.LATB0 #endif #ifndef LCD_RW_PIN #define LCD_RW_PIN LATBbits.LATB1 #endif #ifndef LCD_EN_PIN #define LCD_EN_PIN LATBbits.LATB2 #endif #ifndef LCD_RS_TRIS #define LCD_RS_TRIS TRISBbits.TRISB0 #endif #ifndef LCD_RW_TRIS #define LCD_RW_TRIS TRISBbits.TRISB1 #endif #ifndef LCD_EN_TRIS #define LCD_EN_TRIS TRISBbits.TRISB2 #endif #ifndef LCD_BUSY_PIN #define LCD_BUSY_PIN PORTBbits.RB7 // BUSY PIN #endif #ifndef LCD_DATA4 #define LCD_DATA4 LATBbits.LATB7 // BUSY PIN #endif #ifndef LCD_DATA3 #define LCD_DATA3 LATBbits.LATB6 #endif #ifndef LCD_DATA2 #define LCD_DATA2 LATBbits.LATB5 #endif #ifndef LCD_DATA1 #define LCD_DATA1 LATBbits.LATB4 #endif #ifndef LCD_DATA4_TRIS #define LCD_DATA4_TRIS TRISBbits.TRISB7 // BUSY PIN #endif #ifndef LCD_DATA3_TRIS #define LCD_DATA3_TRIS TRISBbits.TRISB6 #endif #ifndef LCD_DATA2_TRIS #define LCD_DATA2_TRIS TRISBbits.TRISB5 #endif #ifndef LCD_DATA1_TRIS #define LCD_DATA1_TRIS TRISBbits.TRISB4 #endif #endif //LCD_USE_DEFAULTS #ifndef LCD_ROW_COUNT #error YOU MUST DEFINE LCD ROW COUNT (2 OR 4) #endif #ifndef LCD_COL_COUNT #define LCD_COL_COUNT 16 #endif #if LCD_ROW_COUNT == 2 #define LCD_LINE0_ADDRESS 0x80 #define LCD_LINE1_ADDRESS 0xC0 #endif #if LCD_ROW_COUNT == 4 #define LCD_LINE0_ADDRESS 0x80 #define LCD_LINE1_ADDRESS 0xC0 #define LCD_LINE2_ADDRESS 0x90 #define LCD_LINE3_ADDRESS 0xD0 #endif /* Clear Display */ #define LCD_CLEAR_DISPLAY 0b00000001 /* Home position */ #define LCD_CURSOR_HOME 0b00000010 /* Entry Mode Control */ #define LCD_ENTRY_CONTROL 0b00000100 #define LCD_CURSOR_INCREMENT 0b00000110 #define LCD_DISPLAY_SHIFT 0b00000101 /* Display Control */ #define LCD_DISPLAY_CONTROL 0b00001000 #define LCD_DISPLAY_ON 0b00001100 #define LCD_CURSOR_ON 0b00001010 #define LCD_CURSOR_BLINK_ON 0b00001001 /* Cursor or Display Shift Control */ #define LCD_SHIFT_CONTROL 0b00010000 #define LCD_CURSOR_SHIFT 0b00011000 #define LCD_CURSOR_SHIFT_LEFT 0b00010100 /* Function Set Control */ #define LCD_FUNCTION_SET 0b00100000 #define LCD_FUNCTION_8BIT 0b00110000 #define LCD_FUNCTION_2LINE 0b00101000 #define LCD_FUNCTION_5x10 0b00100100 //data static char const LCD_INITS[4] = { LCD_FUNCTION_2LINE, LCD_CURSOR_INCREMENT, LCD_CURSOR_SHIFT, LCD_CLEAR_DISPLAY}; #if LCD_ROW_COUNT == 2 static char const LCD_LINES[2] = { LCD_LINE0_ADDRESS, LCD_LINE1_ADDRESS}; #endif #if LCD_ROW_COUNT == 4 static char const LCD_LINES[4] = { LCD_LINE0_ADDRESS, LCD_LINE1_ADDRESS, LCD_LINE2_ADDRESS, LCD_LINE3_ADDRESS}; #endif static void lcd_send_half_byte(char b) __wparam { LCD_DATA4 = b >> 7; LCD_DATA3 = b >> 6; LCD_DATA2 = b >> 5; LCD_DATA1 = b >> 4; LCD_DELAY_1CYCLE; LCD_EN_PIN = 1; delay_us(2); LCD_EN_PIN = 0; } void lcd_send_byte(char mode, char b) { LCD_DATA4_TRIS = 1; do { LCD_RW_PIN = 1; } while (!LCD_BUSY_PIN); LCD_DATA4_TRIS = 0; LCD_DELAY_10CYCLES; LCD_RS_PIN = mode; LCD_RW_PIN = 0; LCD_EN_PIN = 0; LCD_DELAY_10CYCLES; lcd_send_half_byte(b & 0xf0); lcd_send_half_byte(b << 4); } void lcd_init_char(char charcode, char pattern[]) { char i; charcode = (charcode << 3) | 0x40; putchar('\c'); for(i = 0; i < 8; i++) { lcd_send_byte(LCD_CMD, charcode | i); lcd_send_byte(LCD_DATA, pattern[i]); } } void lcd_init(void) { char i; LCD_RS_TRIS = 0; LCD_RW_TRIS = 0; LCD_EN_TRIS = 0; LCD_DATA4_TRIS = 0; LCD_DATA3_TRIS = 0; LCD_DATA2_TRIS = 0; LCD_DATA1_TRIS = 0; delay_ms(25); lcd_send_half_byte(3); delay_ms(10); lcd_send_half_byte(3); delay_us(200); lcd_send_half_byte(3); lcd_send_half_byte(2); for(i = 0; i < 4; i++) lcd_send_byte(LCD_CMD, LCD_INITS[i]); stdout = STREAM_USER; } void lcd_gotoxy(unsigned char x, unsigned char y) { unsigned char addr; if(y >= LCD_ROW_COUNT) y = 0; addr = LCD_LINES[y] + x; lcd_send_byte(LCD_CMD, 0x80 | addr); } void putchar(char c) __wparam { switch (c) { case '\c' : lcd_send_byte(LCD_CMD, LCD_CLEAR_DISPLAY); delay_ms(2); break; case '\n' : lcd_gotoxy(1, 2); break; default : lcd_send_byte(LCD_DATA, c); break; } } #ifdef LCD_USE_STRING_SHIFT #include <string.h> void lcd_string_shift(char * index, char buffer[]) { char i; char j; if(* index > strlen(buffer)) * index = 0; j = * index; for(i = 0; i < LCD_COL_COUNT; i++) { if (j >= strlen(buffer)) j = 0; lcd_send_byte(LCD_DATA, buffer[j++]); } * index += 1; } #endif #endif