Building a 2-person "quiz reaction timer" with a microcontroller

Markd77

Joined Sep 7, 2009
2,806
Nice work MMcLaren, looks good. Is it possible to change the label RA5 to MCLR?

Farscape:
I spotted a few things:
It is clearer to put portA, 2 than portA, b'10'.
You are only checking portA, 2 so you need another copy of those 2 lines to check portA, 3.
In the flash subroutine you are changing pins 1 and 2 instead of 3 and 4.
You haven't put the code in yet for checking if the countdown has finished.
There is nothing in the doNothing loop so the program will hang when it gets there - I suppose you could put input checking code in there which would solve my previous point.

This last one you don't really have to worry about but deserves a mention. Because there are calls which never get returned from, the stack which stores where to return to will grow. This would create problems if the chip wasn't being reset every game. If for example you later wanted to expand the game to keep scores or use a pin other than the reset pin it could cause headaches later.
 

Thread Starter

farscape

Joined May 16, 2010
26
Thanks Mike. Some of the commands you used are not on the pic16f84a data sheet. Will the pic still be able to read these commands? (Such as skpnz, banksel, etc.)

I have made some more changes to my code and I hope I'm a little bit closer to getting this done. I have a feeling this is a VERY roundabout way (lots of subroutines), but hopefully its workable. If anybody could check it over that would be great.

I'm a little concerned about my initialization and configuration... Any hints in that respect?

Rich (BB code):
;----------------------------------------------------------------------
;    cpu equates (memory map)
portB    equ    0x06        ; (p. 10 defines port address)
count    equ    0x0c
nCount   equ    0x0d
mCount   equ    0x0e
portA    equ    0x05 
;----------------------------------------------------------------------

    
processor 16F84A
INCLUDE "p16f84A.inc"
__CONFIG _CP_OFF & _WDT_OFF & _XT_OSC & _PWRTE_ON
org H?00?


start           movlw   0x00     ; load W with 0x00 make port B output (p. 45)
                 tris       portB        ; copy W tristate, port B outputs (p. 58)
                 clrf       portB        ; clear all lines low
                 movlw   0x0C        ; load w with 0x0C make RA0,RA1 output and RA2,RA3 input
                 tris       portA        ; copy W tristate
      
                 movlw   0x0A         ; set w=10 decimal
                 movf     count, F
get_cnt       movf     count, w     ; move count to W
                 call       table
                 movwf   portB        ; move W to port B
                 call       pause        ; delay by subroutine
                 call       pause        
                 call       pause
                 call       pause
                 call       pause        ; five pause executions equals ~ 1 second
                 decfsz   count, f     ; decrement counter, skip if=0
                 goto     get_cnt      ; repeat forever
                 goto     doNothing

doNothing    call      checkend2
                 call      checkend3                 
                 goto    doNothing


table          addwf   PCL
                 retlw    b'00000000'
                 retlw    b'01111110'
                 retlw    b'00000100'
                 retlw    b'10110110'
                 retlw    b'10011110'
                 retlw    b'11001100'
                 retlw    b'11011010'
                 retlw    b'11111010'
                 retlw    b'00001110'
                 retlw    b'11111110'
                 retlw    b'11011110'


pause        movlw     0xff        ; set w = 255 decimal
                movwf    mCount      ; mCount = w
loadN         movlw    0xff        ; set w = 255 decimal
                movwf    nCount      ; nCount = w
decN          call       test2
                call       test3
                decfsz   nCount, f   ; nCount--
                goto     decN        ; if nCount != 0 then repeat nCount--   
                decfsz   mCount, f   ; else decrement Count
                goto     loadN       ; if mCount != 0 then 
                return               ; else exit subroutine

test2         BTFSS  portA, 2
                return
                call    flash2

flash2        bsf   portA, 1
                movlw    0xff        ; set w = 255 decimal
                movwf    mCount      ; mCount = w
loadN2       movlw    0xff        ; set w = 255 decimal
                movwf    nCount      ; nCount = w
decN2        decfsz   nCount, f   ; nCount--
                goto     decN2        ; if nCount != 0 then repeat nCount--   
                decfsz   mCount, f   ; else decrement Count
                goto     loadN2       ; if mCount != 0 then 
                bcf     portA, 1
                bsf      portA, 0
                call     end1

test3         BTFSS portA, 3
                return
                call      flash3

flash3        bsf   portA, 0
                movlw    0xff        ; set w = 255 decimal
                movwf    mCount      ; mCount = w
loadN3       movlw    0xff        ; set w = 255 decimal
                movwf    nCount      ; nCount = w
decN3        decfsz   nCount, f   ; nCount--
                goto     decN3        ; if nCount != 0 then repeat nCount--   
                decfsz   mCount, f   ; else decrement Count
                goto     load3       ; if mCount != 0 then 
                bcf     portA, 0
                bsf     portA, 1
                call end1

checkend2    BTFSS portA, 2
                  return
                  bsf portA, 1
                  call end1

checkend3    BTFSS portA, 3
                   return
                   bsf portA, 0
                   call end1

end1            movlw    0xff        ; set w = 255 decimal
                  movwf    mCount      ; mCount = w
loadN1           movlw    0xff        ; set w = 255 decimal
                  movwf    nCount      ; nCount = w
decN1           decfsz   nCount, f   ; nCount--
                  goto     decN1        ; if nCount != 0 then repeat nCount--   
                  decfsz   mCount, f   ; else decrement Count
                  goto     loadN1       ; if mCount != 0 then 
                  goto     end1


end
---------------------------------------------------------------------------------------
Thanks for all the help
 
Last edited:

Markd77

