I have two questions about 16c84 1) I set the protection code in 16c84, can I reprogram it? 2) I use AN557 Section 2 Keypad code to scanning a keypad, I find sometimes press key '4' or 'c' will cause it auto set four 7 segment LED display to '0000'. Key '0' or '8' have NOT this problem.(AN557 use 16c71 as microcontroller) Is it a hardware or software problem? Thanks for any assistance. Mei Jie The Code Listing ;********************************************************************* ;This program is to demonstrate how to multiplex four 7 segment LED ;digits and a 4X4 keypad using a PIC16C71. ;The four digits will start as '0000' and when a key is hit ;it is displayed on the 7 segment leds as a hex value 0 to F. The last ;digit hit is always displayed on the right most led with the rest of ;the digits shifted to the left. The left most digit is deleted. ;The LEDs are updated every 20mS, the keypad is scanned at a rate of 20 mS. ;The RTCC timer is used in internal interrupt mode to generate the ;5 mS. ; ; Stan D'Souza 5/8/93 ;********************************************************************** LIST P=16C71, F=INHX8M ; include "picreg.equ" ; TempC equ 0x0c ;temp general purpose regs TempD equ 0x0d TempE equ 0x0e PABuf equ 0x20 PBBuf equ 0x21 Count equ 0x0f ;count MsdTime equ 0x10 ;most significant Timer LsdTime equ 0x11 ;Least significant Timer KeyFlag equ 0x12 ;flags related to key pad keyhit equ 0 ;bit 0 --> key-press on DebnceOn equ 1 ;bit 1 --> debounce on noentry equ 2 ;no key entry = 0 ServKey equ 3 ;bit 3 --> service key Debnce equ 0x13 ;debounce counter NewKey equ 0x14 WBuffer equ 0x2f StatBuffer equ 0x2e OptionReg equ 1 PCL equ 2 ; ; push macro movwf WBuffer ;save w reg in Buffer swapf WBuffer ;swap it swapf STATUS,w ;get status movwf StatBuffer ;save it endm ; pop macro swapf StatBuffer,w ;restore status movwf STATUS ; / swapf WBuffer,w ;restore W reg endm ; org 0 goto Start ;skip over interrupt vector ; org 4 ;It is always a good practice to save and restore the w reg, ;and the status reg during a interrupt. push call ServiceInterrupts pop retfie ; Start call InitPorts call InitTimers loop btfsc KeyFlag,ServKey ;key service pending call ServiceKey ;yes then service goto loop ; ;ServiceKey, does the software service for a keyhit. After a key service, ;the ServKey flag is reset, to denote a completed operation. ServiceKey movf NewKey,w ;get key value movwf TempE ;save in TempE swapf MsdTime,w ;move MSD out andlw B'11110000' ;clr lo nibble movwf MsdTime ;save back swapf LsdTime,w ;get Lsd andlw B'00001111' ;mask off lsd iorwf MsdTime ;and left shift 3rd swapf LsdTime,w ;get Lsd again andlw B'11110000' ;mask off 2nd iorwf TempE,w ;or with new lsd movwf LsdTime ;make Lsd bcf KeyFlag,ServKey ;reset service flag return ; InitPorts bsf STATUS,RP0 ;select pg 1 movlw 3 ;make RA0-3 digital I/O movwf ADCON1 ; / clrf TRISA ;make RA0-4 outputs clrf TRISB ;make RB0-7 outputs bcf STATUS,RP0 ;select page 0 clrf PORT_A ;make all outputs low clrf PORT_B ; / bsf PORT_A,3 ;enable MSB digit sink return ; ; ;The clock speed is 4.096Mhz. Dividing internal clk. by a 32 prescaler, ;the rtcc will be incremented every 31.25uS. If rtcc is preloaded ;with 96, it will take (256-96)*31.25uS to overflow i.e. 5mS. So the ;end result is that we get a rtcc interrupt every 5mS. InitTimers clrf MsdTime ;clr timers clrf LsdTime ; / clrf KeyFlag ;clr all flags bsf STATUS,RP0 ;select pg 1 movlw B'10000100' ;assign ps to rtcc movwf OptionReg ;ps = 32 bcf STATUS,RP0 ;select pg 0 movlw B'00100000' ;enable rtcc interrupt movwf INTCON ; movlw .96 ;preload rtcc movwf RTCC ;start counter retfie ; ServiceInterrupts btfsc INTCON,RTIF ;rtcc interrupt? goto ServiceRTCC ;yes then service clrf INTCON ;else clr all int bsf INTCON,RTIE return ; ServiceRTCC movlw .96 ;initialize rtcc movwf RTCC bcf INTCON,RTIF ;clr int flag btfsc PORT_A,0 ;if msb on then do call ScanKeys ;do a quick key scan call UpdateDisplay ;update display return ; ; ;ScanKeys, scans the 4X4 keypad matrix and returns a key value in ;NewKey (0 - F) if a key is pressed, if not it clears the keyhit flag. ;Debounce for a given keyhit is also taken care of. ;The rate of key scan is 20mS with a 4.096Mhz clock. ScanKeys btfss KeyFlag,DebnceOn ;debounce on? goto Scan1 ;no then scan keypad decfsz Debnce ;else dec debounce time return ;not over then return bcf KeyFlag,DebnceOn ;over, clr debounce flag return ;and return Scan1 call SavePorts ;save port values movlw B'11101111' ;init TempD movwf TempD ScanNext movf PORT_B,w ;read to init port bcf INTCON,RBIF ;clr flag rrf TempD ;get correct column btfss STATUS,C ;if carry set? goto NoKey ;no then end movf TempD,w ;else output movwf PORT_B ;low column scan line nop btfss INTCON,RBIF ;flag set? goto ScanNext ;no then next btfsc KeyFlag,keyhit ;last key released? goto SKreturn ;no then exit bsf KeyFlag,keyhit ;set new key hit swapf PORT_B,w ;read port movwf TempE ;save in TempE call GetKeyValue ;get key value 0 - F movwf NewKey ;save as New key bsf KeyFlag,ServKey ;set service flag bsf KeyFlag,DebnceOn ;set flag movlw 4 movwf Debnce ;load debounce time SKreturn call RestorePorts ;restore ports return ; NoKey bcf KeyFlag,keyhit ;clr flag goto SKreturn ; ;GetKeyValue gets the key as per the following layout ; ; Col1 Col2 Col3 Col3 ; (RB3) (RB2) (RB1) (RB0) ; ;Row1(RB4) 0 1 2 3 ; ;Row2(RB5) 4 5 6 7 ; ;Row3(RB6) 8 9 A B ; ;Row4(RB7) C D E F ; GetKeyValue clrf TempC btfss TempD,3 ;first column goto RowValEnd incf TempC btfss TempD,2 ;second col. goto RowValEnd incf TempC btfss TempD,1 ;3rd col. goto RowValEnd incf TempC ;last col. RowValEnd btfss TempE,0 ;top row? goto GetValCom ;yes then get 0,1,2&3 btfss TempE,1 ;2nd row? goto Get4567 ;yes the get 4,5,6&7 btfss TempE,2 ;3rd row? goto Get89ab ;yes then get 8,9,a&b Getcdef bsf TempC,2 ;set msb bits Get89ab bsf TempC,3 ; / goto GetValCom ;do common part Get4567 bsf TempC,2 GetValCom movf TempC,w addwf PCL retlw 0 retlw 1 retlw 2 retlw 3 retlw 4 retlw 5 retlw 6 retlw 7 retlw 8 retlw 9 retlw 0a retlw 0b retlw 0c retlw 0d retlw 0e retlw 0f ; ;SavePorts, saves the porta and portb condition during a key scan ;operation. SavePorts movf PORT_A,w ;Get sink value movwf PABuf ;save in buffer clrf PORT_A ;disable all sinks movf PORT_B,w ;get port b movwf PBBuf ;save in buffer movlw 0xff ;make all high movwf PORT_B ;on port b bsf STATUS,RP0 ;select page 1 bcf OptionReg,7 ;enable pull ups movlw B'11110000' ;port b hi nibble inputs movwf TRISB ;lo nibble outputs bcf STATUS,RP0 ;page 0 return ; ;RestorePorts, restores the condition of porta and portb after a ;key scan operation. RestorePorts movf PBBuf,w ;get port n movwf PORT_B movf PABuf,w ;get port a value movwf PORT_A bsf STATUS,RP0 ;select page 1 bsf OptionReg,7 ;disable pull ups clrf TRISA ;make port a outputs clrf TRISB ;as well as PORTB bcf STATUS,RP0 ;page 0 return ; ; UpdateDisplay movf PORT_A,w ;present sink value in w clrf PORT_A ;disable all digits sinks andlw 0x0f movwf TempC ;save sink value in tempC bsf TempC,4 ;preset for lsd sink rrf TempC ;determine next sink value btfss STATUS,CARRY ;c=1? bcf TempC,3 ;no then reset LSD sink btfsc TempC,0 ;else see if Msd goto UpdateMsd ;yes then do Msd btfsc TempC,1 ;see if 3rdLsd goto Update3rdLsd ;yes then do 3rd Lsd btfsc TempC,2 ;see if 2nd Lsd goto Update2ndLsd ;yes then do 2nd lsd UpdateLsd movf LsdTime,w ;get Lsd in w andlw 0x0f ; / goto DisplayOut Update2ndLsd swapf LsdTime,w ;get 2nd Lsd in w andlw 0x0f ;mask rest goto DisplayOut ;enable display Update3rdLsd movf MsdTime,w ;get 3rd Lsd in w andlw 0x0f ;mask low nibble goto DisplayOut ;enable display UpdateMsd swapf MsdTime,w ;get Msd in w andlw 0x0f ;mask rest DisplayOut call LedTable ;get digit output movwf PORT_B ;drive leds movf TempC,w ;get sink value in w movwf PORT_A return ; ; LedTable addwf PCL ;add to PC low retlw B'00111111' ;led drive for 0 retlw B'00000110' ;led drive for 1 retlw B'01011011' ;led drive for 2 retlw B'01001111' ;led drive for 3 retlw B'01100110' ;led drive for 4 retlw B'01101101' ;led drive for 5 retlw B'01111101' ;led drive for 6 retlw B'00000111' ;led drive for 7 retlw B'01111111' ;led drive for 8 retlw B'01100111' ;led drive for 9 retlw B'01110111' ;led drive for A retlw B'01111100' ;led drive for b retlw B'00111001' ;led drive for C retlw B'01011110' ;led drive for d retlw B'01111001' ;led drive for E retlw B'01110001' ;led drive for F ; ; end ;