+ Reply to Thread
Page 1 of 3
1 2 3 Last
Results 1 to 15 of 35

Thread: Tough assembly program for the PIC16F84

  1. #1
    asmpic Newbie
    Join Date
    Nov 2004
    Posts
    36

    Default Tough assembly program for the PIC16F84

    I have a programming assignment that I believe to be pretty hard. I have to make a PIC microcontroller program for a Keypad Entry Access Control System. The access control system consists of a five-button keypad (1,2,3,4 and enter), an electronically controlled door lock, and a PIC microcontroller. The control logic for the system will be inside the microcontroller. So the code below is what I have as of now, but I'm having trouble coming up with two last subroutines(update_passcode and compare_pass_code).

    Update_passcode is supposed to update the code stored in location 0x20 using a specific method. The updating process simply left shifts the entered pass code by 2 bits and adds this number to the 2-bits representing the last key pressed. When the Enter key is pressed, the program does not update the entered pass code, but instead compares the entered pass code first to the supervisor’s code (0x1B). If the entered code is not the supervisor’s code then the entered pass code is compared to each entry in its list of authorized pass codes, which begins at location 0x30. I can't assume that there will be at least one authorized pass code as the authorized pass code list will be empty upon power-up.

    The inputs for the update_passcode will be:
    "last_key_pressed" stored at location 0x4F (The interrupt handling routine places the number pressed at the location 0x4F).

    It will output:
    "entered_pass_code" stored at location 0x20 - The updated pass code (in the format described above) should be placed at location 0x20.


    The second subroutine I'm having trouble with is compare_pass_code. This is supposed to compare the entered pass code, stored at location 0x20, first to the supervisor’s pass code (0x1B) and then, assuming the supervisor’s code was not entered and that num_pass_codes > 0, to each of the authorized pass codes beginning at location 0x30. If the entered pass code is the supervisor’s code, then the supervisor_mode flag output is set to 0x01. This subroutine will use this flag to recognize that the next entered pass code should be added to the authorized pass code list instead of being compared to the entries in the list.
    The inputs will be:
    "entered_pass_code" at locations 0x20 - The entered pass code is stored at location 0x20.
    "num_pass_codes" stored at location 0x21 - The number of authorized pass codes is stored at location 0x21.
    "auth_pass_codes" stored at location 0x30 - Authorized pass codes are stored beginning at location 0x30.
    "supervisor_mode" stored at location 0x42 - Your compare_pass_code subroutine may use the value of location 0x42 to determine if the entered pass code should be added to the authorized pass code list.

    Outputs:
    "success" stored at location 0x40 - A one (0x01) should be stored at location 0x40 if the entered pass code is found in the list of authorized pass codes. Otherwise the location 0x40 should be cleared.
    "supervisor_mode" stored at location 0x42 - A one (0x01) should be stored in location 0x42 if the entered pass code equals the supervisors pass code (0x1B).



    Again, I think this program is extremely hard so I understand if you guys don't understand how to do this. Let me know if you need any more information. I appreciate all the help anyone gives me.

    Code:
    	list P=16F84
    	include	P16F84.INC
    
    ; Define the direction bit types
    f		equ	1
    w		equ	0
    
    ; Define the data storage locations
    ; These locations must NOT be modified!
    entered_pass_code	equ 0x20	; the entered passcode - last four keys pressed
    num_pass_codes		equ 0x21	; the number of passcodes stored
    success				equ 0x40	; grant or deny access
    history			 	equ 0x41	; history of passcodes entered
    supervisor_mode		equ 0x42	; supervisor code entered -> adding new pass code to list
    status_temp			equ 0x4A	; temp storage of STATUS reg during subroutines
    w_temp				equ	0x4B	; temp storage of W during subroutines
    last_key_press		equ 0x4F	; last key pressed
    
    			org	0x30
    passcodes			res	16	; location of the passcodes
    
    ; Define the control code for adding new users
    control_code		equ 0x1B
    
    ; start defining the program
    ; interrupts, so start at 0x30
    	org	0x00
    		goto start
    ; Interrupt Service Routine
    	org 0x04
    		movwf w_temp 		; store the value of W
    		movf STATUS, w
    		movwf status_temp 	; store the STATUS register
    		movf PORTA, w 		; get the key pressed
    		movwf last_key_press; move the captured key press to reg
    		bcf INTCON, INTF	; clear interrupt flag
    		movf status_temp, w	; restore the status register's value
    		movwf STATUS	
    		movf w_temp, w		; restore the W register's value
    		retfie
    
    ; Success or Failure Subroutine
    grant_deny
    		movwf w_temp 		; store the value of W
    		movf STATUS, w
    		movwf status_temp 	; store the STATUS register
    		btfss success, 0
    		goto update_history
    open_door
    		movlw 0x8			; send open door signal -> RA3
    		movwf PORTA
    		movlw 0x0
    		movwf PORTA
    update_history
    		bcf STATUS, 0		; clear the carry bit to allow for shift thru carry
    		rlf history, f
    		movf success, w
    		addwf history, f
    		clrf entered_pass_code	; clear last attempt's pass code
    		clrf success			; clear success flag
    		movf status_temp, w		; restore the STATUS register
    		movwf STATUS
    		movf w_temp, w			; restore the W register
    		return
    
    ; Sleep subroutine
    sleep_now
    		sleep
    		; nop needed after sleep command for correct interrupt handling
    		nop	
    		return
    
    ; start main program
    	org 0x30
    start
    		; Set-up Interrupt on RB0
    		bsf INTCON, GIE			; enable global interrupts
    		bsf INTCON, INTE		; enable RB0 interrupts
    		; Set-up Inputs
    		bsf STATUS, RP0		; select bank 1
    		movlw 0x07			; configure first 3 bits as inputs
    		; The following instruction generates a MESSAGE[302] warning from MPLAB - this is expected.
    		movwf TRISA 		; load configuration into RA port
    		bcf STATUS, RP0		; select bank 0
    		clrf history		; zero out history of successes
    		clrf PORTA			; clear the output on PORTA
    		clrf num_pass_codes	; start out with an empty authorized pass codes list
    		clrf supervisor_mode
    
    ; This is the main program loop that calls your subroutines.
    endless_loop
    		call sleep_now
    		btfsc last_key_press, 2	; test for Enter press
    		goto enter_pressed
    		call update_pass_code	; update the entered pass code if Enter not pressed
    		goto endless_loop
    enter_pressed
    		call compare_pass_code
    		goto endless_loop
    
    update_passcode
    
    
    
    
    compare_pass_code
    
    	end
    


  2. #2
    asmpic Newbie
    Join Date
    Nov 2004
    Posts
    36

    Default

    wow, no one can help?

  3. #3
    williB Good williB Good
    Join Date
    Aug 2004
    Location
    New Jersey
    Posts
    2,226

    Default

    its tough getting through your Novel..
    got an abridged version?? lol

  4. #4
    williB Good williB Good
    Join Date
    Aug 2004
    Location
    New Jersey
    Posts
    2,226

    Default

    Questions usually end with a question mark .....?
    i have read it twice and still do not see a question..?
    but it is late , and maybe i am just missing it..

  5. #5
    motion Newbie
    Join Date
    Jul 2003
    Location
    Quezon City.PH
    Posts
    560

    Default

    Quote Originally Posted by asmpic
    wow, no one can help?
    Just 8 hrs after you first posted, you start whining this! It's Sunday morning where I am at now. I sure would like to help but I think I would pass on this one bro.
    "Having to do with Motion Control"

  6. #6
    asmpic Newbie
    Join Date
    Nov 2004
    Posts
    36

    Default

    Quote Originally Posted by motion
    Quote Originally Posted by asmpic
    wow, no one can help?
    Just 8 hrs after you first posted, you start whining this! It's Sunday morning where I am at now. I sure would like to help but I think I would pass on this one bro.
    Sorry about that, but usually when a new topic is posted, people on this board reply pretty quickly. So, I didn't know if my topic was just confusing or what.

  7. #7
    asmpic Newbie
    Join Date
    Nov 2004
    Posts
    36

    Default

    Quote Originally Posted by williB
    Questions usually end with a question mark .....?
    i have read it twice and still do not see a question..?
    but it is late , and maybe i am just missing it..
    I don't have an exact question, I just need help coming up with two subroutines, update_passcode and compare_pass_code. And sorry about it being so long, I didnt know any other way of explaining it clearly.

  8. #8
    asmpic Newbie
    Join Date
    Nov 2004
    Posts
    36

    Default

    No one has any advice? Please, I need some help.

  9. #9
    williB Good williB Good
    Join Date
    Aug 2004
    Location
    New Jersey
    Posts
    2,226

    Default

    somone on here recomended to somone else to create modules for large projects..
    i think that breaking this down into smaller parts might help..ie a new program with just the parts that you are working on at the moment..

  10. #10
    JohnBrown Newbie
    Join Date
    Apr 2004
    Location
    Surrey, England
    Posts
    141

    Default

    One thing I noticed, I think your interrupt service routine trashes the status flags. Take a look at the section on context saving during interrupts. It's in the freely available datasheet. You need to use a SWAPF instruction, as this allows you to restore W at the end of the ISR without affecting the Z flag.

  11. #11
    motion Newbie
    Join Date
    Jul 2003
    Location
    Quezon City.PH
    Posts
    560

    Default

    I have several issues with your code so I don't think it will work as smoothly as predicted. Anyway as I understand it, here is some code to start the discussion:

    Code:
    update_passcode:
        movf   supervisor_mode,w
        btfsc  status.Z               ; Check if supervisor mode
        goto   change_user_passcode 
     
        bcf    status,C
        rlf    entered_pass_code,f  
        bcf    status,C
        rlf    entered_pass_code,f
    ;
        movlw  b'00000011'
        andwf  last_key_press,w       ; mask out upper bits
        addwf  entered_pass_code,f    ; add to entered pass code
    ;
        return
    change_user_passcode:
        movf   num_pass_codes,w
        andlw  b'00001111'
        addlw  passcodes
        movwf  fsr
    ;
        movf   entered_pass_code,w
        movwf  indf
    ;
        incf   num_pass_codes,f
        clrf   supervisor_mode
    ;
        return
    
    compare_pass_code:
        movlw  supervisor_code
        xorwf  entered_pass_code,w  ; compare to supervisor code
        movlw  0 
        btfsc  status,Z
        movlw  1
        movwf  supervisor_mode 
    ;
    ; additonal code here to copare with user pass codes
    ;       
        return
    
    "Having to do with Motion Control"

  12. #12
    phalanx Newbie
    Join Date
    Oct 2003
    Location
    New Hampshire, USA
    Posts
    321

    Default

    There are a couple of things you will have to do but nothing that is too hard. I won't give you complete code but I'll give you enough to get you going in the right direction.

    When scanning in button presses, you will have to make sure your program halts until you release the button you are pressing. If you do not, you will your pass code with entirely one button. To read in the code you want the flow to look like this:

    Check button press using btfss or btfsc

    if pressed call a 5ms delay for debouncing purposes
    if not pressed, goto next button check

    after 5ms delay btfss or btfsc the same pin and read the value
    if still pressed, button is valid - shift the value into a variable
    if not pressed, return to scanning routine

    (after shifting in variable)
    btfss or btfsc the same button
    if still pressed, keep checking until not pressed
    if not pressed, return to your keypad scan routine


    In terms of comparing your inputted combination to the stored one, the way to check it will depend on whether your combo is stored as a single byte or a byte for each digit. Either way, subtract the inputted value from the stored value and check the Zero flag. If the flag is set, the values are the same. If the flag is cleared, the values are different and you can branch accordingly in your program

    Hope that helps somewhat.

    -Bill

  13. #13
    asmpic Newbie
    Join Date
    Nov 2004
    Posts
    36

    Default

    Quote Originally Posted by motion
    I have several issues with your code so I don't think it will work as smoothly as predicted. Anyway as I understand it, here is some code to start the discussion:

    Code:
    update_passcode:
        movf   supervisor_mode,w
        btfsc  status.Z               ; Check if supervisor mode
        goto   change_user_passcode 
     
        bcf    status,C
        rlf    entered_pass_code,f  
        bcf    status,C
        rlf    entered_pass_code,f
    ;
        movlw  b'00000011'
        andwf  last_key_press,w       ; mask out upper bits
        addwf  entered_pass_code,f    ; add to entered pass code
    ;
        return
    change_user_passcode:
        movf   num_pass_codes,w
        andlw  b'00001111'
        addlw  passcodes
        movwf  fsr
    ;
        movf   entered_pass_code,w
        movwf  indf
    ;
        incf   num_pass_codes,f
        clrf   supervisor_mode
    ;
        return
    
    compare_pass_code:
        movlw  supervisor_code
        xorwf  entered_pass_code,w  ; compare to supervisor code
        movlw  0 
        btfsc  status,Z
        movlw  1
        movwf  supervisor_mode 
    ;
    ; additonal code here to copare with user pass codes
    ;       
        return
    

    Thanks for the code! I understand how you compared the entered code with the supervisor code but how exactly would you compare the entered code with all the different user passcodes? Would you setup another FSR and INDF type thing? ...I'm sorry if I'm asking so much, I know this must be a joke of a problem but I'm totally new as far as assembly programming goes, it's been two weeks since I've started learning this.

  14. #14
    JohnBrown Newbie
    Join Date
    Apr 2004
    Location
    Surrey, England
    Posts
    141

    Default

    I mentioned before that you Interrupt Service Routine (ISR) is trashing the status bits. You do not seem to have taken any notice. Here is an extract from the datasheet for the 16F87X, it applies equally to the 16F84.


    EXAMPLE 12-1: SAVING STATUS, W, AND PCLATH REGISTERS IN RAM
    MOVWF W_TEMP ;Copy W to TEMP register
    SWAPF STATUS,W ;Swap status to be saved into W
    CLRF STATUS ;bank 0, regardless of current bank, Clears IRP,RP1,RP0
    MOVWF STATUS_TEMP ;Save status to bank zero STATUS_TEMP register
    MOVF PCLATH, W ;Only required if using pages 1, 2 and/or 3
    MOVWF PCLATH_TEMP ;Save PCLATH into W
    CLRF PCLATH ;Page zero, regardless of current page
    :
    ISR) ;(Insert user code here)
    :
    MOVF PCLATH_TEMP, W ;Restore PCLATH
    MOVWF PCLATH ;Move W into PCLATH
    SWAPF STATUS_TEMP,W ;Swap STATUS_TEMP register into W
    ;(sets bank to original state)
    MOVWF STATUS ;Move W into STATUS register
    SWAPF W_TEMP,F ;Swap W_TEMP
    SWAPF W_TEMP,W ;Swap W_TEMP into W

    It may be that your main loop is currently so trivial that trashing the status flags isn't a problem. One day it will be, and it will drive you crazy trying to debug your program. Ignore this advice at your peril.

  15. #15
    asmpic Newbie
    Join Date
    Nov 2004
    Posts
    36

    Default

    Quote Originally Posted by JohnBrown
    I mentioned before that you Interrupt Service Routine (ISR) is trashing the status bits. You do not seem to have taken any notice. Here is an extract from the datasheet for the 16F87X, it applies equally to the 16F84.


    EXAMPLE 12-1: SAVING STATUS, W, AND PCLATH REGISTERS IN RAM
    MOVWF W_TEMP ;Copy W to TEMP register
    SWAPF STATUS,W ;Swap status to be saved into W
    CLRF STATUS ;bank 0, regardless of current bank, Clears IRP,RP1,RP0
    MOVWF STATUS_TEMP ;Save status to bank zero STATUS_TEMP register
    MOVF PCLATH, W ;Only required if using pages 1, 2 and/or 3
    MOVWF PCLATH_TEMP ;Save PCLATH into W
    CLRF PCLATH ;Page zero, regardless of current page
    :
    ISR) ;(Insert user code here)
    :
    MOVF PCLATH_TEMP, W ;Restore PCLATH
    MOVWF PCLATH ;Move W into PCLATH
    SWAPF STATUS_TEMP,W ;Swap STATUS_TEMP register into W
    ;(sets bank to original state)
    MOVWF STATUS ;Move W into STATUS register
    SWAPF W_TEMP,F ;Swap W_TEMP
    SWAPF W_TEMP,W ;Swap W_TEMP into W

    It may be that your main loop is currently so trivial that trashing the status flags isn't a problem. One day it will be, and it will drive you crazy trying to debug your program. Ignore this advice at your peril.
    I understand what you are saying and the only reason I haven't really said anything about it is because my professor told us to do the ISR that particular way. I dont know why, but I suppose like you said it might not be much of a problem for now.

+ Reply to Thread
Page 1 of 3
1 2 3 Last

Tags for this Thread