; GPR's (General Purpose Registers) are used for the following: ;H070 and H071: counters for short delay and utility delay ;H072 used to temporarily store characters ;H075 used as offset counter in our tables. list p=16F1455 ; list directive to define processor #include "p16F1455.inc" ; processor specific variable definitions __CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_ON & _FCMEN_ON __CONFIG _CONFIG2, _WRT_OFF & _CPUDIV_NOCLKDIV & _USBLSCLK_48MHz & _PLLMULT_3x & _PLLEN_DISABLED & _STVREN_ON & _BORV_LO & _LPBOR_OFF & _LVP_ON errorlevel -302 , -207 ; suppress message 302 from list file banksel OSCCON movlw B'00101110' ; we need to slow down the processor for the LCD display driver. Max 2 Mhz. We'll run at 1 Mhz movwf OSCCON ; everything above this line is simply setting up the processor at 1 MHz. banksel TRISA ; set up PORTA for outputs clrf TRISA banksel LATA ; Don't forget this! LATA and TRISA are NOT in the same bank, though they are both for the same register! clrf LATA ;this sends out RS=0 and E=0 from PORTA to the control lines on the LCD display call utility_delay ; waits about 0.8 seconds for display to initialize banksel TRISC clrf TRISC ; we can now set PORTC to all outputs ; we'll now set the display to 4 bit mode ;NOTE: all binary numbers must include all 8 bits. However, only the lower 4 bits are actually connected and therefore, used banksel LATC movlw B'00000010' ;send first command for 4 bit mode. The lower nibble is actually 0000, but not connected. This is the upper nibble movwf LATC call pulse_e banksel LATC movlw B'00000010' ;send upper nibble command to 4 bit mode. movwf LATC call pulse_e ; We are now in 4 bit mode. banksel LATC movlw B'00001100' ;send lower nibble command to 4 bit mode and two line mode. movwf LATC call pulse_e ; we are now in 4 bit, 2 line mode. banksel LATC movlw B'00000000' ;send upper nibble to turn on display, set cursor. movwf LATC call pulse_e banksel LATC movlw B'00001111' ;send lower nibble to turn on display, set cursor. movwf LATC call pulse_e ; The display is now turned on, with a flashing underline cursor at the current character location banksel LATA bsf LATA,4 ; sets RS to 1, putting it into CHARACTER mode banksel LATC ;here's where we lock and load our message, sending it one character at a time ;*********** Subroutine to call a table of characters, a Hex 00 means the end of the table, we can just check the 0 flag movlw 0 movwf H'075' ;this sets up our own pointer for the table lookup, using GPR at Hex address 075 clrw ;clear the W cause that's the number on our pointer we're startin' with. ;************************************************************************************************************************************* ;******************************Main routine which retrieves a character from the table and then writes it to the LCD display ;************************************************************************************************************************************* message_send1: call message_list1 movwf H'072' ;whatever character we retrieved is stored in GPR 072 clrw ;clear the W for our math function iorwf H'072',0 ;we perform an inclusive OR between the W and GPR 072. If there are ANY 1's in there, we won't get a 0 btfsc STATUS,2 ;if we came back with a 0, the zero bit on STATUS will now be set - leave this subroutine if we got a 0 from our table goto next_step swapf H'072',0 ;this swaps the two nibbles from GPR 072 and stuffs the result in the W register. banksel LATC ;NOTE: swapf *does not change* what's in the GPR unless we store it there (put a 1 after the comma in the command) movwf LATC ;we loaded the upper nibble into the W and now sent it to the LCD display as the first nibble call pulse_e ;pulse the E line to load the number we just sent movf H'072',0 ;because our swapf command did NOT swap the nibbles in the GPR itself, we can now just load the GPR contents onto LATC banksel LATC ;and the lower nibble of our character will be put onto the LATC movwf LATC call pulse_e ;pulse the E line to load the number we just sent incf H'075',1 ;increment our pointer movf H'075',0 ;load our pointer into the W register. This will affect WHICH retlw in our list it accesses goto message_send1 next_step: ;****************sets cursor to first address of second row**************** ;these lines now send a command to move the cursor to a new location. See downloadable display map to change it. banksel LATA bcf LATA,4 ; sets RS to 0, putting it into COMMAND mode banksel LATC movlw B'00001100' ;first nibble of address command for address H40 We must send H80 + H40 = HC0 movwf LATC call pulse_e banksel LATC movlw B'00000000' ; the second nibble of address command HC0 movwf LATC call pulse_e call short_delay ; Remember that some commands took up to 2 miliseconds to fulfill? We just sent a command, let's wait a short delay to let it finish. ;****************END sets cursor to first address of second row**************** banksel LATA bsf LATA,4 ; sets RS to 1, putting LCD back into CHARACTER mode ;*********** Second routine to call a table of characters, a Hex 00 means the end of the table clrf H'075' ;this clears our own pointer for the table lookup, using GPR at Hex address 075 movf H'075',0 ; move out pointer to the W register message_send2: call message_list2 movwf H'072' ;whatever character we retrieved is stored in GPR 072 clrw ;clear the W for our math function iorwf H'072',0 ;we perform an inclusive OR between the W and GPR 072. If there are ANY 1's in there, we won't get a 0 btfsc STATUS,2 ;if we came back with a 0, the zero bit on STATUS will now be set - leave this subroutine if we got a 0 from our table goto endless_loop swapf H'072',0 ;this swaps the two nibbles from GPR 072 and stuffs the result in the W register. NOTE: DOES NOT CHANGE what's in the GPR banksel LATC movwf LATC ;we loaded the upper nibble into the W and now sent it to the LCD display as the first nibble call pulse_e ;pulse the E line to load the number we just sent movf H'072',0 ;because our swapf command did NOT swap the nibbles in the GPR itself, we can now just load the GPR contents onto LATC banksel LATC ;and the lower nibble of our character will be put onto the LATC movwf LATC call pulse_e ;pulse the E line to load the number we just sent incf H'075',1 ;increment our pointer movf H'075',0 ;load our pointer into the W register. This will affect WHICH retlw in our list it accesses goto message_send2 endless_loop goto endless_loop ;*****************************Our first message to be sent************************************ message_list1: ;first message to be displayed addwf PCL,1 ; we add our count to the program counter! retlw "B" retlw "r" retlw "a" retlw "v" retlw "o" retlw "!" retlw 00 ;*****************************Our second message to be sent************************************ message_list2: ;obviously, the next line of message to send addwf PCL,1 ; we add our count to the program counter! retlw "R" retlw "a" retlw "n" retlw "d" retlw "o" retlw "m" retlw " " retlw "m" retlw "e" retlw "s" retlw "s" retlw "a" retlw "g" retlw "e" retlw 00 utility_delay: ; this subroutine is a utility delay that counts down from 255 255 times. That's a total count of 65025. It takes approximately 0.8 seconds at 1 MHz movlw D'255' movwf H'070' ; load 255 into first register movlw D'255' movwf H'071' ; load 255 into second register subloop: decfsz H'070', 1 ; count down in first register till we hit 0 goto subloop movlw D'255' movwf H'070' ; load 255 into first register again decfsz H'071', 1 ; count down 1 on second register. If we're at 0, we've now gone through 255 loops of 255. Return back to the main program. goto subloop return pulse_e: banksel LATA bsf LATA,5 ;sends one pulse on the E line nop ; waitaminit nop ; waitaminit bcf LATA,5 ;sets E line to low nop ; waitaminit nop ; waitaminit return short_delay: ; this subroutine is a utility delay that counts down from 255 to 0. It takes approximately 3 miliseconds at 1 MHz. movlw D'255' movwf H'070' ; load 255 into first register shortloop: decfsz H'070', 1 ; count down in first register till we hit 0 goto shortloop return end