LCD Serial Backpack
If you need a Serial LCD but do not want to spend money, you can build it yourself.
It uses the DT_INTS to read the serial data on the USART of the PIC.
I know DT_INTS looks intimidating at the beginning, but it's really not that bad, and you don't need to learn assembly language to use it.
But I can understand why you might not want to try it out. The biggest obstacle is that you have to be using MPASM.
So whenever you get around to DT_INTS, you can come back to this thread and try out this program.
Tested it on a 16F877A
;---- Config settings for MPASM ---------------------------------------------- @ __config _HS_OSC & _WDT_OFF & _PWRTE_ON & _MCLRE_ON & _LVP_OFF & _CP_OFF trisb = %00000010 trisA = %11110011 ;----Added by DT-------------------------------------------------------------- INCLUDE "DT_INTS-14.bas" INCLUDE "ReEnterPBP.bas" ; Include if using PBP interrupts ASM INT_LIST macro ; IntSource, Label, Type, ResetFlag? INT_Handler RX_INT, _serialin, PBP, no endm INT_CREATE ; Creates the interrupt processor ENDASM @ INT_ENABLE RX_INT ; enable external (INT) interrupts ;----------------------------------------------------------------------------- ' Define LCD registers and bits Define LCD_DREG PORTB Define LCD_DBIT 4 Define LCD_RSREG PORTA Define LCD_RSBIT 0 Define LCD_EREG PORTA Define LCD_EBIT 1 DEFINE LCD_LINES 4 'Define using a 2 line LCD DEFINE LCD_COMMANDUS 2000 'Define delay time between sending LCD commands DEFINE LCD_DATAUS 50 'Define delay time between data sent. DEFINE OSC 20 DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive DEFINE HSER_TXSTA 20h ' Enable transmit, BRGH = 0 DEFINE HSER_SPBRG 32 ' FOR 20MHZ 129 = 2400, 32=9600,25 @ 4 for 2400 DEFINE HSER_CLROERR 1 ' Clear overflow automatically RCIF VAR PIR1.5 ' Receive interrupt flag (1=full , 0=empty) TXIF VAR PIR1.4 ' Transmit interrupt flag (1=empty, 0=full) LED VAR PORTA.4 OERR VAR RCSTA.1 ' Alias OERR (USART Overrun Error Flag) CREN VAR RCSTA.4 ' Alias CREN (USART Continuous Receive Enable) buffer_size CON 64 ' Sets the size of the ring buffer, set up from 32 buffer VAR BYTE[buffer_size]' Array variable for holding received characters index_in VAR BYTE ' Pointer - next empty location in buffer index_out VAR BYTE ' Pointer - location of oldest character in buffer bufchar VAR BYTE ' Stores the character retrieved from the buffer i VAR BYTE ' loop counter Col VAR BYTE ' Stores location on LCD for text wrapping errflag VAR BYTE ' Holds error flags index_in = 0 index_out = 0 i = 0 col = 1 'RxData var byte CMCON = 7 ' PORTA is digital Pause 100 ' Wait for LCD to startup high PortA.2 ' power for backlight low PortA.3 ' backlight ground pause 1500 lcdout $FE,1 lcdout $FE,2 LCDOUT "Your Text Goes Here" PAUSE 2000 ' * * * * * * * * * * * * * Main program starts here - blink an LED at 1Hz loop: For i = 0 to 10 ' Delay for .02 seconds (10*2mS) Pause 2 ' Use a short pause within a loop Next i ' instead of one long pause For i = 0 to 10 ' Delay for .02 seconds (10*2mS) Pause 2 ' Use a short pause within a loop Next i ' instead of one long pause display: ' dump the buffer to the LCD IF errflag Then error ' Handle error if needed IF index_in = index_out Then loop ' loop if nothing in buffer GoSub getbuf ' Get a character from buffer LCDOut bufchar ' Send the character to LCD IF col > 20 Then ' Check for end of line col = 1 ' Reset LCD location LCDOut $fe,$c0,REP " "\20 ' Clear line-2 of LCD LCDOut $FE,2 ' Tell LCD to return home EndIF GoTo display ' Check for more characters in buffer ' Subroutines getbuf: ' move the next character in buffer to bufchar @ INT_DISABLE RX_INT index_out = (index_out + 1) ' Increment index_out pointer (0 to 63) ' Reset pointer if outside of buffer IF index_out > (buffer_size-1) Then index_out = 0 bufchar = buffer[index_out] ' Read buffer location @ INT_ENABLE RX_INT Return error: ' Display error message if buffer has overrun IF errflag.1 Then ' Determine the error LCDOut $FE,$c0,"Clearing Display Buffer" ' Display buffer error on ' line-2 and 3 Buff overrun Else LCDOut $FE,$D4,"USART Overrun" ' Display usart error on line-4 EndIF LCDOut $fe,2 ' Send the LCD cursor back to line-1 home For i = 2 to col ' Loop for each column beyond 1 LCDOut $fe,$14 ' Move the cursor right to the right column Next i ' $14 = 20 DEC. errflag = 0 ' Reset the error flag CREN = 0 ' Disable continuous receive to clear overrun flag CREN = 1 ' Enable continuous receive GoTo display ' Errors cleared, time to work. ' * * * * * * * * * * * * * * * Interrupt handler serialin: ' Buffer the character received IF OERR Then usart_error ' Check for USART errors index_in = (index_in + 1) ' Increment index_in pointer (0 to 63) IF index_in > (buffer_size-1) Then index_in = 0 'Reset pointer if outside of buffer IF index_in = index_out Then buffer_error ' Check for buffer overrun HSerin [buffer[index_in]] ' Read USART and store character to next empty location IF RCIF Then serialin ' Check for another character while we're here @ INT_RETURN ; Return to program buffer_error: errflag.1 = 1 ' Set the error flag for software ' Move pointer back to avoid corrupting the buffer. MIN insures that it ends up within the buffer. index_in = (index_in - 1) MIN (buffer_size - 1) HSerin [buffer[index_in]] ' Overwrite the last character stored (resets the interrupt flag) usart_error: errflag.0 = 1 ' Set the error flag for hardware @ INT_RETURN ; Return to program End
Addendum: By Joe S.
My contribution, aside from asking for help, is in the example below, it is the selectable baud rate. Darrel did the lion's share of the rest, the original program exists on MeLabs site without DT_INTS. Please read the original thread to see the progression of this code.
This is a version of the serial backpack ported to a 16F690 and it features selectable baud rates from a DIP switch attached to the A Port, change the switch, reboot and it works at a different serial baud rate. It continues to use the USART so it will require you to use a pullup resistor and send your data TRUE.
'**************************************************************** '* Name : MyLCD.BAS * '* Author : Joe Stokes & Darrel Taylor * '* Notice : [ Copyright (c) 2006 ] * '* : use it freely, give us credit * '* Date : 3/17/09 * '* Version : 1.1 , baud selection added 7/1/09 * '* Notes : Adapted for PIC 16F690 May 27 2009 * '* LCD pins 1,3,5, and 16 to ground, pins 2 & 15 to Vcc * '* D pins are 11,12,13,14, E bit pin 6, R/S bit pin 4 * '* No contrast pot used. * '* Dip Switch selectable baud rate from 1200 to 115200 on PortA * '**************************************************************** @ __config _HS_OSC & _WDT_ON & _PWRTE_ON & _MCLRE_OFF & _CP_OFF & _FCMEN_OFF & _BOR_OFF DEFINE OSC 20 TRISB = %00100000 'PortB.5 RX input TRISA = %00001111 PORTC = %00000000 TRISC = %00000000 WPUA = %00000000 ; weak pull ups disabled SSPCON.5 = 0 ' DISABLE ssp INCLUDE "DT_INTS-14.bas" ; Darrel Taylors instant interrupts ASM INT_LIST macro ; IntSource, Label, Type, ResetFlag? INT_Handler RX_INT, _serialin, ASM, no endm INT_CREATE ; Creates the interrupt processor ENDASM @ INT_ENABLE RX_INT ; enable external (INT) interrupts ' = = = = = Define LCD registers and bits = = = = = = DEFINE LCD_DREG PORTC ' Set port C for the data lines DEFINE LCD_DBIT 4 ' Set top 1/2 of port to use for data DEFINE LCD_RSREG PORTC 'Set the RS Port and Pin DEFINE LCD_RSBIT 3 ' Set PortC.0 as R/S bit DEFINE LCD_EREG PORTB 'Set LCD Enable bit and pin DEFINE LCD_EBIT 6 DEFINE LCD_BITS 4 ' Set number of data bits DEFINE LCD_LINES 2 ' Set number of lines on LCD DEFINE LCD_COMMANDUS 2000 ' Set command delay time in us Flags = 0 DEFINE LCD_DATAUS 50 ' Set data delay time in us ' = = = = = Set analog functions to off condition = = = ADCON0 = 0 ADCON1 = 0 ANSEL = 0 ANSELH = 0 CM1CON0 = 0 CM2CON0 = 0 SRCON = 0 ' COMPARATOR SET/RESET LATCH OPTION_REG = %10000000 CCP1CON = %00000000 'BITS 7:6 DETERMINE HPWM CHANNEL ' 00 = P1A, 01P1D PWM P1A ACTIVE, P1B P1C INACTIVE,10 ' P1A P1B PWM, P1C P1D AS PORT PINS ' 11 = P1B PWM, PIC ACTIVE , P1C P1D INACTIVE ' = = = = = Set up hardware usart serial port = = = = = = ' This Sets up the baud rate by setting the SPBRG, RCSTA, TXSTA As Variables ' Defined in the appropriate subdirectories. ' Variables for Usart and select case A Var Word B Var Word C Var Word D Var Word E Var Byte F Var byte F = PortA LCDOUT "SETUP" Setup: Select Case F case 0 GoSub One Case 1 GoSub Two Case 2 GoSub Three Case 3 Gosub Four Case 4 Gosub Five Case 5 GoSub Six Case 6 Gosub Seven Case 7 GoSub Eight Case 8 GoSub Nine Case else GoTo Setup end select RCSTA = A ' Enable serial port & continuous receive TXSTA = B ' Enable transmit, BRGH = 1 SPBRG = C ' 10 = 115200 Baud @ 20MHz, 20MHZ 129 = 2400, 32=9600,25 @ 4 for 2400 DEFINE HSER_CLROERR 1 ' Clear overflow automatically RCIF VAR PIR1.5 ' Receive interrupt flag (1=full , 0=empty) TXIF VAR PIR1.4 ' Transmit interrupt flag (1=empty, 0=full) ' = = = = = Setup variables and interrupt flags = = = = = = buffer_size CON 64 ' Sets the size of the ring buffer. OERR VAR RCSTA.1 ' Alias OERR (USART Overrun Error Flag) CREN VAR RCSTA.4 ' Alias CREN (USART Continuous Receive Enable) index_in VAR BYTE ' Pointer - next empty location in buffer index_out VAR BYTE ' Pointer - location of oldest character in buffer bufchar VAR BYTE ' Stores the character retrieved from the buffer i VAR BYTE ' MainLoop counter Col VAR BYTE ' Stores location on LCD for text wrapping errflag VAR BYTE ' Holds error flags buffer VAR BYTE[buffer_size]' Array variable for holding received characters ' = = = = = Set all index pointers to zero, Coloum to one = = = = = = = = index_in = 0 index_out = 0 i = 0 col = 1 'PortB.4 = 1 pause 1500 ' Wait for LCD to startup lcdout $FE,1 ' Clear LCD lcdout $FE,2, " Copyright 2006 " ' Yeah this has value ! lcdout $fe,$C0,"Thanks Darrel & Joe" ' That would be us ! LCDOUT $FE,$94,#D,#E," BAUD 8 N 1 " '#D & #E hold value of Baud for Splash Display PAUSE 3000 'Time to read splash screen lcdout $FE,1 ' Clear LCD MainLoop: Pause 2 ' Use a short pause within a MainLoop display: ' dump the buffer to the LCD IF errflag Then error ' Handle error if needed IF index_in = index_out Then MainLoop ' MainLoop if nothing in buffer GoSub getbuf ' Get a character from buffer LCDOut bufchar ' Send the character to LCD IF col > 20 Then ' Check for end of line col = 1 ' Reset LCD location LCDOut $fe,$c0,REP " "\20 ' Clear line-2 of LCD LCDOut $FE,2 ' Tell LCD to return home EndIF GoTo display ' Check for more characters in buffer getbuf: ' move the next character in buffer to bufchar @ INT_DISABLE RX_INT index_out = (index_out + 1) ' Increment index_out pointer (0 to 63) ' Reset pointer if outside of buffer IF index_out > (buffer_size-1) Then index_out = 0 bufchar = buffer[index_out] ' Read buffer location @ INT_ENABLE RX_INT Return error: ' Display error message if buffer has overrun IF errflag.1 Then ' Determine the error LCDOut $FE,$c0,"Clearing Display Buffer" ' Display buffer error on ' line-2 and 3 Buff overrun Else LCDOut $FE,$D4,"USART Overrun" ' Display usart error on line-4 EndIF LCDOut $fe,1 ' Reset lcd For i = 2 to col ' MainLoop for each column beyond 1 LCDOut $fe,$14 ' Move the cursor right to the right column Next i ' $14 = 20 DEC. errflag = 0 ' Reset the error flag CREN = 0 ' Disable continuous receive to clear overrun flag CREN = 1 ' Enable continuous receive GoTo display ' Errors cleared, time to work. ' * * * * * * * * * * * * * * * Interrupt handler serialin: ' Buffer the character received IF OERR Then usart_error ' Check for USART errors index_in = (index_in + 1) ' Increment index_in pointer (0 to 63) IF index_in > (buffer_size-1) Then index_in = 0 'Reset pointer if outside of buffer IF index_in = index_out Then buffer_error ' Check for buffer overrun HSerin [buffer[index_in]] ' Read USART and store character to next empty location IF RCIF Then serialin ' Check for another character while we're here @ INT_RETURN ; Return to program buffer_error: errflag.1 = 1 ' Set the error flag for software ' Move pointer back to avoid corrupting the buffer. ' MIN insures that it ends up within the buffer. index_in = (index_in - 1) MIN (buffer_size - 1) HSerin [buffer[index_in]] ' Overwrite the last character stored (resets the interrupt flag) usart_error: errflag.0 = 1 ' Set the error flag for hardware @ INT_RETURN ; Return to program End One: A = $90 ' 115200 Baud @ 20MHz, -1.36% B = $24 C = 10 D = 11520 E = 0 Return Two: A = $90 ' 57600 Baud @ 20MHz, -1.36% B = $24 C = 21 D = 5760 E = 0 Return Three: A = $90 ' 38400 Baud @ 20MHz, -1.36% B = $24 C = 32 D = 3840 E = 0 Return Four: A = $90 B = $24 ' 19200 Baud @ 20MHz, 0.16% C = 64 D = 1920 E = 0 Return Five: A = $90 B = $24 ' 9600 Baud @ 20MHz, 0.16% C = 129 D = 960 E = 0 Return Six: A = $90 ' 4800 Baud @ 20MHz, 0.17% B = $20 C = 64 D = 480 E = 0 Return Seven: A = $90 ' 2400 Baud @ 20MHz, 0.17% b = $20 C = 129 D = 240 E = 0 Return Eight: A = $90 ' 1200 Baud @ 20MHz, 1.75% B = $20 C = 255 D = 120 E = 0 'If PortA = 9 then GoSub SetLCDContrast 'If PortA = 0 Then Gosub SetLCDBackLightOFF 'If PortA = 11 Then Gosub SetLCDBackLight Return Nine: LCDOut $FE, $80," Error, check baud" LCDOut $FE, $C0," setting" return Ten:' Subroutine Sets LCD Contrast Level