program TW_LCD_Demo
' * Project name:' TW_LCD_Demo' * Copyright:' Public Domain, 2008' * Author :' Csaba Zvekan' * Revision History:' 20080428:' - initial release.' * Description:' This code demonstrates the two wire Serial LCD Interface originaly' designed Myke Predko. The main code here was written in MikroC by Rich Irace.' I took a different approach for the NybbleShift Routine. More like what' myke suggested on http://www.myke.com/lcd.htm. Also changed some LCD' timing values.' Except at the end I keep Data lines high then low. Different from his' website stated where he keeps clock High then low (to enable "E"pin)' * Test configuration:' MCU: PIC18F452' Dev.Board: EasyPIC4' Oscillator: HS, 4 - 48.000 MHz fully Tested' Ext. Modules: TW_LCD board, Lcd_2x16' SW: mikroBasic v6.0 or higher' * NOTES:' - In order to have valid function, PORTx pin's must be connected to' pull-up/ or down resistors !' - LEDiodes on PORTx should be turned off !include TW_LCD
dim text asstring[16]main:'**********************************************************************ADCON0 = %00000000ADCON1 = %00000100' used to be 0b00000100PORTA = %00000000' Start with Everything LowPORTB = %00000000' Start with Everything LowPORTC = %00000000' Start with Everything LowPORTD = %00000000' Start with Everything LowPORTE = %00000000INTCON = %00000000' Disables InterruptsTRISA = %00000000' ALL OutputsTRISB = %00000000' All Outputs PORTB6 and PORTB7 TW_LCDTRISC = %00000000' ALL OutputsTRISD = %00000000' ALL OutputsTRISE = %00000000' ALL Outputs'**********************************************************************'variables'none'**********************************************************************
TW_LCD_Init()' Initializes the two wire LCD InterfacewhiletrueTW_LCD_CMD(Lcd_Clear)
text="Initialized "TW_LCD_Out(1, 3,text)' Displays Message on Row 1Delay_ms(3000)
text="Two Wire LCD"TW_LCD_Out(1, 2,text)' Displays Message on Row 1
text="inf www.csaba.ch"TW_LCD_Out(2, 1,text)' Displays Message on Row 2Delay_ms(3000)TW_LCD_CMD(Lcd_Clear)TW_LCD_CMD(Lcd_Underline_On)TW_LCD_CMD(Lcd_Blink_Cursor_On)
text="Cursor Blink On"TW_LCD_Out(1, 1,text)' Displays Message on Row 1Delay_ms(3000)TW_LCD_CMD(Lcd_Cursor_Off)
text="Now Off"TW_LCD_Out(2, 3,text)' Displays Message on Row 2Delay_ms(3000)
text="same CMDs MikroE"TW_LCD_Out(2, 1,text)' Displays Message on Row 2TW_LCD_CMD(Lcd_Clear)
text="Celsius 25.5"TW_LCD_Out(1, 2,text)' Displays Message on Row 1TW_LCD_Write(%11011111,1)' Displays the degree symbol °Delay_ms(3000)wendend.
and then the TW.LCD module is here:
module TW_LCD
' * Project name:' module TW_LCD.pbas' * Copyright:' Public Domain, 2008' * Author :' Csaba Zvekan' * Revision History:' 20080428:' - initial release.' * Description:' This code demonstrates the two wire Serial LCD Interface originaly' designed Myke Predko. The main code here was written in MikroC by Rich Irace.' I took a different approach for the NybbleShift Routine. More like what' myke suggested on http://www.myke.com/lcd.htm. Also changed some LCD' timing values.' Except at the end I keep Data lines high then low. Different from his' website stated where he keeps clock High then low (to enable "E"pin)' * Test configuration:' MCU: PIC18F452' Dev.Board: EasyPIC4' Oscillator: HS, 4 - 48.000 MHz fully Tested' Ext. Modules: TW_LCD board, Lcd_2x16' SW: mikroBasic v6.0 or higher' * NOTES:' - In order to have valid function, PORTx pin's must be connected to' pull-up/ or down resistors !' - LEDiodes on PORTx should be turned off !symbol Clk = PORTB.4' PORTB6 for the Clock Signalsymbol Data = PORTB.3' PORTB7 for the Data Signal'* This is where you define the two lines for Clock / Data'**********************************************************************symbol row1 = %00000000' Define on LCD Row1 (0)symbol row2 = %01000000' Define on LCD Row2 (64)'symbol Lcd_Clear = %00000001 ' Define LCD_CLEAR
const ClockDelay asbyte = 160dim progarray asstring[17]'*****************************************************************'* Shift Out the Nybble'*****************************************************************sub procedureNybbleShift(dim Nybble asbyte, dim RS asbyte)dim i asbyte'** Empty shift register by writing 6 zeroes to it
Data = 0for i= 1 to 6'Clear the Shift Register by writing
Clk = 1'6 times data 0
Clk = 0next i
'** Output E-pin on LCD at the end of the 6th bit
Data = 1
Clk = 1
Clk = 0'** Output RS-Pin on LCD at 5th position
Data = RS
Clk = 1
Clk = 0'** Output the Nybble highest bit firstfor i= 1 to 4if Nybble.3 = 1then' look at bit MSB lower nybble
Data = 1else
Data = 0endif
Clk = 1
Clk = 0
Nybble= Nybble << 1next i
'** Finish Nybble write with E-pin High
Data = 1' E-pin goes high by pulling Data highdelay_us(1)' 450nS for the delay
Data = 0end sub'**********************************************************************'* Write a byte to LCD with option RS(xx,1) HIGH or RS(xx,0) LOW'**********************************************************************sub procedureTW_LCD_Write(dim LCDData asbyte,dim RSValue asbyte)dim j,t asbyte
t = 0
j = 0
j = LCDData 'save LCDData to jNybbleShift((j >> 4)and 0x0F, RSValue )'Shift out High Nybble'delay_us(ClockDelay) ' 450nS for the clock only if necessary
t = (LCDData << 4)
t = (t >> 4)NybbleShift(t and 0x0F, RSValue)'Shift out Low Nybble'delay_us(ClockDelay) ' 450nS for the clockif((LCDData AND 0xFC) + (RSValue)) = 0thendelay_ms(5)' to be adjusted even higher !!!elsedelay_uS(160)' to be adjusted even higher !!!endifend sub'**********************************************************************'* Converts digital value to BCD'**********************************************************************sub function NumToChar(dim valu asinteger)asintegerdim ch asintegerif valu < 10then
ch=valu + 48' 48 = '0'else
valu=valu - 10endif' 65 = A in MIKROC
ch=valu + 48' 48 for MikroBasicresult = ch
end sub'***********************************************************************'* LCD to BCD displays byte in decimal as either 1, 2 or 3 digits'***********************************************************************sub procedure LCDtoBCD(dim valu asinteger,dim digits asinteger)dim d asintegerdim ch asintegerif digits = 3then' Take 100's Digits
d = valu/100' Divide it by 100
ch = NumtoChar(d)' Take number, convert it to ASCII' lcdchar(ch) ' number (0 - 9)TW_LCD_Write(ch, 1)' Send that value to displayendifif(digits >1)then' Take the two lowest digits
valu = valu mod 100
d = valu/10
ch = NumtoChar(d)' lcdchar(ch)TW_LCD_Write(ch, 1)endifif(digits = 1)then' Take the least significant digit
valu = valu mod 100endif
d = valu mod 10
ch = NumtoChar(d)' lcdchar(ch)TW_LCD_Write(ch, 1)end sub'**********************************************************************'* LCD Configuration TW_LCD but it don't work !!!'**********************************************************************'sub procedure TW_LCD_Config(dim byref data_port as byte,dim Clk1, Data1 as byte)'symbol Clk = data_port.Clk1 ' PORTB6 for the Clock Signal'symbol Data = data_port.Data1 ' PORTB7 for the Data Signal'end sub'**********************************************************************'* Reset TW_LCD'**********************************************************************sub procedureTW_LCD_Reset()TW_LCD_Write(%00101000, 0)' Switch to 4-Bit mode 2 linesTW_LCD_Write(%00010000, 0)' Turn Off the DisplayTW_LCD_Write(%00000001, 0)' Clear LCD and Home CursorTW_LCD_Write(%00000110, 0)' Move Cursor After Each Character'LCDWrite(%00010000, 0) ' Shift Cursor without chasngin DD Reg'LCDWrite(%00001111, 0) ' Turn On LCD and Enable Cursor & BlinkTW_LCD_Write(%00001100, 0)' Turn On LCD and Disable Cursor& Blinkend sub'************************************************************************'* Initializes the Two Wire LCD'************************************************************************sub procedure TW_LCD_Init()delay_ms(20)NybbleShift(3, 0)' Init LCDdelay_ms(5)NybbleShift(3, 0)' Init LCDdelay_us(160)NybbleShift(3, 0)' Init LCDdelay_us(160)NybbleShift(2, 0)' Set LCD 4 Bit Modedelay_us(160)TW_LCD_Reset()' Call Reset LCDend sub'************************************************************************'* Sends LCD Commands to the TW_LCD Interface same as MikroE'************************************************************************Sub procedureTW_LCD_CMD(dim TW_command asbyte)TW_LCD_Write(TW_command, 0)' Send out a TW_ LCD Commandend sub'***********************************************************************'* Displays String to the TW LCD'*'* When row is 1, Characters are displayed on LCD Row 1 v 0'* When row is 2, Characters are displayed on LCD Row 2 v 64'***********************************************************************sub procedureTW_LCD_Out(dim row asbyte,dim character asbyte, dimbyref s asstring[16])dim i asbyteif row =1then row = row1
endifif row =2then row = row2
endifTW_LCD_Write(%10000000 + row + (character-1), 0)'Move Cursor to the corresponding Row
i = 0while(s[i] <> 0)'Display the stringTW_LCD_Write(s[i],1)inc(i)wendend subend.