;****************************************************************** ; * ; Filename: ezLCD v2 (12F635).asm * ; Author: Mike McLaren, K8LH * ; (C)2010: Micro Application Consultants, All Rights Reserved * ; Date: 30-Oct-07 (last revision 23-May-08) * ; * ; Novelty 12F635 serial 44780 LCD 4-bit interface concept * ; * ; 4-bit test code... this interface requires a custom host * ; driver (hi nybble must be written to LCD 1st) * ; * ; * ; MPLab: 8.80 (tabs=8) * ; MPAsm: 5.43 * ; * ;****************************************************************** #include list st=off errorlevel -302 radix dec __config _FCMEN_OFF&_IESO_OFF&_MCLRE_OFF&_WDT_OFF&_INTRC_OSC_NOCLKOUT ;--< variables >--------------------------------------------------- shadow equ 0x40 ; gpio shadow register flags equ 0x41 ; flag register cx equ 0 ; ;--< constants >--------------------------------------------------- ; ; bit time (cycles) used to sample a serial bit stream ; ; 19200 baud, 104 (104.2) cycles, 0.16% bit rate error ; 57600 baud, 35 ( 34.7) cycles, 0.80% bit rate error ; 115200 baud, 17 ( 17.4) cycles, 2.08% bit rate error ; 250000 baud, 8 ( 8.0) cycles, 0.00% bit rate error ; ; it seems plus or minus 1% baud rate tolerance may render the ; interface useless at very high bit rates. I probably should ; consider placing RS data in both the b6 and b7 serial bits ; and strobing LCD 'E' line between the b6 and b7 bit periods ; to compensate for 'drift'. ; clock equ 8 ; 8 MHz clock usecs equ clock/4 ; cycles per microsecond bRate equ 57600 ; baudrate 19200, 57600 or 115200 bTime equ (usecs*10000000/bRate+5)/10 ; bTime = 104, 35 or 17 cycles ; #define D4 0 ; GP0 -> LCD 'D4' #define D5 1 ; GP1 -> LCD 'D5' #define D6 2 ; GP2 -> LCD 'D6' #define SerPin GPIO,3 ; GP3 -> LCD 'RS' (serial data) #define D7 4 ; GP4 -> LCD 'D7' #define E 5 ; GP5 -> LCD 'E' ;--< macros >------------------------------------------------------ ; ; uDelay(Tcy) in-line delay macro, range 1..1023 cycles, ; produces 1 to 6 instructions. ; uDelay macro pTime local dloop if pTime > 3 movlw (pTime)/4-1 ; dloop addlw -1 ; bc dloop ; endif if pTime%4 & 1 nop ; 1 cycle endif if pTime%4 & 2 goto $+1 ; 2 cycles endif endm ;****************************************************************** ; Reset Vector * ;****************************************************************** org 0x0000 v_reset clrf STATUS ; |B0 goto Main ; |B0 ;****************************************************************** ; Interrupt Vector * ;****************************************************************** org 0x0004 strt uDelay (bTime/2-2) ; half bit time minus 2 cycles |B0 clrf shadow ; |B0 clrf flags ; |B0 bit0 uDelay (bTime-3) ; |B0 btfsc SerPin ; bit = 0? yes, skip, else |B0 bsf shadow,D4 ; set LCD D4 shadow bit |B0 bit1 uDelay (bTime-2) ; |B0 btfsc SerPin ; bit = 0? yes, skip, else |B0 bsf shadow,D5 ; set LCD D5 shadow bit |B0 bit2 uDelay (bTime-2) ; |B0 btfsc SerPin ; bit = 0? yes, skip, else |B0 bsf shadow,D6 ; set LCD D6 shadow bit |B0 bit3 uDelay (bTime-2) ; |B0 btfsc SerPin ; bit = 0? yes, skip, else |B0 bsf shadow,D7 ; set LCD D7 shadow bit |B0 bit4 uDelay (bTime-2) ; |B0 btfsc SerPin ; CX mode '1'? no, skip, else |B0 bsf flags,cx ; set 'CX' flag |B0 bit5 uDelay (bTime) ; |B0 bit6 uDelay (bTime-3) ; |B0 movf shadow,W ; |B0 movwf GPIO ; set LCD D4..D7 lines |B0 bsf shadow,E ; preset E = 1 in shadow |B0 bit7 uDelay (bTime-5) ; |B0 movf shadow,W ; |B0 btfss flags,cx ; wr lcd? no, skip, else |B0 movwf GPIO ; nybble + E = 1 |B0 xorlw 1<