;------------------------------------------------------------------------------- ; FILE: EEPROM - 16F628A ; AUTH: Ed's Projects ; DATE: 01/07/2016 ; DESC: 4x4 Keypad input, 10 values saved to EEPROM, displayed on LCD ;------------------------------------------------------------------------------- LIST P=16F628A, R=DEC ; All numbers Decimal format unless otherwise stated. include ; Define configurations, registers, etc. __config _CP_OFF & _CPD_OFF & _LVP_OFF & _BOREN_ON & _MCLRE_OFF & _PWRTE_ON & _WDTE_OFF & _HS_OSC ;------------------------------------------------------------------------------- ;----------------------------- Port Definitions ------------------------------ ;------------------------------------------------------------------------------- ; PortA - Output - RA0 - Pin 17 - RS Register select for LCD ; PortA - Output - RA1 - Pin 18 - E Enable for LCD ; PortB - Output - RB4 - Pin 10 - DB4 Dataline for LCD ; PortB - Output - RB5 - Pin 11 - DB5 Dataline for LCD ; PortB - Output - RB6 - Pin 12 - DB6 Dataline for LCD ; PortB - Output - RB7 - Pin 13 - DB7 Dataline for LCD ; PortB - Output - RB0 - Pin 6 - Column 1 Keypad ; PortB - Output - RB1 - Pin 7 - Column 2 Keypad ; PortB - Output - RB2 - Pin 8 - Column 3 Keypad ; PortB - Output - RB3 - Pin 9 - Column 4 Keypad ; PortA - Input - RA2 - Pin 1 - Row 1 Keypad ; PortA - Input - RA3 - Pin 2 - Row 2 Keypad ; PortA - Input - RA4 - Pin 3 - Row 3 Keypad ; PortA - Input - RA5 - Pin 4 - Row 4 Keypad ;------------------------------------------------------------------------------- ;-------------------------------- Variables ---------------------------------- ;------------------------------------------------------------------------------- cblock h'20' micro200f ms2delayf ms2delayg dly0 Tmp temp temp2 temp3 temp4 temp5 startemp hashtemp offset keytemp vartemp lcdtemp clrtemp ee_data ee_adr endc ;------------------------------------------------------------------------------- ;----------------------------- Define Symbols -------------------------------- ;------------------------------------------------------------------------------- #define LCD4 PORTB, 4 #define LCD5 PORTB, 5 #define LCD6 PORTB, 6 #define LCD7 PORTB, 7 #define LCDRS PORTA, 0 #define LCDE PORTA, 1 #define R1 PORTA, 2 #define R2 PORTA, 3 #define R3 PORTA, 4 #define R4 PORTA, 5 #define C1 PORTB, 0 #define C2 PORTB, 1 #define C3 PORTB, 2 #define C4 PORTB, 3 ;------------------------------------------------------------------------------- ;------------------------------- Program Code -------------------------------- ;------------------------------------------------------------------------------- ORG 0 ;------------------------------------------------------------------------------- ;-------------------------- Initialisation of Ports -------------------------- ;------------------------------------------------------------------------------- Init bsf STATUS,RP0 ; Set RP0 to 1 bcf STATUS,RP1 ; Set RP1 to 0 ; Bank 1 Selected clrf VRCON ; Set Vref to off clrf TRISB ; Set all PortB as Output movlw b'00111100' ; Load 00111100 to working register movwf TRISA ; bcf STATUS,RP0 ; Set RP0 to 0 ; Bank 0 Selected movlw d'7' ; Load working register with "7" movwf CMCON ; Turn off comparators clrf PORTA clrf PORTB clrf micro200f clrf ms2delayf clrf ms2delayg clrf dly0 clrf Tmp clrf temp clrf temp2 clrf temp3 clrf temp4 clrf temp5 clrf startemp clrf hashtemp clrf keytemp clrf lcdtemp clrf clrtemp clrf ee_data clrf ee_adr movlw h'A0' movwf vartemp movlw h'A0' ; This section will clear the first 64 movwf FSR ; blocks of RAM in bank 1 clrram clrf INDF incf FSR, f incf clrtemp, f btfss clrtemp, 6 goto clrram ; Clear variables and output ports ;------------------------------------------------------------------------------- ;--------------------------- LCD Initialisation ------------------------------ ;------------------------------------------------------------------------------- movlw d'32' call delay bsf LCD5 bsf LCD4 call Enable call ms2delay call ms2delay call Enable call micro200 call Enable bcf LCD4 call Enable ;Function Set movlw b'00101000' ;4-bit mode, 2 lines, 5x7 matrix call SendLCD ;Display on / off movlw b'00001100' ;Display on, Cursor off, Blink off call SendLCD ;Entry Mode Set movlw b'00000110' ;Increment, Display shifted call SendLCD ;Cursor or display shift movlw b'00010000' ;Display Shift call SendLCD ;Clear Screen movlw b'00000001' ; Clear screen call SendLCD call ms2delay call ms2delay bsf LCDRS ; Set data mode goto Start ;------------------------------------------------------------------------------- ;----------------------------- Send Data to LCD ------------------------------ ;------------------------------------------------------------------------------- SendLCD ; Send data in two 4-bit nibbles movwf Tmp bcf LCD7 bcf LCD6 bcf LCD5 bcf LCD4 btfsc Tmp, 7 bsf LCD7 btfsc Tmp, 6 bsf LCD6 btfsc Tmp, 5 bsf LCD5 btfsc Tmp, 4 bsf LCD4 call Enable bcf LCD7 bcf LCD6 bcf LCD5 bcf LCD4 btfsc Tmp, 3 bsf LCD7 btfsc Tmp, 2 bsf LCD6 btfsc Tmp, 1 bsf LCD5 btfsc Tmp, 0 bsf LCD4 call Enable return ;------------------------------------------------------------------------------- ;--------------------------------- Enable ------------------------------------ ;------------------------------------------------------------------------------- Enable bsf LCDE nop nop nop nop bcf LCDE call micro200 call micro200 call micro200 return ;------------------------------------------------------------------------------- ;--------------------------------- LCD Clear --------------------------------- ;------------------------------------------------------------------------------- LCDClr bcf LCDRS movlw b'00000001' call SendLCD bsf LCDRS call ms2delay call ms2delay return ;------------------------------------------------------------------------------- ;----------------------------- LCD Cursor Shift ------------------------------ ;------------------------------------------------------------------------------- LCDShi bcf LCDRS iorlw b'10000000' call SendLCD bsf LCDRS call ms2delay return ;------------------------------------------------------------------------------- ;--------------------------- LCD Character Space ----------------------------- ;------------------------------------------------------------------------------- LCDSpace movlw d'32' call SendLCD return ;------------------------------------------------------------------------------- ;---------------------------- Loops 2ms Delay -------------------------------- ;------------------------------------------------------------------------------- delay movwf dly0 delayloop call ms2delay decfsz dly0, f goto delayloop return ;------------------------------------------------------------------------------- ;------------------------------- 2ms Delay ----------------------------------- ;------------------------------------------------------------------------------- ms2delay movlw d'8' movwf ms2delayg ms2delayc movlw d'250' movwf ms2delayf ms2delaya nop ;0.2us nop ;0.2us decfsz ms2delayf,f ;0.2us goto ms2delaya ;0.4us ;total 250us ms2delayb decfsz ms2delayg,f ;0.2us goto ms2delayc ;0.4us return ;return from call ;------------------------------------------------------------------------------- ;------------------------------- 200us Delay --------------------------------- ;------------------------------------------------------------------------------- micro200 movlw d'200' movwf micro200f micro200a nop ;0.2us nop ;0.2us decfsz micro200f,f ;0.2us goto micro200a ;0.4us return ;return from call ;------------------------------------------------------------------------------- ;--------------------------- Character Storage ------------------------------- ;------------------------------------------------------------------------------- Charr call LCDClr clrf offset charra movf offset, w call charrlookup ; fetch a character addlw 0 btfsc STATUS, Z return call SendLCD call micro200 incf offset, f goto charra charrlookup addwf PCL, f DT " Welcome to ", " EEPROM using the ", " Ed's Projects ", " PIC16F628A ", d'0' Char1 ; Since this table will cross the page boundary call LCDClr ; and increment the PCH then PCLATH must be clrf offset ; dealt with Char1a call Char1b ; Fetch a character addlw 0 btfsc STATUS, Z goto Char1c call SendLCD call micro200 incf offset, f ; Increment offset to choose next character goto Char1a ; from table Char1b movlw LOW table ; Get low 8 bits of table address addwf offset, w ; Check to see if a carry will occur movlw HIGH table ; Get high 5 bits of address btfsc STATUS, C ; Has page crossed? addlw 1 ; Yes then increment PCLATH - PCH movwf PCLATH ; Load high address into PCLATH - PCH movlw LOW table ; Get low 8 bits of table address again addwf offset, w ; Load original PCL offset value movwf PCL ; Jump into table table DT "Please enter a value ", d'0' Char1c movlw h'A0' ; Load start of RAM location to be sent movwf lcdtemp Chard movf lcdtemp, w movwf FSR movf INDF, w addlw d'48' call SendLCD incf lcdtemp movf lcdtemp, w xorlw h'AA' ; Check if ten digits have been sent, if btfss STATUS, Z ; so return goto Chard return ;------------------------------------------------------------------------------- ;---------------------------------- Keypad ----------------------------------- ;------------------------------------------------------------------------------- Keyscan bsf C1 ; Check to see if any key has been pressed bsf C2 bsf C3 bsf C4 btfsc R1 goto scanprocess btfsc R2 goto scanprocess btfsc R3 goto scanprocess btfsc R4 goto scanprocess return Keynot ; Return to main program when no keys are bsf C1 ; pressed bsf C2 bsf C3 bsf C4 btfsc R1 goto Keynot btfsc R2 goto Keynot btfsc R3 goto Keynot btfsc R4 goto Keynot bsf temp2, 0 return scanprocess ; Start scanning which key is pressed bsf C1 bcf C2 bcf C3 bcf C4 movlw d'1' call Rscan bcf C1 movlw d'2' bsf C2 call Rscan bcf C2 movlw d'3' bsf C3 call Rscan bcf C3 movlw d'32' bsf C4 call Rscan movf keytemp, w xorlw d'11' btfsc STATUS, Z clrf keytemp ; When 48 is added later on it will translate movf keytemp, w ; to the ASCII number 0 xorlw d'10' btfsc STATUS, Z call star movf keytemp, w xorlw d'12' btfsc STATUS, Z call hash goto Keynot star ; When 48 is added later on it will roll over movlw d'250' ; to ASCII number 42 - * movwf keytemp bsf startemp, 0 ; Used as confirm key return hash movlw d'243' ; When 48 is added later on it will roll over movwf keytemp ; to ASCII number 35 - # bsf hashtemp, 0 ; Used as an option key return Rscan btfsc R1 goto R1set btfsc R2 goto R2set btfsc R3 goto R3set btfsc R4 goto R4set return R1set movwf keytemp call checkalpha goto Keynot R2set addlw d'3' movwf keytemp call checkalpha goto Keynot R3set addlw d'6' movwf keytemp call checkalpha goto Keynot R4set addlw d'9' movwf keytemp call checkalpha goto Keynot checkalpha btfss keytemp, 5 return movf keytemp, w xorlw b'00100000' btfsc STATUS, Z goto leta movf keytemp, w xorlw b'00100011' btfsc STATUS, Z goto letb movf keytemp, w xorlw b'00100110' btfsc STATUS, Z goto letc goto letd leta movlw d'17' ; When 48 is added later on these will movwf keytemp ; translate to ASCII letter corresponding return ; with what was pressed on the keypad letb movlw d'18' movwf keytemp return letc movlw d'19' movwf keytemp return letd movlw d'20' movwf keytemp return ;------------------------------------------------------------------------------- ;------------------------------ EEPROM Write --------------------------------- ;------------------------------------------------------------------------------- Ewrite movf ee_adr, w ; Load working register with ee_adr bsf STATUS, RP0 ; Bank 1 Selected movwf EEADR ; Set location to write to EEPROM bcf STATUS, RP0 ; Bank 0 Selected movf ee_data, w ; Load working register with ee_data bsf STATUS, RP0 ; Bank 1 Selected movwf EEDATA ; Data to be written to address bsf EECON1, WREN ; Enables EEPROM write bcf INTCON, GIE ; Global interrupts disabled, all ints off btfsc INTCON, GIE ; Check to make sure interrupts are disabled goto $-1 ; Jump to above instruction ; The next four lines must be there to allow the data to be written movlw d'85' ; Load working register with decimal 85 movwf EECON2 ; Load working register to EECON2 movlw d'170' ; Load working register with decimal 170 movwf EECON2 ; Load working register to EECON2 bsf EECON1, WR ; Send data btfsc EECON1, WR goto $-1 ; If 1, check again, 0 indicates data written bsf INTCON, GIE ; Turn back on all interrupts bcf EECON1, WREN ; Turn off EEPROM write bcf STATUS, RP0 ; Select bank 0 return ; return from where left off ;------------------------------------------------------------------------------- ;------------------------------ EEPROM Read ---------------------------------- ;------------------------------------------------------------------------------- Eread movf ee_adr, w ; Load working register with ee_adr bsf STATUS, RP0 ; Bank 1 Selected movwf EEADR ; Set location to read EEPROM from bsf EECON1, RD ; Enables EEPROM read btfsc EECON1, RD goto $-1 movf EEDATA, w ; Load working resgister with EEPROM data bcf STATUS, RP0 ; Bank 0 Selected movwf ee_data return ; return from where left off ;------------------------------------------------------------------------------- ;------------------------- Main part of program ------------------------------ ;------------------------------------------------------------------------------- Start call Charr Starta movlw d'250' call delay movlw d'250' call delay movlw d'250' call delay movlw d'250' call delay call Char1 movlw h'A0' movwf vartemp Here call Keyscan btfsc startemp, 0 ; Confirm Key goto confirm btfsc hashtemp, 0 ; Option / Confirm Key goto hashcon btfsc temp2, 0 ; Only write if a new character has been entered call incvar clrf temp2 clrf keytemp goto Here incvar movf vartemp, w movwf FSR movf keytemp, w movwf INDF call Char1 clrf keytemp incf vartemp movf vartemp, w xorlw h'AA' btfss STATUS, Z return movlw h'A0' movwf vartemp return confirm clrf keytemp clrf temp2 clrf startemp movlw h'A0' movwf vartemp clrf temp3 ; EEPROM address variable movlw h'A0' movwf temp4 ; Keypad check variable confirma movf temp3, w movwf ee_adr call Eread movf temp4, w movwf FSR movf INDF, w xorwf ee_data, w btfss STATUS, Z goto wrongcode incf temp3, f incf temp4, f movf temp3, w xorlw d'10' btfss STATUS, Z goto confirma ; String to LCD saying correct code call LCDClr call LCDSpace call LCDSpace movlw d'67' ; C call SendLCD movlw d'111' ; o call SendLCD movlw d'114' ; r call SendLCD movlw d'114' ; r call SendLCD movlw d'101' ; e call SendLCD movlw d'99' ; c call SendLCD movlw d'116' ; t call SendLCD call LCDSpace movlw d'80' ; P call SendLCD movlw d'97' ; a call SendLCD movlw d'115' ; s call SendLCD movlw d'115' ; s call SendLCD movlw d'119' ; w call SendLCD movlw d'111' ; o call SendLCD movlw d'114' ; r call SendLCD movlw d'100' ; d call SendLCD goto Starta hashcon clrf keytemp clrf temp2 clrf hashtemp movlw h'A0' movwf vartemp clrf temp3 ; EEPROM address variable movlw h'A0' movwf temp4 ; Keypad new password variable hashcona movf temp3, w movwf ee_adr movf temp4, w movwf FSR movf INDF, w movwf ee_data call Ewrite incf temp3, f incf temp4, f movf temp3, w xorlw d'10' btfss STATUS, Z goto hashcona call LCDClr call LCDSpace call LCDSpace movlw d'80' ; P call SendLCD movlw d'97' ; a call SendLCD movlw d'115' ; s call SendLCD movlw d'115' ; s call SendLCD movlw d'119' ; w call SendLCD movlw d'111' ; o call SendLCD movlw d'114' ; r call SendLCD movlw d'100' ; d call SendLCD call LCDSpace movlw d'67' ; C call SendLCD movlw d'104' ; h call SendLCD movlw d'97' ; a call SendLCD movlw d'110' ; n call SendLCD movlw d'103' ; g call SendLCD movlw d'101' ; e call SendLCD movlw d'100' ; d call SendLCD call LCDSpace goto Starta wrongcode call LCDClr call LCDSpace call LCDSpace call LCDSpace movlw d'87' ; W call SendLCD movlw d'114' ; r call SendLCD movlw d'111' ; o call SendLCD movlw d'110' ; n call SendLCD movlw d'103' ; g call SendLCD call LCDSpace movlw d'80' ; P call SendLCD movlw d'97' ; a call SendLCD movlw d'115' ; s call SendLCD movlw d'115' ; s call SendLCD movlw d'119' ; w call SendLCD movlw d'111' ; o call SendLCD movlw d'114' ; r call SendLCD movlw d'100' ; d call SendLCD goto Starta end