Help programming a pic12f683 in assembly

Thread Starter

Daemon

Joined Jun 20, 2009
33
Hi guys

I am attempting to learn assembly and program a switched timer for a fishing torpedo.

I am using MPLAB IDE v8.56 to write the assembly code and debug it

I have read the datasheet, although it hasn't all sunk in and gone through several of the tutorials available on the net but I need some examples or someone to steer me in the right direction please.

This is not homework, it is a hobby project I am building at home.

My circuit works like this
I have a 12v battery attached to GP4 via a 7805 and a resistor divider to reduce the voltage below 5v for the pic to read the voltage
I have one reed switch on GP2 as the circuit will be activated by a magnet from outside the body of the torpedo as it is fully contained and waterproofed.
I have 1 led and resistor. on GP0
I also have a mosfet grounded on GP1 and switched by GP5

The timer will work like this

psuedo code
is switch open on powering unit
if yes light led steady for 1 second then flash to indicate low voltage cutoff setting
if low voltage setting done save to EEPROM
is switch not open on powering unit
if not then blink led up to 6 times to indicate setting of motor timer. ie 5 blinks equals 5x5 minutes or25 minutes
then light led steady to indicate ready to run
when switch next opened start 1 minute timer to allow time to get the torpedo in the water then start saved motor timer and activate mosfet to switch on motor
when set motor timer elapses or low voltage cutoff setting reached stop motor
if switch held open for longer than 10 seconds after timer indication then power off circuit

I intend to write all the code and debug it to the best of my ability but will need some help(other than saying look in the data sheet) in order to correct anything I haven't quite worked out

The order I will write the program I think would be in this order
1. Implement the interrupt on change features of the chip so the chip can be put into low power sleep mode and also power on when the switch is activated
2. Write the code for the adc feature so I can read the lvc(low voltage cutoff) setting and store it in EEPROM
3. Write the subroutine for the 5 minute delay and how to store that in EEPROM
4. Write the code with all the timers etc to blink, light and flash the led and activate the motor.

Does anyone have any suggestions for me on a better way to do things or a better order to write it?

Thanks for reading this
Steve
 

beenthere

Joined Apr 20, 2004
15,819
Don't try to write the whole program code all at once. Assembly code can be done in modules, so you can get started by flashing LED's and using a pot to supply voltages to the ADC for conversion. Programming is weird, but sometimes it clicks and you can do anything.
 

Markd77

Joined Sep 7, 2009
2,806
Sounds like a good plan. Start with the template code so that you already have the context saving for the interrupts.
ADC and EEPROM code is in the datasheet, but the sample code does not restore the bank back to bank 0. Also the sample code expects certain variables to be in the memory that is shared between banks (addresses 0x70-0x7f).

Have a go, get to know the IDE and simulator and if you get stuck, we are here to help.
 

Thread Starter

Daemon

Joined Jun 20, 2009
33
Thanks guys.
Will write something up and post it and see how I go.
Will be doing exactly as suggested too and doing it in modules.

Sorry for the late reply, I clicked instant notification but it never happened.
Will need to be more watchful.
Cheers
 

Thread Starter

Daemon

Joined Jun 20, 2009
33
From the tutorials etc I have read so far I have pieced together the following code
I was going to only add the interrupt on change code but have also added a 5 minute delay subroutine and some definitions

Please tell me what you think.
My next step would be writing the code for the low voltage cutoff setting and EEPROM

Rich (BB code):
;Timer with low voltage cutoff
;Program to monitor a 12v battery
;Uses a FET to drive a load
;Switches the load off when volts reach minimum (10v)
;Reed switch 2 triggers advance in timer incremented by 5 minutes
;This causes led to flash number of 5 minute intervals up to 30 minutes
;Reed switch 1 held on power up causes led to flash quickly 5 times indicating lvc programming mode has been entered
;once lvc programming mode has been entered voltage is tested through a LM7805 and value is stored in EEPROM for lvc function
;Written for PIC12F683 (8 pin)
;On startup if reed switch 2 is not activated within 1 second the led flashes the number of times it is programmed for then waits for reed switch 1 to activate
;Pushing Reed switch 1 again at this time activates the timer
;If during led flashing reed switch 2 is activated again new timer period will be set
;Pin 2(GP5) switches mosfet, Pin 6(GP1) switches mosfet, Pin 3(GP4) reads voltage, Pin 7(GP0) LED output, Pin 5(GP2) Switch input, Pin 1(VDD), Pin 8(VSS)

