RatFink
Joined: 01 May 2004 Posts: 49
|
LCD driver |
Posted: Sat May 15, 2004 12:07 pm |
|
|
I'm posting this here because I spent a long time looking for a driver that worked for me, I finally found this hidden in the back pages of the forum, it worked right off the bat for me. and was originally posted by a member named chava in this thread;
http://www.ccsinfo.com/forum/viewtopic.php?t=17323&highlight=picdem+2
Since I'm a beginner at this and had already spent a week trying to get my LCD to work, finding code that work for me very easily seemed like something others would find helpfull.
BTW, I'm using a PIC16F877A w/ a CrystalFontz LCD w/ aHD44780 compatible controller.
Code: | //////////////////// LCD //////////////////////////////
// As defined in the following structure the pin connection is as follows:
// A1 enable
// A2 rw
// A3 rs
// D0 D4
// D1 D5
// D2 D6
// D3 D7
//
// LCD pins D0-D3 are not used and PIC D3 is not used.
//****************************************************************************************
#if defined(__PCH__)
#byte lcd = 0xF83 // This puts the entire structure
#else
#byte lcd = 8 // on to port D (at address 8)
#endif
//****************************************************************************************
#define lcd_type 2 // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40 // LCD RAM address for the second line
BYTE const LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6};
// These bytes need to be sent to the LCD
// to start it up.
// for 2 lines lcd: {0x0a,0xc,1,6}
// for 5x10 lcd: {0x06,0xc,1,6}
// for 5x7 lcd: {0x20,0xc,1,6}
// The following are used for setting
// the I/O port direction register.
//***** lcd command port *******************************************************************
struct lcd_command{
char none:1;
char enable:1;
char read_write:1;//rw
char data_command:1;//rs
};
struct lcd_command lcd_command_port;
#locate lcd_command_port=5
//---------------------------------------------------
struct lcd_data{
char data:4;
};
struct lcd_data lcd_data_port;
#locate lcd_data_port=8
//************ "COMMAND / DATA definition ************************************************************
#define COMMAND0 0
#define DATA1 1
//************ "READ / WRITE definition ************************************************************
#define WRITE0 0 //LCD <- MPU
#define READ1 1 //LCD -> MPU
//************ "E_UP / E_DOWN definition ************************************************************
#define E_DOWN 0
#define E_UP 1
//**********eeprom or flash******************************************************************************
#define EEPROM0 0 ;eeprom - not the program memory
#define FLASH1 1 ;program memory
//********* set tris d *********************************************************************
#define set_tris_lcd_read(){\
set_tris_a(TRISA & 0xf1/*0b11110001*/);\
set_tris_d(TRISD | 0x0f/*0b00001111*/);\
}
#define set_tris_lcd_write(){\
set_tris_a(TRISA & 0xf1/*0b11110001*/);\
set_tris_d(TRISD & 0xf0/*0b11110000*/);\
}
//*********** clear LCD ************************************
#define clear_lcd lcd_send_byte(0x1,COMMAND0);//clear lcd display
//****************************************************************************************
//************************************************************
char lcd_read_byte(void){
char low,high;
set_tris_lcd_read();
lcd_command_port.read_write = READ1;
delay_cycles(1);
lcd_command_port.enable = E_UP;
delay_cycles(1);
high = lcd_data_port.data & 0x0f;
lcd_command_port.enable = E_DOWN;
delay_cycles(1);
lcd_command_port.enable = E_UP;
delay_us(1);
low = lcd_data_port.data & 0x0f;
lcd_command_port.enable = E_DOWN;
set_tris_lcd_write();
return( (high << 4) | low);
}
//*************** - - *********************************************
void lcd_write_nibble(char temp_wr){
//Purpose:
lcd_data_port.data = temp_wr;
delay_cycles(1);
lcd_command_port.enable = 1;
delay_us(2);
lcd_command_port.enable = 0;
}
//*************** - - *********************************************
void lcd_send_byte(char data , char data_or_command ) {
lcd_command_port.data_command = COMMAND0;
while ( bit_test(lcd_read_byte(),7) ) ;
lcd_command_port.data_command = data_or_command;
delay_cycles(1);
lcd_command_port.read_write = WRITE0;
delay_cycles(1);
lcd_command_port.enable = E_DOWN;
lcd_write_nibble(data >> 4);
lcd_write_nibble(data & 0xf);
}
//************************************************************
void lcd_gotoxy( char location, char line) {//location 0...
char address;
if(line!=1)
address=40;//was80
else
address=0;
address+=location;
lcd_send_byte(0x80|address,COMMAND0);
}
//********** - 1 - **************************************************
void lcd_init(void){
//Purpose: initiate the lcd
//turnning PORTA0=analog, PORTA1-7=digital
ADCON1=0x0e;
//turnning command pin of lcd to output
set_tris_lcd_write();
//delay 15msec
delay_ms(15);
lcd_command_port.enable=0;
lcd_command_port.data_command=0;
lcd_command_port.read_write=0;
lcd_data_port.data=0;
delay_ms(2);
lcd_write_nibble(0x03);//was 30 ddram address: 1:1bit,line:1bit,address:4bit
delay_ms(10);//more then 4.1msec
lcd_write_nibble(0x03);//was 30
delay_us(150);//more then 100usec
lcd_write_nibble(0x03);//was 30
delay_us(100);
lcd_write_nibble(0x02);//was 20
while(bit_test(lcd_read_byte(),7));
lcd_send_byte(0x28,COMMAND0);//was 0x28 portd[3:0]=x2 then portd[3:0]=x8
// 4 bit low nibble, ddram address=0 first line
lcd_send_byte(0x0c,COMMAND0);//disp on
clear_lcd;
lcd_send_byte(0x6,COMMAND0);//entry inc
lcd_gotoxy(1,1);
}
//************************************************************
void lcd_putc( char c) {//this function works good
switch (c) {
case '\f' : lcd_send_byte(1,COMMAND0); delay_ms(2); break; //Clear display
case '\n' : lcd_gotoxy(1,2); break; //Go to start of second line
case '\b' : lcd_send_byte(0x10,COMMAND0); break; //Move back one position
default : lcd_send_byte(c,DATA1); break; //send the actual character
}
}
//*************** - - *********************************************
char lcd_getc( char location, char line) {
char value;
lcd_gotoxy(location,line);
while ( bit_test(lcd_read_byte(),7) ); // wait until busy flag is low
lcd_command_port.data_command=1;
value = lcd_read_byte();
lcd_command_port.data_command=0;
return(value);
return 1;
}
//************************************************************
//*************************----***********************************
void lcd_put_string(char *string){
//put string, starting from the curren cursor position
//assume that string not excides from lcd displayed RAM
char index=0;
while(string[index]!=0){
lcd_putc(string[index++]);
}
}
//************************************************************
void lcd_put_string_xy(char *string, char pos, char line){
//assume that string not excides from lcd displayed RAM
lcd_gotoxy(pos,line);
lcd_put_string(string);
}
//************************************************************
void stan_char(long *ptr,char line,char eeprom_or_flash){
//Purpose: write 16 chars, given in ptr location(eeprom or flash)
//to line of lcd, from the begining of the line
char c,i;
lcd_gotoxy(1,line);
/*OR: switch(line==1) {
case 1:lcd_send_byte(0x80,COMMAND); //initiate lcd to write to line 1
case 2:lcd_send_byte(0xc0,COMMAND); //initiate lcd to write to line 2
}*/
for (i=0;i<16;i++){
if (eeprom_or_flash)
c=read_program_eeprom(ptr+1);
else
c=read_eeprom((char)ptr+1);
lcd_putc(c);ptr++;
}
}
/*
LCD_INIT
MOVLW DISP_ON ; Display On, Cursor On = 0x0C
CALL SEND_CMD ; Send This command to the Display Module
MOVLW CLR_DISP ; Clear the Display =0x01
CALL SEND_CMD ; Send This command to the Display Module
MOVLW ENTRY_INC ; Set Entry Mode Inc., No shift =0x06
CALL SEND_CMD ; Send This command to the Display Module
*/
/*
SEND_CHAR
MOVWF CHAR ; Character to be sent is in W
CALL BUSY_CHECK ; Wait for LCD to be ready
SWAPF CHAR, W
ANDLW 0x0F ; Get upper nibble
MOVWF LCD_DATA ; Send data to LCD
BCF LCD_CNTL, RW ; Set LCD to read
BSF LCD_CNTL, RS ; Set LCD to data mode
BSF LCD_CNTL, E ; toggle E for LCD
BCF LCD_CNTL, E
MOVF CHAR, W
ANDLW 0x0F ; Get lower nibble
MOVWF LCD_DATA ; Send data to LCD
BSF LCD_CNTL, E ; toggle E for LCD
BCF LCD_CNTL, E*/
/*
SEND_CMD
MOVWF CHAR ; Character to be sent is in W
CALL BUSY_CHECK ; Wait for LCD to be ready
MOVF CHAR,w
ANDLW 0xF0 ; Get upper nibble
MOVWF LCD_DATA ; Send data to LCD
BCF LCD_CNTL,RW ; Set LCD to read
BCF LCD_CNTL,RS ; Set LCD to command mode
BSF LCD_CNTL,E ; toggle E for LCD
BCF LCD_CNTL,E
SWAPF CHAR,w
ANDLW 0xF0 ; Get lower nibble
MOVWF LCD_DATA ; Send data to LCD
BSF LCD_CNTL,E ; toggle E for LCD
BCF LCD_CNTL,E
*/
/*
BUSY_CHECK
BSF STATUS, RP0 ; Select Register Bank1
MOVLW 0xFF ; Set Port_D for input
MOVWF LCD_DATA_TRIS
BCF STATUS, RP0 ; Select Register Bank0
BCF LCD_CNTL, RS ; Set LCD for Command mode
BSF LCD_CNTL, RW ; Setup to read busy flag
BSF LCD_CNTL, E ; Set E high
BCF LCD_CNTL, E ; Set E low
MOVF LCD_DATA, W ; Read upper nibble busy flag, DDRam address
ANDLW 0xF0 ; Mask out lower nibble
MOVWF TEMP
BSF LCD_CNTL, E ; Toggle E to get lower nibble
BCF LCD_CNTL, E
SWAPF LCD_DATA, w ; Read lower nibble busy flag, DDRam address
ANDLW 0x0F ; Mask out upper nibble
IORWF TEMP ; Combine nibbles
BTFSC TEMP, 7 ; Check busy flag, high = busy
GOTO BUSY_CHECK ; If busy, check again
BCF LCD_CNTL, RW
BSF STATUS, RP0 ; Select Register Bank1
MOVLW 0x0F
MOVWF LCD_DATA_TRIS ; Set Port_D for output
BCF STATUS, RP0 ; Select Register Bank0
*/
|
|
|