How to jump back to an original state? - PIC programming

Discussion in 'Embedded Systems and Microcontrollers' started by draeberg, May 4, 2008.

  1. draeberg

    Thread Starter New Member

    Apr 24, 2008
    7
    0
    I have made a well functioning electronic combination lock, with a lot of help from Nigel's page: http://www.winpicprog.co.uk/. Well, the thing is, that I made it work perfectly until one thing, that seems to annoy me.

    To simulate an unlock/lock stage I "make" the PIC jump from one place in the code to another place.

    What happens is that when you start the PIC, it will start up with a text displaying that says "Enter Code" in english (I know it is not what says in the text, but it is in Danish). I enter the code and it works all well. Then I make it jump and it says "Locked: Enter code". You will therefore have to enter the code once again to unlock (or the right word should be jump) the pic and it should jump back and display "Enter code". It all works well, except that when it says "Locked...." you have to enter any 4 bit code, but the right code to unlock it, and if you enter the right code it keeps on jumping back. So you see it works quite well, except that it should work the other round, so when you enter the wrong code it keeps on looping and says "Locked: Enter code" and when the right code is entered it will jump And say "Enter code:"....

    I make it jump by writing:
    Code ( (Unknown Language)):
    1. Correct_Wait call Delay255
    2.   call Delay255
    3.   call Delay255
    4.   call Delay255
    5.   goto Init2
    Where init2 is the locked stage, it is actually an exact copy of the init, and does the same thing. Except that when wrong code is entered it should jump back to init2 and when correct it should jump to init.

    Why does it not work?
    Where did I go wrong?
    You can see what I have done in the code given below:

    Code ( (Unknown Language)):
    1.  
    2.  LIST p=16F628  ;Her fortælles til assembler hvilken chip der bruges
    3.  include "P16F628.inc" ;Her defineres hvad der skal inkluderes til chippen
    4.         ;hvilket er nogle standarder som programmet kan gå ud fra
    5.         ;når chippen skal programmeres
    6.  ERRORLEVEL 0, -302 ;suppress bank selection messages
    7.  __config 0x3D18
    8.  
    9.   cblock 0x20   ;start of general purpose registers
    10.    count   ;used in looping routines
    11.    count1   ;used in delay routine
    12.    counta   ;used in delay routine
    13.    countb   ;used in delay routine
    14.    tmp1   ;temporary storage
    15.    tmp2
    16.    templcd   ;temp store for 4 bit mode
    17.    templcd2
    18.    key   ;which key was pressed
    19.    rows   ;counter for number of rows
    20.    code1   ;registers for secret code
    21.    code2
    22.    code3
    23.    code4
    24.    key1   ;registers for keyed attempts
    25.    key2
    26.    key3
    27.    key4
    28.   endc
    29. LCD_PORT Equ PORTA
    30. LCD_TRIS Equ TRISA
    31. LCD_RS  Equ 0x04   ;LCD handshake lines
    32. LCD_RW  Equ 0x06
    33. LCD_E  Equ 0x07
    34. KEY_PORT Equ PORTB   ;keypad port
    35. KEY_TRIS Equ TRISB
    36. Col1  Equ 0   ;pins used for keypad inputs
    37. Col2  Equ 1
    38. Col3  Equ 2
    39. Col4  Equ 3
    40.   org 0x0000
    41.   goto Start
    42. Key_Table   ADDWF   PCL       , f ;translation table for keypad
    43.              RETLW   0x31 ;1
    44.              RETLW   0x34 ;4
    45.              RETLW   0x37 ;7
    46.              RETLW   0x2a ;*
    47.              RETLW   0x32 ;2
    48.              RETLW   0x35 ;5
    49.              RETLW   0x38 ;8
    50.              RETLW   0x30 ;0
    51.              RETLW   0x33 ;3
    52.              RETLW   0x36 ;6
    53.              RETLW   0x39 ;9
    54.              RETLW   0x23 ;#
    55.              RETLW   0x43 ;C
    56.              RETLW   0x44 ;D
    57.              RETLW   0x45 ;E
    58.              RETLW   0x46 ;F
    59.  
    60. HEX_Table   ADDWF   PCL       , f  ;hex table for LCD routines
    61.              RETLW   0x30
    62.              RETLW   0x31
    63.              RETLW   0x32
    64.              RETLW   0x33
    65.              RETLW   0x34
    66.              RETLW   0x35
    67.              RETLW   0x36
    68.              RETLW   0x37
    69.              RETLW   0x38
    70.              RETLW   0x39
    71.              RETLW   0x41
    72.              RETLW   0x42
    73.              RETLW   0x43
    74.              RETLW   0x44
    75.              RETLW   0x45
    76.              RETLW   0x46
    77.  
    78. Text  addwf PCL, f
    79.   retlw 'S'
    80.   retlw 'k'
    81.   retlw 'r'
    82.   retlw 'i'
    83.   retlw 'v'
    84.   retlw ' '
    85.   retlw 'k'
    86.   retlw 'o'
    87.   retlw 'd'
    88.   retlw 'e'
    89.   retlw ':'
    90.   retlw 0x00
    91. Text2  addwf PCL, f
    92.   retlw 'L'
    93.   retlw 'a'
    94.   retlw 'a'
    95.   retlw 's'
    96.   retlw 't'
    97.   retlw ':'
    98.   retlw ' '
    99.   retlw 'S'
    100.   retlw 'k'
    101.   retlw 'r'
    102.   retlw 'i'
    103.   retlw 'v'
    104.   retlw 0x00
    105. Wrong_Text addwf PCL, f
    106.   retlw 'F'
    107.   retlw 'o'
    108.   retlw 'r'
    109.   retlw 'k'
    110.   retlw 'e'
    111.   retlw 'r'
    112.   retlw 't'
    113.   retlw ' '
    114.   retlw 'k'
    115.   retlw 'o'
    116.   retlw 'd'
    117.   retlw 'e'
    118.   retlw 0x00
    119. Correct_Text addwf PCL, f
    120.   retlw 'K'
    121.   retlw 'o'
    122.   retlw 'r'
    123.   retlw 'r'
    124.   retlw 'e'
    125.   retlw 'k'
    126.   retlw 't'
    127.   retlw ' '
    128.   retlw 'k'
    129.   retlw 'o'
    130.   retlw 'd'
    131.   retlw 'e'
    132.   retlw 0x00
    133. Start  movlw 0x07
    134.   movwf CMCON   ;turn comparators off (make it like a 16F84)
    135. Initialise movlw '0'   ;set 4 digit secret code
    136.   movwf code1
    137.   movlw '0'
    138.   movwf code2
    139.   movlw '0'
    140.   movwf code3
    141.   movlw '0'
    142.   movwf code4
    143.  
    144. SetPorts bsf  STATUS,  RP0 ;select bank 1
    145.   movlw 0x00   ;make all pins outputs
    146.   movwf LCD_TRIS
    147.   movlw 0x0F   ;set keypad pins
    148.   movwf KEY_TRIS  ;half in, half out
    149.   movwf TRISB
    150.   bcf  STATUS,  RP0 ;select bank 0
    151. Init  call LCD_Init  ;setup LCD
    152.  
    153.   clrf count   ;set counter register to zero
    154. Message  movf count, w  ;put counter value in W
    155.   call Text   ;get a character from the text table
    156.   xorlw 0x00   ;is it a zero?
    157.   btfsc STATUS, Z
    158.   goto Main
    159.   call LCD_Char
    160.   incf count, f
    161.   goto Message
    162. Wrong  call LCD_Clr
    163.   clrf count   ;set counter register to zero
    164. Message1 movf count, w  ;put counter value in W
    165.   call Wrong_Text  ;get a character from the text table
    166.   xorlw 0x00   ;is it a zero?
    167.   btfsc STATUS, Z
    168.   goto Wrong_Wait
    169.   call LCD_Char
    170.   incf count, f
    171.   goto Message1
    172. Wrong_Wait call Delay255
    173.   call Delay255
    174.   call Delay255
    175.   call Delay255
    176.   goto Init
    177. Correct  call LCD_Clr
    178.   clrf count   ;set counter register to zero
    179. Message2 movf count, w  ;put counter value in W
    180.   call Correct_Text  ;get a character from the text table
    181.   xorlw 0x00   ;is it a zero?
    182.   btfsc STATUS, Z
    183.   goto Correct_Wait
    184.   call LCD_Char
    185.   incf count, f
    186.   goto Message2
    187. Correct_Wait call Delay255
    188.   call Delay255
    189.   call Delay255
    190.   call Delay255
    191.   goto Init2
    192. Init2  call LCD_Init  ;setup LCD
    193.  
    194.   clrf count   ;set counter register to zero
    195. Messagelaas movf count, w  ;put counter value in W
    196.   call Text2   ;get a character from the text table
    197.   xorlw 0x00   ;is it a zero?
    198.   btfsc STATUS, Z
    199.   goto Main
    200.   call LCD_Char
    201.   incf count, f
    202.   goto Messagelaas
    203. Wrong2  call LCD_Clr
    204.   clrf count   ;set counter register to zero
    205. Messagelaas1 movf count, w  ;put counter value in W
    206.   call Wrong_Text  ;get a character from the text table
    207.   xorlw 0x00   ;is it a zero?
    208.   btfsc STATUS, Z
    209.   goto Wrong_Wait2
    210.   call LCD_Char
    211.   incf count, f
    212.   goto Messagelaas1
    213. Wrong_Wait2 call Delay255
    214.   call Delay255
    215.   call Delay255
    216.   call Delay255
    217.   goto Init
    218. Correct2 call LCD_Clr
    219.   clrf count   ;set counter register to zero
    220. Messagelaas2 movf count, w  ;put counter value in W
    221.   call Correct_Text  ;get a character from the text table
    222.   xorlw 0x00   ;is it a zero?
    223.   btfsc STATUS, Z
    224.   goto Correct_Wait2
    225.   call LCD_Char
    226.   incf count, f
    227.   goto Messagelaas2
    228. Correct_Wait2 call Delay255
    229.   call Delay255
    230.   call Delay255
    231.   call Delay255
    232.   goto Init2
    233. Main  movlw d'1'
    234.   call LCD_Line2W  ;move to 2nd row, 2nd column
    235.   call LCD_CurOn
    236.   call Chk_Keys  ;wait for key
    237.   movwf key1   ;store first digit
    238.   call LCD_Char
    239.   call Chk_Keys  ;wait for key
    240.   movwf key2   ;store second digit
    241.   call LCD_Char
    242.   call Chk_Keys  ;wait for key
    243.   movwf key3   ;store third digit
    244.   call LCD_Char
    245.   call Chk_Keys  ;wait for key
    246.   movwf key4   ;store fourth digit
    247.   call LCD_Char
    248.   call LCD_CurOff
    249.  
    250. Chk_Code movf code1, w  ;test first digit
    251.   subwf key1, w
    252.   btfss STATUS, Z
    253.   goto Wrong
    254.   movf code2, w  ;test second digit
    255.   subwf key2, w
    256.   btfss STATUS, Z
    257.   goto Wrong
    258.   movf code3, w  ;test third digit
    259.   subwf key3, w
    260.   btfss STATUS, Z
    261.   goto Wrong
    262.   movf code4, w  ;test fourth digit
    263.   subwf key4, w
    264.   btfss STATUS, Z
    265.   goto Wrong
    266.   goto Correct
    267.  
     
  2. Caveman

    Active Member

    Apr 15, 2008
    471
    0
    If I read this right, you are just absolutely going from init to init2. This isn't right. The way your state machine should work is like this:
    2 states: LOCKED and UNLOCKED.
    If code is wrong, state stays the same.
    If code is right, state toggles.

    Here's the pseudocode:
    Code ( (Unknown Language)):
    1.  
    2. Start:
    3.   Initialize STATE = UNLOCKED.
    4. RunLoop:
    5.   if STATE = LOCKED
    6.       Print "Locked: Enter code"
    7.   else
    8.       Print "Unlocked: Enter code"
    9.   Get Code Entry
    10.   If entry is correct
    11.       Print "Correct"
    12.       Toggle State
    13.   Else entry is incorrect
    14.       Print "Wrong"
    15.   Delay so statement can be read.
    16.   Goto RunLoop
    Once you understand the pseudocode, then you can flesh it out with the details.
     
  3. draeberg

    Thread Starter New Member

    Apr 24, 2008
    7
    0
    Well, I see your point. But I have no clue about how to do it, with use of pseudocode.
     
  4. Papabravo

    Expert

    Feb 24, 2006
    10,136
    1,786
    You have to "translate" the pseudocode into actual code. I should think that this would be self evident.

    Res ipsa loquitur
     
  5. Caveman

    Active Member

    Apr 15, 2008
    471
    0
    Which step do you not understand how to translate to assembly? You already have coded almost all of the steps.
     
  6. draeberg

    Thread Starter New Member

    Apr 24, 2008
    7
    0
    Well, I do not now know how to write the beginning of the runloop.
    I already wrote some of the code...?

    As shown below, I thought I was doing something like the example you given.

    The only thing I want is to make it jump back when to the first state when the code is entered correct, when in "locked" stage, and when wrong it should keep looping there. And everytime you start the system it should be reset as if it was unlocked. And I understand the pseudocode, but I can not find the way how to simulate it.

    I was thinking of something like what I have already written.

    Code ( (Unknown Language)):
    1.  
    2. Init  call LCD_Init  ;setup LCD
    3.  
    4.   clrf count   ;set counter register to zero
    5. Message  movf count, w  ;put counter value in W
    6.   call Text   ;get a character from the text table
    7.   xorlw 0x00   ;is it a zero?
    8.   btfsc STATUS, Z
    9.   goto Main
    10.   call LCD_Char
    11.   incf count, f
    12.   goto Message
    13. Wrong  call LCD_Clr
    14.   clrf count   ;set counter register to zero
    15. Message1 movf count, w  ;put counter value in W
    16.   call Wrong_Text  ;get a character from the text table
    17.   xorlw 0x00   ;is it a zero?
    18.   btfsc STATUS, Z
    19.   goto Wrong_Wait
    20.   call LCD_Char
    21.   incf count, f
    22.   goto Message1
    23. Wrong_Wait call Delay255
    24.   call Delay255
    25.   call Delay255
    26.   call Delay255
    27.   goto Init
    28. Correct  call LCD_Clr
    29.   clrf count   ;set counter register to zero
    30. Message2 movf count, w  ;put counter value in W
    31.   call Correct_Text  ;get a character from the text table
    32.   xorlw 0x00   ;is it a zero?
    33.   btfsc STATUS, Z
    34.   goto Correct_Wait
    35.   call LCD_Char
    36.   incf count, f
    37.   goto Message2
    38. Correct_Wait call Delay255
    39.   call Delay255
    40.   call Delay255
    41.   call Delay255
    42.   goto Init2
    43.  
     
  7. Caveman

    Active Member

    Apr 15, 2008
    471
    0
    Create a variable called "state" in your list of registers. If state is 0, we will call it UNLOCKED, if 1 it is LOCKED

    Code ( (Unknown Language)):
    1.  
    2. Start:
    3.   clrf state        ; Initialize STATE = UNLOCKED.
    4. RunLoop:
    5.   btfss state, 0   ; if state = LOCKED, skip the next line.
    6.   goto UL1          ; not locked, so go to the unlocked code.
    7.   call ShowLockedQuery  ; Print "Locked: Enter code"
    8.   goto ML1
    9. UL1:
    10.   call ShowUnlockedQuery ; Print "Unlocked: Enter code"
    11. ML1:
    12.   ; Get Code Entry in the same method as before.
    13.   ;If entry is correct
    14.   ;    Print "Correct"
    15.   ;    Toggle State
    16.   ;Else entry is incorrect
    17.   ;    Print "Wrong"
    18.   ;Delay so statement can be read.
    19. goto RunLoop
    20.  
    21.  
    Does this make sense?
     
  8. draeberg

    Thread Starter New Member

    Apr 24, 2008
    7
    0
    This make a lot of sense to me. I am indeed certain of what to do. ;) I will try it out.
     
Loading...