' Name : LCD_BIT_BANG.pbp ' Compiler : PICBASIC PRO Compiler 2.6 ' Assembler : PM or MPASM ' Target PIC : 40-pin 16F877A, 18F452 or similar ' Hardware : LAB-X1 Experimenter Board ' Oscillator : 4MHz external crystal ' Keywords : LOOKUP ' Description : PICBASIC PRO program to manually operate (without LCDOUT) ' an LCD in 4-bit mode with the PIC16F877A and LAB-X1. ' ' Alias LCD connections - any output pin can be used LCD_DB4 Var PORTD.4 ' LCD data bit 4 LCD_DB5 Var PORTD.5 ' LCD data bit 5 LCD_DB6 Var PORTD.6 ' LCD data bit 6 LCD_DB7 Var PORTD.7 ' LCD data bit 7 LCD_RS Var PORTE.0 ' LCD register select LCD_E Var PORTE.1 ' LCD enable LCD_RW Var PORTE.2 ' LCD read/write c Var Byte ' Variable to store character to send to the LCD i Var Byte ' Loop counter ADCON1 = 7 ' Set PIC16F877A analog pins to digital Pause 500 ' Wait for the LCD to power up Gosub lcdinit ' Initialize the LCD mainloop: Gosub lcdclr ' Clear the LCD screen For i = 0 to 4 ' Send string to the LCD one letter at a time Lookup i, ["Hello"], c ' Get letter from string to variable c Gosub lcddata ' Send data in c to the LCD Next i Pause 500 ' Wait .5 second Gosub lcdclr ' Clear the LCD screen c = $c0 ' Move to second line of display gosub lcdcom ' Send command in c to the LCD For i = 0 to 4 ' Send string to the LCD one letter at a time Lookup i, ["World"], c ' Get letter from string to variable c Gosub lcddata ' Send data in c to the LCD Next i Pause 500 ' Wait .5 second Goto mainloop ' Do it forever ' Subroutine to write the lower nibble to the LCD lcdlower: LCD_E = 1 ' Enabled LCD_DB4 = c.0 ' Write bit 0 to the LCD LCD_DB5 = c.1 ' Write bit 1 to the LCD LCD_DB6 = c.2 ' Write bit 2 to the LCD LCD_DB7 = c.3 ' Write bit 3 to the LCD Pauseus 1 ' Enable for at least 1us LCD_E = 0 ' Not enabled Return ' Subroutine to write the upper nibble to the LCD lcdupper: LCD_E = 1 ' Enabled LCD_DB4 = c.4 ' Write bit 4 to the LCD LCD_DB5 = c.5 ' Write bit 5 to the LCD LCD_DB6 = c.6 ' Write bit 6 to the LCD LCD_DB7 = c.7 ' Write bit 7 to the LCD Pauseus 1 ' Enable for at least 1us LCD_E = 0 ' Not enabled Return ' Subroutine to clear the LCD screen lcdclr: c = 1 ' Set c to clear command and fall through to lcdcom ' Subroutine to send a command to the LCD lcdcom: LCD_RS = 0 ' Set RS to command Gosub lcdupper ' Write upper nibble to the LCD Gosub lcdlower ' Write lower nibble to the LCD Pause 2 ' Wait command delay time, 2ms Return ' Subroutine to send data to the LCD lcddata: LCD_RS = 1 ' Set RS to data Gosub lcdupper ' Write upper nibble to the LCD Gosub lcdlower ' Write lower nibble to the LCD Pauseus 50 ' Wait data delay time, 50us Return ' Subroutine to initialize the LCD lcdinit: Low LCD_E ' Set all LCD I/O lines to output low Low LCD_RS Low LCD_RW Low LCD_DB4 Low LCD_DB5 Low LCD_DB6 Low LCD_DB7 Pauseus 15100 ' Wait at least 15ms c = $33 ' Initialize the LCD Gosub lcdupper ' Send to upper nibble only Pauseus 4200 ' Wait at least 4.1ms c = $33 ' Send it again Gosub lcdupper ' Send to upper nibble only Pauseus 100 ' Wait at least 100us c = $22 ' Put the LCD into 4 bit mode Gosub lcdupper ' Send to upper nibble only c = $28 ' 4 bit mode, 2 lines, 5x7 font Gosub lcdcom ' Send command in c to the LCD c = $0c ' LCD display on, no cursor, no blink Gosub lcdcom ' Send command in c to the LCD c = $01 ' Clear screen Gosub lcdcom ' Send command in c to the LCD c = $06 ' LCD entry mode set, increment, no shift Goto lcdcom ' Send command in c to the LCD and return End