![]() | ![]() | ![]() |
| | |||||||
| Micro Controllers Discuss all aspects of micro controllers - building them, coding them, etc. All controllers are welcome - PIC, BASIC, Z8 Encore!, etc. |
| | Thread Tools | Display Modes |
| | (permalink) |
| Experienced Member | 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 |
| | |
| | (permalink) |
| Experienced Member | wow, no one can help? |
| | |
| | (permalink) |
| Experienced Member | its tough getting through your Novel.. got an abridged version?? lol |
| | |
| | (permalink) |
| Experienced Member | 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.. |
| | |
| | (permalink) | |
| Experienced Member | Quote:
__________________ "Having to do with Motion Control" | |
| | |
| | (permalink) | ||
| Experienced Member | Quote:
| ||
| | |
| | (permalink) | |
| Experienced Member | Quote:
| |
| | |
| | (permalink) |
| Experienced Member | No one has any advice? Please, I need some help. |
| | |
| | (permalink) |
| Experienced Member | 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.. |
| | |
| | (permalink) |
| Experienced Member | 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. |
| | |
| | (permalink) |
| Experienced Member | 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" |
| | |
| | (permalink) |
| Experienced Member | 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 |
| | |
| | (permalink) | |
| Experienced Member | Quote:
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. | |
| | |
| | (permalink) |
| Experienced Member | 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 : : 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. |
| | |
| | (permalink) | |
| Experienced Member | Quote:
| |
| | |