;//PREPROCESSOR ===============================================|---|

    LIST    p=12F683
    include "P12F683.INC"

    __CONFIG    _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOD_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT
    errorlevel -302
    errorlevel -312
    

nBUTTON      EQU    D'02'            ; Reed switch 1 on GP2 
nBUTTON2    EQU D'03'            ; Reed switch 2 on GP3 
nB_LED        EQU    D'00'            ; switch activated led on GP0
clockrate      EQU     .4000000        ; 4MHz


        CBLOCK    0x20
        Delay:2            ;Define two registers for the delay and delay + 1
        mode            ;Mode
        count1            ; for 5 minute delay     
        cs_W            ; ISR save context
        cs_STATUS        ; "
        SW1                ; Switch #1
        SW2                ; Switch #2
        TMR                ; timer value in minutes
        d1                ;Delay variables for 5 minute timer
        d2                ;
        d3                ;
        d4                ;

    ENDC



    org 0x0000
    goto    init

; interrupt service routine :
;----------------------------
ISR    org    0x004    
        movwf    cs_W                ; save W
        movf    STATUS,w            ; save status
        movwf    cs_STATUS            ; 

isr_end                            ;restore context then return
        movf    cs_STATUS,w            ;restore STATUS
        movwf    STATUS
        swapf    cs_W,f                ;restore w
        swapf    cs_W,w
        retfie

; 5 minute delay subroutine
DelayW      movwf   count1         ;call DelayW with 1 in w it will set 5 minutes
                                ;call DelayW with 2 in w it will set 10 minutes etc
Delay5
         ;299999995 cycles 
       movlw   0x54 
       movwf   d1 
       movlw   0xA1 
       movwf   d2 
       movlw   0xFD 
       movwf   d3 
       movlw   0x02 
       movwf   d4 
Delay_0 
       decfsz   d1, f 
       goto   $+2 
       decfsz   d2, f 
       goto   $+2 
       decfsz   d3, f 
       goto   $+2 
       decfsz   d4, f 
       goto   Delay_0 

         ;5 cycles 
       goto   $+1 
       goto   $+1 
       nop 

      decfsz   count1   ,f 
      goto   Delay5 
      retlw   0x00


; initialize port and registers :
;--------------------------------
init
      banksel    GPIO
      movf    GPIO,w                ;Clear mismatch condition
      bcf        INTCON,GPIF            ;clear interrupt flag
                                ;configure ports
    
        
    END
Thanks
Steve
 

Markd77

Joined Sep 7, 2009
2,806
Looks OK so far. To deal with the interrupt happening when the main code is in bank 1, cs_W and cs_STATUS should be defined in a second section starting cblock 0x70 (available from both banks) and there should be a banksel after saving W and STATUS in the ISR.
 

Thread Starter

Daemon

Joined Jun 20, 2009
33
To deal with the interrupt happening when the main code is in bank 1, cs_W and cs_STATUS should be defined in a second section starting cblock 0x70 (available from both banks) and there should be a banksel after saving W and STATUS in the ISR.
Like this?
I have pasted just the cblock and isr section
Rich (BB code):
        CBLOCK    0x20
        Delay:2            ;Define two registers for the delay and delay + 1
        mode            ;Mode
        count1            ; for 5 minute delay     
        
        SW1                ; Switch #1
        SW2                ; Switch #2
        TMR                ; timer value in minutes
        d1                ;Delay variables for 5 minute timer
        d2                ;
        d3                ;
        d4                ;

    ENDC

        CBLOCK    0x70
        cs_W            ; ISR save context
        cs_STATUS        ; "

    ENDC

    org 0x0000
    goto    init

; interrupt service routine :
;----------------------------
ISR    org    0x004    
    movwf    cs_W                ; save W
    movf    STATUS,w            ; save status
    movwf    cs_STATUS            ; 
    banksel    GPIO
 

Thread Starter

Daemon

Joined Jun 20, 2009
33
I have read a tutorial by Nigel Goodwin and hopefully ported it to the pic12f683 correctly and GP4 of my pic.

I am not sure of my facts as far as the result of the adc. I want to set a 10v low voltage cutoff, do I need to connect a variable power supply to the circuit to do this or can I work out the value by using the ratio instead and simply program it from MPLab.

