Here you will find source code and schematic for controlling LCD based on Hitachi HD44780U with Microchip PIC16 microcontrollers using only 3 I/O ports.
To achieve that we use 8-Bit Serial-Input/Parallel-Output Shift Register 74HC164.
The I/O ports used for controlling are:
- Clock
- Data
- LCD Enable
The Clock and Data ports can be shared with other peripheral devices.
The code is designed with minimum ASM instructions so to be as small as possible, especially for microcontrollers with less instruction memory.
Schematic
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 | ;****************************************************************************** ; LCD interface for Microchip PIC16 microcontrollers. ; ; author: Ivan Dachev ; email: [email protected] ; web: www.lz2gl.com ; version: v1.0 ; ;****************************************************************************** ; ; Program control 8-Bit Serial-Input/Parallel-Output Shift Register ; 74HC164 which is connected to LCD. ; ; It is implement to use only 3 ports from microcontroller: ; CLOCK - clock for 74HC164 ; DATA - data for 74HC164 ; STROBE - enable/disable for LCD read operation ; ; 14.01.2007 Initial Version ; All source here is small parts from my programs ; so to be usable for own use, change position ; of file registers to fit your program. ; ;****************************************************************************** ;****************************************************************************** ; Bit flags for SYNSTATUS ; ; Constants _XXX_BITS are used to make bit swapping ; example: ; movlw _LOCK_BITS ; xorwf SYNSTATUS, F ; #define _INSTLCD SYNSTATUS, 5 ;5-bit Instruction/Data flag for LCD #define _INSTLCD_BITS B'00100000' ;****************************************************************************** ; ; Main preferences for program. ; #define OUT2LCD_DELAY_TIME .62 ;Delay counter for OUT2LCD_DATA. ;Each iteration is 3 instructions we must wait about 37000ns ;so (20Mhz - number is 62) (10Mhz - number is 31) ;****************************************************************************** ; ; Defines IN/OUT for PORTA ; #define OUT_LCDCLOCK PORTA, 1 ;Share CLOCK at RA1 for LCD #define OUT_LCDDATA PORTA, 2 ;Share DATA at RA2 for LCD #define OUT_LCDSTROBE PORTA, 3 ;Strob signal at RA3 for LCD ;****************************************************************************** ; Define commands for LCD ; #define LCD_CLEAR B'00000001' ; Clear display, home cursor #define LCD_HOME B'00000010' ; Send cursor home #define LCD_8BIT B'00111100' ; 8-bit interface, 2 display lines, 5x10 font #define LCD_DISABLE B'00001000' ; Disable entire display #define LCD_ENABLE B'00001100' ; Display enable, no cursor #define LCD_MODESET B'00000110' ; Increment cursor, no scrolling #define LCD_CURSOFF B'00001100' ; Cursor off #define LCD_CURSON B'00001111' ; Cursor on and blink at position #define LCD_CURSRIGHT B'00010100' ; move cursor right one space #define LCD_SETADDR B'10000000' ; Set display address for writing ;****************************************************************************** ; File registers ; ;general temp tmp equ 0x50 ;general counter count equ 0x53 ;used for delay functions delay1 equ 0x5D delay2 equ 0x5E ;other variables SYNSTATUS equ 0x73 ;boolean flags ;****************************************************************************** ; ; INITLCD ; ------- ; ; Initializing LCD ; ; 03.07.2004 Changed according to HITACHI specification ! ;****************************************************************************** ; INITLCD ;--- START HITACHI INITIALIZING SPECIFICATION FOR LCD ---- #ifndef DEBUG_SIM movlw .255 CALL WAITWMS #endif ;Wait for more than 15 ms after VCC rises to 4.5 V ;Wait for more than 40 ms after VCC rises to 2.7 V ;Set Data Serial 8bit ;B 0011 1100 movlw LCD_8BIT CALL OUT2LCD_INST CALL WAIT5MS ;Wait more then 4.1ms ;Again set Data Serial 8bit CALL LCDSTROBE ;Just enable LCD to read again same operation CALL WAIT1MS ;Wait more then 100us ;And again CALL LCDSTROBE ;Just enable LCD to read again same operation ;Set Data Serial 8bit, display 2 lines, Font to 5x10 dots ;B 0011 1100 movlw LCD_8BIT CALL OUT2LCD_INST ;Turns display off / cursor off / blinck off ;B 0000 1000 movlw LCD_DISABLE CALL OUT2LCD_INST ;Clears display and set address 0 of RAM ;B 0000 0001 movlw LCD_CLEAR CALL OUT2LCD_INST CALL WAIT2MS ;LCD_CLEAR need more wait to execute ;Set Cursor to move Increment / No shift ;B 0000 0110 movlw LCD_MODESET CALL OUT2LCD_INST ;--- END HITACHI INITIALIZING SPECIFICATION FOR LCD ---- ;Turns display on / cursor off / blinck off ;B 0000 1100 movlw LCD_ENABLE GOTO OUT2LCD_INST ;RETURN goto will return ! same as return save place ; ; end *********************************************************************** ; ;****************************************************************************** ; ; OUT2LCD_INST & OUT2LCD_DATA ; --------------------------- ; ; Output character or instruction in W to LCD ; ; For all OUT2LCD_DATA we must wait 37000ns ; ; For all OUT2LCD_INST expect below we must wait 37000ns ; for RETURN_TOHOME and CLEAR_DISPLAY we must wait 1,520,000ns ; ; Corrupts: count and tmp. ;****************************************************************************** ; OUT2LCD_INST bsf _INSTLCD ;Change to instruction send GOTO POUT2LCD OUT2LCD_DATA bcf _INSTLCD ;Change from instruction to data send POUT2LCD movwf tmp movlw 008H movwf count NEXTOUT bcf OUT_LCDCLOCK GOTO $+1 bcf OUT_LCDDATA rlf tmp,F btfsc STATUS, C ;Check bit state skip if it is 0 bsf OUT_LCDDATA GOTO $+1 bsf OUT_LCDCLOCK decfsz count, F GOTO NEXTOUT ;Go to send next bit btfsc _INSTLCD ; OUT_LCDCLOCK is used for Instruction/Data switch bcf OUT_LCDCLOCK GOTO $+1 LCDSTROBE ;use this to repeat last operation again ! bsf OUT_LCDSTROBE ;enable LCD to read operation GOTO $+1 ;wait LCD to do its job bcf OUT_LCDSTROBE ;disable LCD to read operation ;--- from here LCD starts to execute operation --- ;--- so we need to wait it to finish him before next operation --- movlw OUT2LCD_DELAY_TIME ;Wait for data and instructions movwf delay1 decfsz delay1,F GOTO $-1 RETURN ; ; end *********************************************************************** ; ;****************************************************************************** ; ; Delay functions ; ; For 20Mhz ; 1 instruction - 200ns ; 1 call/goto instruction - 400ns ; ; For 10Mhz ; 1 instruction - 400ns ; 1 call/goto instruction - 800ns ; ; Here is formula to calculate each iterations call ; ; (767*(delay2-1) + 766) ; + 2 (call to WAITXXXLC) ; + 2 (init delay2) ; + 2 (goto delay2LOOP) ; + 2 final RETURN) ; ; 1ns = 10^-9s ; 1mcrs = 10^-6s ; 1ms = 10^-3s ; ; Names are for 20Mhz ; ; delay2 = 255 -> (iters 195592) (10Mhz 78,236,800ns) (20Mhz 39,118,400ns) ; WAIT1MS movlw .7 ;(iters 5376) (10Mhz 2,150,400ns) (20Mhz 1,075,200ns) WAITWMS movwf delay2 GOTO DELAY2LOOP WAIT2MS movlw .13 ;(iters 9978) (10Mhz 3,991,200ns) (20Mhz 1,995,600ns) movwf delay2 GOTO DELAY2LOOP WAIT5MS movlw .33 ;(iters 25318) (10Mhz 10,127,200ns) (20Mhz 5,063,600ns) movwf delay2 GOTO DELAY2LOOP DELAY2LOOP ;(767*(delay2-1) + 766) iterations (without return) #ifdef DEBUG_NODELAYS RETURN ;USE ONLY FOR DEBUG #endif movlw .255 movwf delay1 DELAY1LOOP decfsz delay1,F GOTO DELAY1LOOP decfsz delay2,F GOTO DELAY2LOOP RETURN ; ; end *********************************************************************** ; |