Joined Sep 7, 2009
2,806
I've made a couple of changes (including some labels that were used twice so it's worth checking it still does what it should) and tweaked the delay so it is close enough to 1 second.
It runs in the simulator fine now.
Initialisation and config look fine. The tris command isn't used on newer PICs but works fine on this one.
There are a couple of subroutines that are very short and it would probably be clearer to leave them in the main part but for readability plenty of subroutines are pretty good.
There are a couple of calls that in a bigger program should be gotos because they are never intended to return, but as the program ends and then gets reset it won't cause any problems here.
I think you should program a PIC and see what happens.

Rich (BB code):
;----------------------------------------------------------------------
;    cpu equates (memory map)
portB    equ    0x06        ; (p. 10 defines port address)
count    equ    0x0c
nCount   equ    0x0d
mCount   equ    0x0e
portA    equ    0x05 
;----------------------------------------------------------------------

    
processor 16F84A
INCLUDE "p16f84A.inc"
__CONFIG _CP_OFF & _WDT_OFF & _XT_OSC & _PWRTE_ON
org 0x00


start          movlw    0x00        ; load W with 0x00 make port B output (p. 45)
                 tris    portB        ; copy W tristate, port B outputs (p. 58)
                 clrf    portB        ; clear all lines low
                 movlw    0x0C        ; load w with 0x0C make RA0,RA1 output and RA2,RA3 input
                 tris    portA        ; copy W tristate
      
                 movlw   0x0A         ; set w=10 decimal
                 movwf    count
get_cnt      movf    count, w     ; move count to W
                 call    table
                movwf   portB        ; move W to port B
                call    pause        ; delay by subroutine
                call    pause        
                call    pause
                call    pause
                call    pause        ; five pause executions equals ~ 1 second
                decfsz  count, f     ; decrement counter, skip if=0
                goto    get_cnt      ; repeat forever
                goto doNothing

doNothing    call checkend2
                        call checkend3                 
                          goto doNothing


table            addwf PCL, F
                   retlw b'00000000'
                   retlw b'01111110'
                   retlw b'00000100'
                   retlw b'10110110'
                   retlw b'10011110'
                   retlw b'11001100'
                   retlw b'11011010'
                   retlw b'11111010'
                   retlw b'00001110'
                   retlw b'11111110'
                   retlw b'11011110'


pause        movlw    0x3C        ; set w = 255 decimal
                 movwf    mCount      ; mCount = w
loadN         movlw    0xff        ; set w = 255 decimal
                 movwf    nCount      ; nCount = w
decN          call      test2
                 call      test3
                 decfsz   nCount, f   ; nCount--
                 goto     decN        ; if nCount != 0 then repeat nCount--   
                 decfsz   mCount, f   ; else decrement Count
                 goto     loadN       ; if mCount != 0 then 
                 return               ; else exit subroutine

test2         BTFSS  portA, 2
                return
                call       flash2

flash2        bsf   portA, 1
                 movlw    0xff        ; set w = 255 decimal
                 movwf    mCount      ; mCount = w
loadN2       movlw    0xff        ; set w = 255 decimal
                 movwf    nCount      ; nCount = w
decN2        decfsz   nCount, f   ; nCount--
                 goto     decN2        ; if nCount != 0 then repeat nCount--   
                 decfsz   mCount, f   ; else decrement Count
                 goto     loadN2       ; if mCount != 0 then 
                 bcf     portA, 1
                 bsf     portA, 0
                  call    end1

test3        BTFSS portA, 3
                return
                call      flash3

flash3        bsf   portA, 0
                movlw    0xff        ; set w = 255 decimal
                movwf    mCount      ; mCount = w
loadN3       movlw    0xff        ; set w = 255 decimal
                 movwf    nCount      ; nCount = w
decN3       decfsz   nCount, f   ; nCount--
                 goto     decN3        ; if nCount != 0 then repeat nCount--   
                 decfsz   mCount, f   ; else decrement Count
                 goto     loadN3       ; if mCount != 0 then 
                 bcf     portA, 0
                 bsf     portA, 1
        call end1

checkend2    BTFSS portA, 2
                        return
                        bsf portA, 1
        call end1

checkend3    BTFSS portA, 3
                        return
                        bsf portA, 0
                        call end1

end1        movlw    0xff        ; set w = 255 decimal
                 movwf    mCount      ; mCount = w
loadN0        movlw    0xff        ; set w = 255 decimal
                 movwf    nCount      ; nCount = w
decN0        decfsz   nCount, f   ; nCount--
                 goto     decN0        ; if nCount != 0 then repeat nCount--   
                 decfsz   mCount, f   ; else decrement Count
                 goto     loadN0       ; if mCount != 0 then 
                 goto     end1


end
 

meri-d

Joined Jan 1, 2012
2
Hello, I'm having the same final project, so I wanted to ask if someone can explain me what about the reset? I'm not seeing it in this code.. pleas help me,it is realy very important!
 

meri-d

Joined Jan 1, 2012
2
Nice work MMcLaren, looks good. Is it possible to change the label RA5 to MCLR?

Farscape:
I spotted a few things:
It is clearer to put portA, 2 than portA, b'10'.
You are only checking portA, 2 so you need another copy of those 2 lines to check portA, 3.
In the flash subroutine you are changing pins 1 and 2 instead of 3 and 4.
You haven't put the code in yet for checking if the countdown has finished.
There is nothing in the doNothing loop so the program will hang when it gets there - I suppose you could put input checking code in there which would solve my previous point.

This last one you don't really have to worry about but deserves a mention. Because there are calls which never get returned from, the stack which stores where to return to will grow. This would create problems if the chip wasn't being reset every game. If for example you later wanted to expand the game to keep scores or use a pin other than the reset pin it could cause headaches later.
hello, I have the same final project so i wanted to ask what about the reset button? how should define it in the code?
 
Top