For instance I have 2 resistors going through an lm7805(which has the 12v from the 2 7ah batteries connected to it)
The resistors are 33k and 10k so I think it would work like so
for a 10 bit number (0-1023) then I have a ratio of 4.3
If I want the cutoff to be 10v then that should make the number to set as 479 being 479 *.005v=2.395v at pic times ratio of 4.3 makes it 2.395*4.3=10.2985v

I worked out the ratios etc using this spreadsheet
http://www.flyelectric.ukgateway.net/PIC ADC resistors and current.xls

Do I then need to put that value in w and then call the adc routines?
I decided to leave the eeprom routine until later for now.

Rich (BB code):
  ;//PREPROCESSOR ===============================================|---|

    LIST    p=12F683
    include "P12F683.INC"


    __CONFIG    _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOD_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT
    errorlevel -302
    errorlevel -312
    CBLOCK    0x21
NumH
NumL
    ENDC
            
            org        0x0000
Init_ADC    org        0x004
; Set ADCON0
            movlw   b'10000001'
            movwf   ADCON0
; Set ADSEL
            BANKSEL ANSEL
            movlw   b'10000101'
            movwf   ANSEL
            BANKSEL ADCON0
        return

Read_ADC
            bsf    ADCON0, GO        ;initiate conversion
            btfsc   ADCON0, GO
            goto    $-1            ;wait for ADC to finish

            movf    ADRESH,W
            andlw   0x03
            movwf   NumH
            BANKSEL ADRESL
            movf    ADRESL,W
            BANKSEL    ADRESH
        movwf    NumL            ;return result in NumL and NumH
        return    
        END
 

Thread Starter

Daemon

Joined Jun 20, 2009
33
Do I then need to put that value in w and then call the adc routines?
Didn't mean to write that but couldn't edit my post. I was writing while thinking about the EEPROM code I will write next and wrote this accidentaly. I can see how it works and think I have a handle on the adc.

I think the code is better like this too
Rich (BB code):
  ;//PREPROCESSOR ===============================================|---|

    LIST    p=12F683
    include "P12F683.INC"


    __CONFIG    _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOD_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT
    errorlevel -302
    errorlevel -312
    CBLOCK    0x21
NumH
NumL
    ENDC
            
            org        0x0000
Init_ADC    org        0x004
; Set ADCON0
            movlw   b'10000001'
            movwf   ADCON0
            CALL SampleTime ;Acquisiton delay
; Set ADSEL
            BANKSEL TRISIO ;
            BSF TRISIO,4 ;Set GP4 to input
            BANKSEL ANSEL
            MOVLW b'01110010' ;ADC Frc clock,4MHz
            IORWF ANSEL ; and GP4 as analog
            BANKSEL ADCON0
        return

Read_ADC
            bsf    ADCON0, GO        ;initiate conversion
            btfsc   ADCON0, GO
            goto    $-1            ;wait for ADC to finish

            movf    ADRESH,W
            andlw   0x03
            movwf   NumH
            BANKSEL ADRESL
            movf    ADRESL,W
            BANKSEL    ADRESH
        movwf    NumL            ;return result in NumL and NumH
        return    
SampleTime    nop
            nop
            nop
            nop
            nop
            nop
            nop
            nop
            nop
            nop
            nop
            nop
            return        

        END
 
Last edited:

Markd77

Joined Sep 7, 2009
2,806
You should be able to edit your posts now.
I've given it a quick run through the simulator and it is complaining about TAD time being less than 1.6us so you should look at the value for ADCON0.
Presumably there is some code missing because otherwise there are a couple of RETURNs that shouldn't be there.
Also the default values for some of the FSRs isn't 0 so:
bsf TRISIO, 4 does nothing because the default is b'00111111'

MOVLW b'01110010' ;ADC Frc clock,4MHz
IORWF ANSEL ; and GP4 as analog
doesn't change ANSEL to b'01110010' because the default is b'00001111'
Use movwf ANSEL instead.

I'm not sure it's necessary for analog input but I turn the comparator off if I'm not using it:
movlw 0x07
movwf CMCON0
 

Thread Starter

Daemon

Joined Jun 20, 2009
33
I've given it a quick run through the simulator and it is complaining about TAD time being less than 1.6us so you should look at the value for ADCON0.
Yes, the data sheet referred to calling sampletime for the acquisition time but didn't specify how to set it up. So I guessed.
Here is the code in the data sheet.
Rich (BB code):
;This code block configures the ADC
;for polling, Vdd reference, Frc clock
;and GP0 input.
;
;Conversion start & polling for completion
; are included.
;
BANKSEL TRISIO ;
BSF TRISIO,0 ;Set GP0 to input
BANKSEL ANSEL ;
MOVLW B’01110001’ ;ADC Frc clock,
IORWF ANSEL ; and GP0 as analog
BANKSEL ADCON0 ;
MOVLW B’10000001’ ;Right justify,
MOVWF ADCON0 ;Vdd Vref, AN0, On
CALL SampleTime ;Acquisiton delay
BSF ADCON0,GO ;Start conversion
BTFSC ADCON0,GO ;Is conversion done?
GOTO $-1 ;No, test again
BANKSEL ADRESH ;
MOVF ADRESH,W ;Read upper 2 bits
MOVWF RESULTHI ;Store in GPR space
BANKSEL ADRESL ;
MOVF ADRESL,W ;Read lower 8 bits
MOVWF RESULTLO ;Store in GPR space
I was trying to edit it to an3 and I wasn't sure how to set the correct conversion and acquisition time. In fact the setup for the adc configuration has lost me completely.
I have changed the code to add the comparator off and paste here the edited part of adcon0 but still not sure how to setup ansel.
Rich (BB code):
;turn off comparator
            movlw 0x07
            movwf CMCON0

Init_ADC    org        0x004
; Set ADCON0
            movlw   b'11001111';right justify,vref,an3,go/done,adc enable?
            movwf   ADCON0
            CALL SampleTime ;Acquisiton delay
; Set ADSEL
            BANKSEL ANSEL
            MOVLW b'11001111' 
            MOVWF ANSEL 
            BANKSEL ADCON0
        return
Presumably there is some code missing because otherwise there are a couple of RETURNs that shouldn't be there.
Yes this is just one module so I am guessing as these are set up as subroutines I would call the read or write from the correct place in the full code, hence the returns.

Thanks for your guidance Mark. I really appreciate it. I am starting to 'get it' slowly.
 

Markd77

Joined Sep 7, 2009
2,806
For ADCON0 I would go for:
10001101
If you use a voltage regulator for the PIC it usually makes sense to use Vdd as the reference (although your setup may be different).
The go/done bit should not be set in the same instruction that turns on the A/D.

for ANSEL I would go for:
00011000
fosc/8 and an3

I think that should work.
 

Thread Starter

Daemon

Joined Jun 20, 2009
33
I have pasted the eeprom example code from the data sheet altered slightly only so they can be called.

Rich (BB code):
    #include "P12F683.INC"
    errorlevel -302

    GLOBAL    EEPROM_W
    GLOBAL    EEPROM_R

    org 0x2100
    
;Read EEPROM data
EEPROM_R    
    BANKSEL EEADR ;
    MOVLW CONFIG_ADDR ;
    MOVWF EEADR ;Address to read
    BSF EECON1,RD ;EE Read
    MOVF EEDAT,W ;Move data to W
    return
;Write EEPROM data
EEPROM_W
    BANKSEL EECON1 ;
    BSF EECON1,WREN ;Enable write
    BCF INTCON,GIE ;Disable INTs
    BTFSC INTCON,GIE ;See AN576
    GOTO $-2 ;
    MOVLW 55h ;Unlock write
    MOVWF EECON2 ;
    MOVLW 0AAh ;
    MOVWF EECON2 ;
    BSF EECON1,WR ;Start the write
    BSF INTCON,GIE ;Enable INTS
    return
    
    END
In my case from doing my adc conversion I copied the adc result into numH and numL. As it is right justified can I just ignore the numH and am I correct that the contents of numL are what I want to write to and then later read from EEPROM memory? I cannot work out from the data sheet how to copy that data with the code provided.

It halts at 1st error at the bit highlighted in blue for config_addr. It also gave an error for the location Aah so I changed it to 0Aah
Is that the right way to do it?
 

Markd77

Joined Sep 7, 2009
2,806
I would think you probably want to save all of ADRES.
Here's how I do it for loading and saving in the first 2 locations, but on a slightly different PIC. The only differences seem to be that EEDATA seems to be called EEDAT which probably needs changing, and the 2 lines in your sample starting ;see AN576. May as well add those lines.
Reading and writing EEPROM is one of the trickier things to do on a PIC.

Also, if you aren't using interrupts then you can comment out the line which enables them (although if the individual interrupts aren't enabled {default settings} then it makes no difference).

Rich (BB code):
ORG 0x2100 
de 0xFF 
de 0x00
Rich (BB code):
writeEE 
    bsf STATUS,RP0 ;Bank 1 
    bsf EECON1,WREN ;Enable write 
    bcf INTCON,GIE ;Disable INTs 
    movlw 0x55 ;Unlock write 
    movwf EECON2 ; 
    movlw 0xAA ; 
    movwf EECON2 ; 
    bsf EECON1,WR ;Start the write 
    bsf INTCON,GIE ;Enable INTS 
    bcf STATUS, RP0 ;bank 0 
    return 
 
readEE 
    BSF STATUS, RP0 ; Bank 1 
    MOVWF EEADR ; Address to read 
    BSF EECON1, RD ; EE Read 
    MOVF EEDATA, W ; W = EEDATA 
    BCF STATUS, RP0 ; Bank 0 
    return
Rich (BB code):
clrw 
call readEE 
movwf redduty 
movlw 0x01 
call readEE 
movwf blueduty
Rich (BB code):
    movf redduty, W 
    bsf STATUS, RP0                    ;page 1 
    clrf EEADR 
    movwf EEDATA 
    call writeEE 
    bsf STATUS, RP0                    ;page 1 
waitEE 
    btfsc EECON1, WR 
    goto waitEE 
    bcf STATUS, RP0                    ;page 0     
    movf blueduty, W 
    bsf STATUS, RP0                    ;page 1  
    incf EEADR, F 
    movwf EEDATA 
    call writeEE
 

Thread Starter

Daemon

Joined Jun 20, 2009
33
Okay so the EEPROM subroutines are unchanged and you move your adres in your case redduty to w then to the EEDATA and then call the writeEE.

Why do you do this
Rich (BB code):
movlw  0x01
In between reading the data from EEPROM?

Is a waitEE required for each write because I can't see where it is being called from.

Also being right justified and the most significant bit in my case being in NumH and the rest being in NumL how do I reassemble them before copying the result to w then to EEDATA

Sorry if this seems dense but I couldn't follow how and where to inject my own data in to the correct location.

Thanks
Steve
 

Markd77

Joined Sep 7, 2009
2,806
The "movlw 0x01" is because readEE expects the eeprom address to save into to be in W. For the first read W was 0 (clrw).
There is a goto waitEE a couple of lines later. Those few lines are checking that the write has completed (it takes a little while).
Only one wait is required because I assume there is no need to write again soon after the second write.

Really you can just swap redduty and blueduty for NumH and NumL. It's a good idea to step through in the simulator and watch the flow and check everything works.
The de'0xff' part saves 2 values in the eeprom, which would be your default value. You can read the PIC with your programmer to check that the values are actually changing.
Presumably later you want to compare the value in NumH and NumL with savedNumH and savedNumL (or similar names).
That's easy enough. You subtract NumH from SavedNumH, if the answer isn't zero then you can tell which number is bigger.
If the answer is zero then subtract NumL from SavedNumL and then you know which number was bigger.
 

Thread Starter

Daemon

Joined Jun 20, 2009
33
Hi Mark

Someone else assisted me with the following code. Its not finished yet as I need to implement the routines we have made.

I get an error 'Error - section '.org_0' type is non-overlay and absolute but occurs in more than one input file'
Can you tell me what that means?
I have searched the routines for a duplication of org 0x000 but cannot find one.

Here is the code
Rich (BB code):
;//PREPROCESSOR ===============================================|---|

    LIST    p=12F683
    include "P12F683.INC"

    __CONFIG    _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOD_OFF & _WDT_OFF & _PWRTE_ON & _INTRC_OSC_NOCLKOUT
    errorlevel -302
    errorlevel -312

        EXTERN    adc
        EXTERN    EEPROMRW
        EXTERN    Interrupt_on_change

delA        equ 20h    ;
delB        equ 21h    ;
temp1        equ 22h    ;
temp2        equ    23h    ; 
pushes        equ    24h    
flashes        equ    25h
Stat_sav    equ 26h
W_sav       equ 27h
 
;****************************************************************
;Equates
;****************************************************************
status        equ    0x03
rp1            equ    0x06
rp0            equ    0x05
option_reg    equ 81h

    
        ;bits
 
rp0        equ    5            ;bit 5 of the status register
 
 
 
;****************************************************************
;Beginning of program
;****************************************************************
        org        0x00
    cblock 0x20
           d1 
           d2 
          d3 
           d4 
           count1            ; for 5 minute delay     
        SW1                ; Switch #1
        SW2                ; Switch #2
        TMR                ; timer value in minutes
      endc 
        GOTO    SetUp
        nop
        ORG    4                ;interrupts always vector to here
        GOTO    isr
        nop
SetUp   bsf        status, rp0     ;Bank 1            
        movlw    b'10111000'        ;Set TRIS  GP0,1,2 out   GP3,4,5 input
        movwf    TRISIO               ;    
        bcf     option_reg,7    ;pull-ups enabled        
        MOVLW    b'00000100'        ;prescaler (1:32)
        movwf    option_reg     ;TMR0 interrupts = 6 mS apart
        BCF        STATUS, RP0        ;bank 0
        movlw   07h             ;turn off Comparator ports
        movwf   CMCON0           ;must be placed in bank 0  
        Clrf    TMR0            ;clear Timer0 register    
        clrf    flashes    
        incf    flashes
        movlw    0xA0            ;set GIE <7> and T0IE <5>
        movwf    INTCON            ;enable Interrupts
        goto     Main    
 
 
isr        MOVWF    W_sav            ;first save critical registers
        SWAPF    STATUS,W
        BCF        STATUS,RP0        ;change to bank 0 
        MOVWF     Stat_sav    
 
        btfss    GPIO,4        ;test switchA
        call    switchPressed
 
        BCF        INTCON,T0IF
        BCF        INTCON,INTF
        SWAPF    Stat_sav,W
        MOVWF    STATUS        ; restore status 
        SWAPF    W_sav,F    
        SWAPF     W_sav,W        ; restore w without changing status
        RETFIE    
 
;********************
;* Delays             *
;********************
 
 
_10mS    movlw    0Ah
        movwf    delB
        nop
        decfsz     delA,f
        goto     $-2
        decfsz     delB,f
        goto     $-4    
        retlw     00    
 
 
_250mS    nop
        decfsz     delA,f
        goto     $-2
        decfsz     delB,f
        goto     $-4    
        retlw     00    

 ; Delay = 60 seconds
; Clock frequency = 4 MHz

; Actual delay = 60 seconds = 60000000 cycles
; Error = 0 %

Delay60            ;59999994 cycles
    movlw    0x23
    movwf    d1
    movlw    0xCB
    movwf    d2
    movlw    0x83
    movwf    d3
Delay_1
    decfsz    d1, f
    goto    $+2
    decfsz    d2, f
    goto    $+2
    decfsz    d3, f
    goto    Delay_1

            ;6 cycles
    goto    $+1
    goto    $+1
    goto    $+1       

; Delay = 300 seconds 
; Clock frequency = 4 MHz 
 
; Actual delay = 300 seconds = 300000000 cycles 
; Error = 0 % 
 

 
DelayW      movwf   count1 
 
Delay5
         ;299999995 cycles 
   movlw   0x54 
   movwf   d1 
   movlw   0xA1 
   movwf   d2 
   movlw   0xFD 
   movwf   d3 
   movlw   0x02 
   movwf   d4 
Delay_0 
   decfsz   d1, f 
   goto   $+2 
   decfsz   d2, f 
   goto   $+2 
   decfsz   d3, f 
   goto   $+2 
   decfsz   d4, f 
   goto   Delay_0 
 

      decfsz   count1   ,f 
      goto   Delay5 
      retlw   0x00
 
 
;****************************
;* Sub Routines             *
;****************************
 
switchPressed
 
        movf    flashes,W    
        movwf    temp1
        movlw   06
        xorwf   temp1     ;if flashes=6
        btfss   status,Z  ;z=1 if flashes=6
        goto    $+4
        movlw   1
        movwf   flashes
        goto    $-8        
 
        bsf     GPIO,0   ;turn on LED    
        call    _250mS
        bcf     GPIO,0   ;turn off LED    
        call    _250mS
        decfsz  temp1,f
        goto    $-5
        incf    flashes,f
        btfss   GPIO,5        ;loop until SwA is released
        goto    $-1
        retlw    00
 
 
;************************
;* Main                 *
;************************
 
Main    
            btfss   GPIO,5        ;test switchA
        call    SwA_Pressed
        btfss   GPIO,4        ;test switchB
        call    SwB_Pressed
        goto    $-4  
 
SwA_Pressed
        call    switchPressed
        goto Main

SwB_Pressed

        call Delay60
        goto Main

;************************
;*EEPROM                 *
;************************
 
        org        2100h            
 
 
        END
 
Top