by Chris Camerlin [camerlin at ovis.net] and Micheal Rigby Jones
Chris Camerlin says:
...a keyless entry system where you use a 4x4 keypad to unlock an electric door strike on the door to your house. I built this and it works like a charm so the decoding of the keypad section is correct. I have the data sheet of the keypad with truth table if you want that too. I used a keypad from grayhill. I got it through Jameco. This program is a little different from the original that Micheal Rigby Jones sent me, I changed it some to fit my needs. I like to give programming credit when credit is do. The program is heavily commented but if you would like more info on the project and how exactly it works let me know.
See:
; *************************** ; * * ; * Keyless Entry Program * ; * * ; *************************** ; ; ;DIRECTIVES list p=16f84 ifndef __16f84 messg "processor-header file mismatch. verify selected processor." endif ;REGISTER EQU w equ 0x0000 f equ 0x0001 ;the following equates are used for reference ;REGISTER FILES BANK 0 indf equ 0x0000 ;uses contents of FSR to address tmr0 equ 0x0001 ;8-bit realtime clock/counter pcl equ 0x0002 ;low order 8 bits of program counter status equ 0x0003 ;arithmetic status of ALU fsr equ 0x0004 ;indirect data memory address pointer porta equ 0x0005 ; portb equ 0x0006 ; eedata equ 0x0008 ;eeprom data register eeadr equ 0x0009 ;eeprom address register pclath equ 0x000a ;13 program counter intcon equ 0x000b ;RD/WR register contains enable bits Int ;------------------------------------------------- ;REGISTER FILES BANK 1 option_reg equ 0x0081 ;enables bits for TMR0 trisa equ 0x0085 ;1=input trisb equ 0x0086 eecon1 equ 0x0088 ;control register for read writes eecon2 equ 0x0089 ;-------------------------------------------------- ;STATUS BITS ;Arithmetic status of the ALU (w) irp equ 0x0007 ;register bank select (indirect) rp1 equ 0x0006 ;register bank select (direct) rp0 equ 0x0005 ; not_to equ 0x0004 ;time out bit not_pd equ 0x0003 ;power down bit z equ 0x0002 ;zero dc equ 0x0001 ;digit carry c equ 0x0000 ;carry ;--------------------------------------------------- ;INTCON BITS ;Enable bits for all interupt sources gie equ 0x0007 ;global interrupt enable bit eeie equ 0x0006 ;ee write complete inter enable t0ie equ 0x0005 ;TMR0 overflow inter enable inte equ 0x0004 ;RB0/INT Enable bit rbie equ 0x0003 ;RB port change t0if equ 0x0002 intf equ 0x0001 rbif equ 0x0000 ;--------------------------------------------------- ;OPTION BITS ;Configures TMRO/WDT/esternal INT/weak pull-ups on PortB not_rbpu equ 0x0007 ;PortB pull up enable bit (1-disable) intedg equ 0x0006 ;interrupt edge select bit t0cs equ 0x0005 ;TMR0 clock source select bit t0se equ 0x0004 ;TMR0 source edge psa equ 0x0003 ;prescalars ps2 equ 0x0002 ps1 equ 0x0001 ps0 equ 0x0000 ;--------------------------------------------------- ;EECON1 BITS ;Control Register eeif equ 0x0004 ;interrupt flag bit wrerr equ 0x0003 ;a write operation is interrupted wren equ 0x0002 ;allow a write operation wr equ 0x0001 ;initiate write rd equ 0x0000 ;initiate read ;upper 3 bits are defaulted to 000 ;--------------------------------------------------- ;RAM __maxram 0xaf __badram 0x07, 0x50-0x7f, 0x87 ;--------------------------------------------------- ;CONFIGURATION BITS ;_cp = code protection bits ;_pwrite = power up timer enable bit ;_wdt = watch dog timer ;_lp,_xt,_hs,_rc = oscillator modes _cp_on equ 0x3fef ;11111111101111 ;code protection bits _cp_off equ 0x3fff ;11111111111111 _pwrte_on equ 0x3fff ;11111111111111 ;power up timer enable _pwrte_off equ 0x3ff7 ;11111111110111 _wdt_on equ 0x3fff ;11111111111111 ;watch dog timer _wdt_off equ 0x3ffb ;11111111111011 _lp_osc equ 0x3ffc ;11111111111100 ;RC=11 _xt_osc equ 0x3ffd ;11111111111101 ;HS=10 _hs_osc equ 0x3ffe ;11111111111110 ;XT=01 _rc_osc equ 0x3fff ;11111111111111 ;LP=00 ;setting the congiguration bits __config _xt_osc & _wdt_off & _pwrte_on & _cp_off ;--------------------------------------------------------- xtal_freq = d'4000000' ;crystal frequency clock = xtal_freq/4 ;base operating freq. ;PORTA ASSIGNMENTS n_red equ 0 ;low on ra0 turns red led on n_green equ 1 ;low on ra1 turns green led on relay equ 2 ;high on ra2 turns relay on ra3 equ 3 ;not used ra4 equ 4 ;not used ;PIN OUTS FOR KEYPAD ; ; <5> <6> <7> <8> ; <1> 1 2 3 A ; <2> 4 5 6 B ; <3> 7 8 9 C ; <4> * 0 # D ;decoding of keypad (truth table from Grayhill) xload = b'11100111' ;* - LOAD yload = 'l' x0 = b'11010111' ;0 y0 = '0' xclr = b'10110111' ;# - CLEAR yclr = 'c' xent = b'01110111' ;D - ENTER yent = 'e' x1 = b'11101110' ;1 y1 = '1' x2 = b'11011110' ;2 y2 = '2' x3 = b'10111110' ;3 y3 = '3' xrun = b'01111011' ;C - RUN yrun = 'r' x4 = b'11101101' ;4 y4 = '4' x5 = b'11011101' ;5 y5 = '5' x6 = b'10111101' ;6 y6 = '6' xdown = b'01111101' ;B ydown = 'd' x7 = b'11101011' ;7 y7 = '7' x8 = b'11011011' ;8 y8 = '8' x9 = b'10111011' ;9 y9 = '9' xup = b'01111110' ;A yup = 'u' xx = b'00000000' ;allows to test z ;eeprom data ;area is 64x8 bytes org 0x2100 usercode0 de xx, xx, xx, xx, xx, xx, xx, xx usercode1 de xx, xx, xx, xx, xx, xx, xx, xx usercode2 de xx, xx, xx, xx, xx, xx, xx, xx usercode3 de xx, xx, xx, xx, xx, xx, xx, xx usercode4 de xx, xx, xx, xx, xx, xx, xx, xx usercode5 de xx, xx, xx, xx, xx, xx, xx, xx umastercode de y1, y2, y3, y4, y5, y6, y7, y8 mastercode de y5, y5, y5, y5, y5, y5, y5, y5 ;usercode can be changed which is represented by the xx ;mastercode can not be changed (55555555) ; ************************************************************** ; * file register ram starts at 0ch and ends at 4fh (68 bytes) * ; ************************************************************** cblock h'0c' keycode ;stores uncoded or decoded keycode savew ;saves w for the interupt handler savestatus ;saves statis register for the int. handler savefsr ;saves the interrupt pointer eeadr1 ;storage for eeadr1 xmillisec ;first loop counter for waits in msec ymillisec ;second loop counter for waits in msec keycounter1 ;first loop counter keycounter2 ;second loop counter ok ;non-zero means ok blinks ;indicates number of blinks to perform exitkey ;holds value of key used to terminate entry usercounter1 ;user key entry user0 ;user0-7 holds the code entered by the keypad user1 ;for usercode and mastercode user2 user3 user4 user5 user6 user7 onetime ;one time use code endc org h'0000' ;sets origin in rom goto setup ;gets around the interrupt vector org h'0004' ;sets the interrupt vector ; ************************************************************** ; * Interupt Service Routine * ; ************************************************************** inthandler movwf savew ;saves w register swapf status,w ;twist status so its not effected movwf savestatus ;save status register movf fsr,w ;saves the interrupt pointer movwf savefsr ;saves the fsr now in savefsr ;the following loops are used to waste 25msecs for debounce ;doing 65000 instructions in the loops will waste 25msec of time ;65000/400nsec = 26msec clrf keycode ;clears keycode clrf keycounter1 ;initialize secound counter loop256x256 decfsz keycounter1,f ;256 loops ;since keycounter1=h'00' it will ;decrement to h'FF' goto more256x256 goto nogood more256x256 clrf keycounter2 ;initialize first counter loopinner256 decfsz keycounter2,f ;256fist loops per second loop goto innertest goto loop256x256 innertest comf portb,w ;compliments portb andlw b'11110000' ;tests for any key hit btfsc status,z ;tests z flag/skips next if 0 goto loopinner256 ;try it again ;if we are here their was probably a key hit scankey0 movlw b'11111110' ;loads mask movwf portb ;set outputs and inputs nop ;waste time to settle movf portb,w ;read current value into keycode movwf keycode ;through the w register comf keycode,w ;reverse bits to match truthtab andlw b'11110000' ;look at the high bites btfss status,z ;no hit sets z flag goto decode scankey1 movlw b'11111101' ;loads mask movwf portb ;set outputs and inputs nop ;waste time to settle movf portb,w ;read current value into keycode movwf keycode ;through the w register comf keycode,w ;reverse bits to match truthtab andlw b'11110000' ;look at the high bites btfss status,z ;no hit sets z flag goto decode scankey2 movlw b'11111011' ;loads mask movwf portb ;set outputs and inputs nop ;waste time to settle movf portb,w ;read current value into keycode movwf keycode ;through the w register comf keycode,w ;reverse bits to match truthtab andlw b'11110000' ;look at the high bites btfss status,z ;no hit sets z flag goto decode scankey3 movlw b'11110111' ;loads mask movwf portb ;set outputs and inputs nop ;waste time to settle movf portb,w ;read current value into keycode movwf keycode ;through the w register comf keycode,w ;reverse bits to match truthtab andlw b'11110000' ;look at the high bites btfss status,z ;no hit sets z flag goto decode goto loopinner256 ;no keys were hit yet clrf keycode nogood clrf keycode ;reset keycode decode movf keycode,w btfsc status,z goto fillercode decode0 movf keycode,w ;reloads keycode sublw x0 ;subs w from x0 btfss status,z ; goto decode1 ;checks next code movlw y0 ;loads the ascii goto savecode ;saves the ascii code decode1 movf keycode,w sublw x1 btfss status,z goto decode2 movlw y1 goto savecode decode2 movf keycode,w sublw x2 btfss status,z goto decode3 movlw y2 goto savecode decode3 movf keycode,w sublw x3 btfss status,z goto decode4 movlw y3 goto savecode decode4 movf keycode,w sublw x4 btfss status,z goto decode5 movlw y4 goto savecode decode5 movf keycode,w sublw x5 btfss status,z goto decode6 movlw y5 goto savecode decode6 movf keycode,w sublw x6 btfss status,z goto decode7 movlw y6 goto savecode decode7 movf keycode,w sublw x7 btfss status,z goto decode8 movlw y7 goto savecode decode8 movf keycode,w sublw x8 btfss status,z goto decode9 movlw y8 goto savecode decode9 movf keycode,w sublw x9 btfss status,z goto decodeload movlw y9 goto savecode decodeload movf keycode,w sublw xload btfss status,z goto decodeclr movlw yload goto savecode decodeclr movf keycode,w sublw xclr btfss status,z goto decodeent movlw yclr goto savecode decodeent movf keycode,w sublw xent btfss status,z goto decoderun movlw yent goto savecode decoderun movf keycode,w sublw xrun btfss status,z goto decodedown movlw yrun goto savecode decodedown movf keycode,w sublw xdown btfss status,z goto decodeup movlw ydown goto savecode decodeup movf keycode,w sublw xup btfss status,z goto fillercode movlw yup goto savecode fillercode clrf keycode ;set up filler code goto intreturn ;skips delay savecode movwf keycode ;store keycode bsf porta,n_red ;turn red off movlw b'11110000' movwf portb nop release comf portb,w ;wait for key to be released andlw b'11110000' ;only check upper 4 bits btfss status,z goto release ;if key is down...wait movlw d'25' ;set debounce for 25msec call wmillisec comf portb,w andlw b'11110000' btfss status,z goto release ;if key is still down movlw d'25' call wmillisec intreturn movlw b'11110000' movwf portb bcf porta,n_red ;turn red on after keypress bcf intcon,rbif ;clear interrupt flag ;1 when at least 1 of 7-4 has ; changed ;0- nothing has changed ;restoring everything saved at beginning movf savefsr,w movwf fsr swapf savestatus,w movwf status swapf savew,f swapf savew,w retfie ;return from interupt ;keycode now contains valid keycode ;anything else gives a 00000000 in keycode ;=============================================================== ;THE SETUP SECTION IS USED TO CONFIGURE THE REGISTERS AND PORTS ;=============================================================== setup ;PORTA and PORTB bsf status,rp0 ;sets rp0 in status register to 1 movlw b'00000000' ;laods w with 00h to set porta I/O direction ;w is cleared so trisa reg. can be used to configure movwf trisa ;moves a copy of w into tris ;0=output, 1=input, tris is setup for all outputs ;that completes configuration for porta movlw b'11110000' ;moves copy of w into tris register movwf trisb ;0Fh in the trisb register sets RB7-RB4 as outputs ;and RB3-0 as inputs since they are used for the keypad ;that completes configuration for portb ;OPTION bcf option_reg,not_rbpu ;the not rbpu is cleared so that internal ;pull-ups are enabled bcf option_reg,intedg ;clears bit6 of option to make interupt on ;on falling edge bcf option_reg,t0cs ;enables internal clkout bcf option_reg,t0se ;inc on low to high transistion bcf option_reg,psa ;enables the watch dog timer bcf option_reg,ps2 ;a 000 on these last 3 bits sets the rate at bcf option_reg,ps1 ;a 1:1 ratio bcf option_reg,ps0 ;STATUS bcf status,rp0 ;a 0 at rp0 selects bank 0 ;INTCON (interupt configuration) clrf tmr0 ;resets tmr0 since I am not using it clrf intcon ;clears any interupts that may be present bsf intcon,gie ;sets the GIE bit so all interupts are enabled bsf intcon,rbie ;enables RB port change on pins 7,6,5,4 clrf keycode ;clears keycode so that no code currently exists bcf porta,relay ;relay is equ. so in turns the relay off ;END OF SETUP FOR I/O ;************************************************************************** ; MAIN PROGRAM * ;************************************************************************** ;enter notes on how program works here mainprog movlw b'11110000' ;scans all 4 lines from keypad at once movwf portb ;initializes keypad scanning bcf porta,relay ;relay was equ to 02h, a high on ra2 turns the relay on ;this instruction clrs the relay bit so relay is off bcf porta,n_red ;n_red was equ to 0h (ra0) ;low on ra0 turns red LED on ;red is usually on unless a key is depressed ;the interupt will turn it back off bsf porta,n_green ;n_green was equated to 01h (ra1) ; low on ra1 turns on green light ;bsf sets this bit high so green light is off movf keycode,w ;checks to see if CLR (*) button was hit sublw yclr ;subtracts w from '10110111', result in w btfsc status,z ;tests the z flag in STATUS register if it is '0' ;it skips next instruction ;1=result of arithmetic is zero,0=result in not zero ;if ystr was hit z flag will be a '1' goto gotyclr ;if ystr was hit then i have to handle that separetely bsf porta,n_green ;turn green off clrf keycode mainloop movf keycode,w ;check to see if keycode is there btfsc status,z ;check the z flag goto mainloop ;loop until there is a code in keycode ;this was handled by the interrupt sublw yclr ;check for ystr btfsc status,z ; goto gotyclr goto mainloop ;----------------------------------------------------------------------------------- gotyclr bcf porta,n_green ;turns on green led to indicate that ystr was hit movlw d'20' ;d'20' is used as a counter for the msec wait call wmillisec ;sub to create the 1msec on time for the green led bsf porta,n_green ;turns green led off clrf keycode ;clears keycode and begins to wait for next code gotyclr1 movf keycode,w ;moves contents of keycode into w so that it can be checked btfsc status,z ;skips next inst. if the z flag is zero goto gotyclr1 ;loops while empty movf keycode,w ;the next 4 lines checks for ystr again. if it was we go back sublw yclr btfsc status,z ;to gotystr to start over. if it is not another ystr then it goto gotyclr ;skips the goto gotystr inst. and calls 'getuser' call getuser ;gets a set of inputs movf exitkey,w ;check for exitmode sublw 0 ;was it an error btfsc status,z goto mainprog ;if it was an error then start over movf exitkey,w sublw yent ;checks for yd btfsc status,z goto wasent ;if it was yd we handle it here movf exitkey,w sublw yrun ;check for yc btfsc status,z goto wasrun goto mainprog ;anything else was an error wasent ;compare with code movlw 0*8 ;usercode check movwf eeadr call compare8 movf ok,w ;if ok is not zero then we have a match btfss status,z goto entok movlw 1*8 ;mastercode check movwf eeadr call compare8 movf ok,w btfss status,z goto entok movlw 2*8 movwf eeadr call compare8 movf ok,w btfss status,z goto entok movlw 3*8 movwf eeadr call compare8 movf ok,w btfss status,z goto entok movlw 4*8 movwf eeadr call compare8 movf ok,w btfss status,z goto entok movlw 5*8 movwf eeadr call compare8 movf ok,w btfss status,z goto entok1 movlw 6*8 movwf eeadr call compare8 movf ok,w btfss status,z goto entok movlw 7*8 movwf eeadr call compare8 movf ok,w btfss status,z goto entok goto mainprog ;if no sets were matched then it is wrong code ;if we are here then code was correct nogood2 clrf onetime decf onetime,1 goto mainprog entok1 incfsz onetime,1 ;if already used goes back to mainprog goto entok goto nogood2 entok decf onetime,1 decf onetime,1 bsf porta,relay ;turn relay on movlw d'100' ;for 100*100 msec = 1 sec movwf usercounter1 clrf keycode ;clear keycode to allow new key ldelay movf keycode,w ;any key hit will terminate btfss status,z goto mainprog bcf porta,n_red ;turn red on bsf porta,n_green ;turn green led off movlw d'50' call wmillisec ;delay 50msec bsf porta,n_red ;turn red off bcf porta,n_green ;turn green on movlw d'50' call wmillisec ;delay 50msec decfsz usercounter1,f ;update counter goto ldelay goto mainprog wasrun ;compare user set with mastercode ;if ok, then allow new entry set ;turn on green led ;1st key is pointer, next 8 max ;get entered at pointer in eeprom ;then goto mainprog movlw 6*8 ;compares with mastercode movwf eeadr call compare8 movf ok,w btfss status,z goto runok movlw 7*8 movwf eeadr call compare8 movf ok,w btfss status,z goto runok goto mainprog runok clrf keycode ;clears any old key data bcf porta,n_green ;turn green led on runloop1 bcf porta,n_red ;turn red on movlw d'35' call wmillisec ;delay for 35msec bsf porta,n_red ;red off movlw d'35' call wmillisec ;delay for 35msec movf keycode,w ;interrupt will load it btfsc status,z goto runloop1 ;wait for key bcf porta,n_red ;once key is found turn red on bcf porta,n_green ;turn green on sublw yclr btfsc status,z goto mainprog ;handle ystr movf keycode,w ;look at code again sublw '6' ;allow only stuff less than 6 btfss status,c ;if w<6 c is set, if w>6 c is cleared goto mainprog movf keycode,w ;look at code once again andlw b'00000111' ;convert from ascii to binary movwf eeadr1 ;save it decf eeadr1,f ;reduce address by 1 btfss eeadr1,7 ;0-1 would give us 11111111 goto rollem ;if msb=0 handle it movlw b'00000110' ;convert 0 to 6 movwf eeadr1 ;so rollem bcf status,c ;initial carry in must be 0 rlf eeadr1,f ;*2 rlf eeadr1,f ;*4 rlf eeadr1,f ;*8 ;we now have proper ee address set in eeadr1 eeadrok clrf keycode ;get ready for next key loadloop movf keycode,w ;interrupt will load it btfsc status,z ; goto loadloop ;wait for key sublw yload ;must be the 'load' key btfss status,z goto mainprog ;if not loose it clrf keycode call getuser ;get user inputs movf exitkey,w ;check for exitmode sublw yent ;check for ent btfss status,z ; goto mainprog ;on error or ystr start all over ent2stuff movlw d'8' ;eight digits to be moved movwf usercounter1 ;used as a counter movf eeadr1,w ;recover starting address movwf eeadr ;set up ee address movlw user0 ;point to user set in ram movwf fsr ;make it indirect pointer nextent2 movf indf,w ;use indirect pointer movwf eedata ;copy ram to eedata call writeeedata ;use sub to do it decfsz usercounter1,f ;update loop goto next1ent2 ; goto mainprog ;when done start over next1ent2 incf eeadr,f ;update ee address incf fsr,f ;update indirect pointer goto nextent2 ;do all 8 digits ;----------------------------------------------------------------------------------- getuser clrf exitkey ;get ready for next key movf keycode,w ;checks for ystr again sublw yclr btfss status,z goto get8keys ;if it wasn't ystr then go to get8keys ;if it was then go to handleystr handleyclr movlw h'00' movwf exitkey ;exitkey still has the ystr so it can be used here goto checkret ;handle ystr special get8keys clrf user0 ;clears the key holders clrf user1 clrf user2 clrf user3 clrf user4 clrf user5 clrf user6 clrf user7 ;clears master key holder movlw user0 movwf fsr ;sets interupt vector so (allows indirect addressing) clrf usercounter1 ;we handle 8 keys, 1-8 get8wait movf keycode,w btfsc status,z goto get8wait ;we loop until we find the key and then we check for ystr sublw yclr btfsc status,z goto handleyclr ;ystr will synchronize everything movf keycode,w ;put the current key input into w sublw yent ;yd means the end of the entry btfsc status,z goto checkent ;if it was yd we'll handle it at checkent movf keycode,w ;check for yc sublw yrun btfsc status,z goto checkrun ;if yc, handle it at checkrun ;if we get this far we know that the key is not a special purpose key (CLR,ENT,RUN) movf keycode,w movwf indf ;indirect keycode to user elecments clrf keycode ;resets keycode to allow for next key entry incf fsr,f ;increments the interupt pointer (fsr) incf usercounter1,f ;update counter movf usercounter1,w ;moves the incremented usercounter into w sublw 9 ;9 is subtracted since their is only a max of 8 digits btfss status,z ;tests the z flag for a 1, if it is it skips next inst. goto get8wait ;if not 8 yet get next entry ;if the z flag was set then the ninth key was not a special ;purpose key so it was an error goto checkret ;return with exitkey=0 to indicate error ;------------------------------------------------------------------------- checkent movlw yent movwf exitkey goto checkret ;returns with ystr in exitkey checkrun movlw yrun movwf exitkey checkret return ;return with yc in exitkey compare8 clrf ok ;assume not ok at first movf user0,w ;look at first key entry btfsc status,z ; goto compareret ;return with error set if 0 set ;this prevents a null set from being ok movlw 1 ;set ok for now movwf ok ; movlw 8 movwf usercounter1 ;initialize counter to 8 movlw user0 movwf fsr ;allow indirect addressing compareloop movf indf,w ;recover user data bsf status,rp0 ;bank select to 1 so eecon register can be asseccesed bsf eecon1,rd ;set up read, initiates eeprom read bcf status,rp0 ;back to bank 0 subwf eedata,w ;compare with eeprom data btfss status,z ; goto compareerror ;if different then error incf eeadr,f ;addresses up to 256 bytes of eeprom data ;direct addressing incf fsr,f ;indirect addressing decfsz usercounter1,f ;update counter goto compareloop ;if not all 8 done do more goto compareret ;if all 8 matched, all done compareerror clrf ok compareret return ;------------------------------------------------------------------------- ;EEPROM ;eecon1 register in bank 1 will be used ;eeadr is used to hold the address of the desired data ;eecon1 and eecon2 are eeprom_control registers to make sure that there ; can never be an accidental write to the eeprom ;to read: load eeadr with the desired address ;clear eecon1 and the rd bit to 1, read eedata. writeeedata bsf status,rp0 ;selecting bank 1 bcf eecon1,eeif ;clear eeif(eeprom write operation interupt flag) bsf eecon1,wren ;set wren (eeprom wirte enable bit) bcf intcon,gie ;disable all interrupts movlw h'55' movwf eecon2 movlw h'aa' movwf eecon2 bsf eecon1,wr eewait btfss eecon1,eeif ;tests the eeif reg. for a 1 goto eewait ; if a 0 we loop bcf eecon1,eeif ;clears eeif bcf eecon1,wren ;disables writes bsf intcon,gie ;enable gie interrupts bcf status,rp0 ;select bank 0 return ;------------------------------------------------------------------------- ;wblinks is a subroutine that will let us enter the number of blinks for green wblinks movwf blinks ;save no. of blinks incf blinks,f ;addjust for initial decrement wblinksloop decfsz blinks,f goto blinkit ;on or off once return blinkit bcf porta,n_green ;on call xmillisecs ;delay for light on time bsf porta,n_green ;off call xmillisecs ;delay again for off time goto wblinksloop ;do more blinks ;------------------------------------------------------------------------- ;the following loops are used to waste some time for led on time (1msec) xmillisecs movlw d'200' ;delay wmillisec movwf xmillisec ;saves the no. of msec in w to delay the led incf xmillisec,f ;adjust to account for initial decrement wmloop1 ;first outer loop for the wait decfsz xmillisec,f ;decrements xmillisec, if it is a 0 it skips next instruction ;so if there is something in xmill.. we will loop more goto wmloopa return ;if it is all done then return to gotystr wmloopa clrf ymillisec ;second loop wmloopb decfsz ymillisec,f ;decrements ymillisec if zero skip next step goto wmloopb ;takes 3usec per loop movlw d'75'+1 movwf ymillisec ;75 loops for third loop wmloopc decfsz ymillisec,f ;update inner loop goto wmloopc ;another 3usec per loop goto wmloop1 ;continue with last outer loop ;total time for the loop is 3*(256+75) = 993usec = 1msec ;----------------------------------------------------------------------------------- ;************************************************************** ;* END OF PROGRAM * ;**************************************************************
Questions: