Vai al contenuto
PLC Forum


Timer 16f84a


kiki kaikai

Messaggi consigliati

Ciao a tutti

Sto impazzendo con un progetto che ho trovato su internet, questo è lo schema

http://img718.imageshack.us/i/timer16f84.jpg/

ho fatto tutto alla perfezione ma non riesco a farlo funzionare, ho testato separatamente sia il cd4511 e anche il 16f84 con altri schemi e file hex e tuttu funziona bene, a questo punto ho pensato di riscrivere il file in ASM e poi di compilarlo in hex con il programma MPLAB IDE

Da solo non sono in grado di riscriverlo, mi potete aiutare? in rete ho trovato questo listato ASM ho pensato di prendere spunto da qui

perfavore aiutatemi.. worthy.gif

Grazie

;-------------------------------------------------------------------------;

; Darkroom Timer ;

; April '99 Stan Ockers (ockers[at]anl.gov) ;

; circuit diagram in CNTDN.PCX ;

; further description in CNTDN.TXT ;

; ;

; Counts down from 0-99 min and 0-59 sec giving an alarm at 0 ;

; initial counts are held in data EEPROM setable with one button ;

; ;

; RBO-RB3 to bases of transistors connect to common cathode of displays. ;

; RA0-RA3 to 1,2,4,8 BCD inputs of CD4511 7 segment latch and driver. ;

; RB7 to start pushbutton used to start countdown and silence alarm. ;

; RB6 goes to time set pushbutton use to sucessively set the digits. ;

; RA4 with pull-up resistor goes to PB to select from 15 starting counts ;

; RB4 and RB5 go to speaker which gives an alarm. ;

;-------------------------------------------------------------------------;

LIST P=16F84

#INCLUDE "p16f84.inc"

;-------------------------------------------------------------------------;

; Here we define our own personal registers and give them names ;

;-------------------------------------------------------------------------;

SEC EQU H'0C' ; this register holds the value of seconds

SEC10 EQU H'0D' ; holds value of 10's of seconds

MIN EQU H'0E' ; holds value of minutes

MIN10 EQU H'0F' ; holds value of 10's of minutes

DIGCTR EQU H'10' ; 8 bit counter, only 2 lowest bits actually used

DIGIT EQU H'11' ; hold digit number to access table

INTCNT EQU H'12' ; counts # interrupts to determine when 1 sec up

FUDGE EQU H'13' ; allows slight adjustment every 7 interrupts

RUNFLG EQU H'14' ; bit 0 only, tells if countdown in progress

W_TEMP EQU H'15' ; temporarily holds value of W

STATUS_TEMP EQU H'16' ; temporarily holds value of STATUS

SECNT EQU H'17' ; used in counting 50, 20 msec delays for 1 sec

CNTMSEC EQU H'18' ; used in timing of milliseconds

ALARM EQU H'19' ; bit 0 only, used as flag for when to alarm

OFFSET EQU H'1A' ; hold offset of address in EEPROM

;-------------------------------------------------------------------------;

; Here we give names to some numbers to make their use more clear ;

;-------------------------------------------------------------------------;

#DEFINE START_PB D'7'

#DEFINE SET_PB D'6'

#DEFINE SELECT_PB D'4'

#DEFINE RB4 D'4'

#DEFINE RB5 D'5'

;-------------------------------------------------------------------------;

; We set the start of code to orginate a location zero ;

;-------------------------------------------------------------------------;

ORG 0

GOTO MAIN ; jump to the main routine

NOP

NOP

NOP

GOTO INTERRUPT ; interrupt routine

;-------------------------------------------------------------------------;

; This table is used to get a bit pattern that will turn on a digit ;

;-------------------------------------------------------------------------;

BITPAT ADDWF PCL,f ; get bit pattern for transistors

RETLW H'0E' ; a low, (0), turns the transistor on

RETLW H'0D'

RETLW H'0B'

RETLW H'07'

;-------------------------------------------------------------------------;

; Initialization routine sets up ports and timer ;

;-------------------------------------------------------------------------;

INIT MOVLW H'C0' ; PB6 & PB7 inputs all others outputs

TRIS PORTB

MOVLW H'10' ; Port RA4 input, others outputs

TRIS PORTA

MOVLW H'03' ; prescaler on TMR0 and 1:16

OPTION

MOVLW H'A0' ; GIE & T0IE set T0IF cleared

MOVWF INTCON

MOVLW H'F4' ; initialize INTCNT

MOVWF INTCNT

MOVLW H'06' ; initialize FUDGE

MOVWF FUDGE

CLRF OFFSET ; initialize OFFSET

RETURN

;-------------------------------------------------------------------------;

; This is the interrupt routine that is jumped to when TMR0 overflows ;

;-------------------------------------------------------------------------;

INTERRUPT MOVWF W_TEMP ; save W

SWAPF STATUS,W ; save status

MOVWF STATUS_TEMP ; without changing flags

INCF DIGCTR,f ; next digit #

MOVF DIGCTR,W ; get it into W

ANDLW H'03' ; mask off 2 lowest bits

MOVWF DIGIT ; save it for later

ADDLW H'0C' ; point at register to display

MOVWF FSR ; use as pointer

MOVF INDF,W ; get value of reg pointed to into W

MOVWF PORTA ; output to CD4511

MOVF DIGIT,W ; recall digit #

CALL BITPAT ; get bit pattern

MOVWF PORTB ; select transistor

DECFSZ INTCNT,f ; finished 1 sec ?

GOTO RESTORE ; not yet, return and enable inter.

CALL EVERYSEC ; go to every second routine

MOVLW H'F4' ; reset INTCNT to normal value

MOVWF INTCNT

DECFSZ FUDGE,f ; time for fudge?

GOTO RESTORE ; not yet, continue on

MOVLW H'06' ; reset FUDGE to 6

MOVWF FUDGE

INCF INTCNT,f ; INTCNT to 245

RESTORE SWAPF STATUS_TEMP,W ; get original status back

MOVWF STATUS ; into status register

SWAPF STATUS_TEMP,f ; old no flags trick again

SWAPF STATUS_TEMP,W ; to restore W

BCF INTCON,T0IF ; clear the TMR0 interrupt flag

RETFIE ; finished

;-------------------------------------------------------------------------;

; This routine is called by the interrupt routine every second ;

;-------------------------------------------------------------------------;

EVERYSEC BTFSS RUNFLG,0 ; return if runflg not set

RETURN

DECF SEC,f ; decrement seconds digit

INCFSZ SEC,W ; test for underflow

GOTO CKZERO

MOVLW H'09' ; reset sec to 9

MOVWF SEC

DECF SEC10,f ; decrement SEC10

INCFSZ SEC10,W ; check underflow

GOTO CKZERO

MOVLW H'05'

MOVWF SEC10

DECF MIN,f

INCFSZ MIN,W

GOTO CKZERO

MOVLW H'09'

MOVWF MIN

DECF MIN10,f

CKZERO MOVF SEC,f ; test SEC for zero

BTFSS STATUS,Z

RETURN

MOVF SEC10,f ; check SEC10 for zero

BTFSS STATUS,Z

RETURN

MOVF MIN,f ; check MIN for zero

BTFSS STATUS,Z

RETURN

MOVF MIN10,f ; check MIN10 for zero

BTFSS STATUS,Z

RETURN

CLRF RUNFLG ; stop the countdown

BSF ALARM, 0 ; set the alarm flag

RETURN

;-------------------------------------------------------------------------;

; This is a routine to read a byte from the data EEPROM ;

;-------------------------------------------------------------------------;

READEE MOVWF EEADR ; set up eeprom address from W

BSF STATUS,RP0 ; change to page 1

BSF EECON1,RD ; set the read bit

BCF STATUS,RP0 ; back to page 0

MOVF EEDATA,W ; return value in W

RETURN

;-------------------------------------------------------------------------;

; This routine fills the display registers from data EEPROM ;

;-------------------------------------------------------------------------;

GETEE MOVLW H'01' ; EEprom location 1 +

ADDWF OFFSET,W ; offset from start

CALL READEE ; into W

MOVWF SEC ; into SEC register

MOVLW H'02' ; location 2 +

ADDWF OFFSET,W ; offset from start

CALL READEE ; into W

MOVWF SEC10 ; into SEC10 register

MOVLW H'03' ; location 3 +

ADDWF OFFSET,W ; offset from start

CALL READEE ; into W

MOVWF MIN ; into MIN register

MOVLW H'04' ; location 4 +

ADDWF OFFSET,W ; offset from start

CALL READEE ; into W

MOVWF MIN10 ; into MIN10 register

RETURN

;-------------------------------------------------------------------------;

; This routine writes a byte to data EEPROM ;

;-------------------------------------------------------------------------;

WRITEEE BSF STATUS,RP0 ; set up EEADR and EEDATA first

CLRF EECON1

BSF EECON1,WREN ; enable write

MOVLW H'55' ; magic sequence

MOVWF EECON2

MOVLW H'AA'

MOVWF EECON2

BSF EECON1,WR

EELOOP BTFSC EECON1,WR ; wait for WR to go low

GOTO EELOOP ; not yet

BSF EECON1,WREN

BCF EECON1,EEIF ; clear the interrupt flag

BCF STATUS,RP0 ; return to page 0

RETURN

;-------------------------------------------------------------------------;

; This routine puts display registers into data EEPROM ;

;-------------------------------------------------------------------------;

PUTEE MOVF SEC,W ; put digit registers into EEprom

MOVWF EEDATA

MOVLW H'01' ; EEPROM location 1 +

ADDWF OFFSET,W ; offset from start

MOVWF EEADR

CALL WRITEEE

MOVF SEC10,W

MOVWF EEDATA

MOVLW H'02' ; EEPROM location 2 +

ADDWF OFFSET,W ; offset from start

MOVWF EEADR

CALL WRITEEE

MOVF MIN,W

MOVWF EEDATA

MOVLW H'03' ; EEPROM location 3 +

ADDWF OFFSET,W ; offset from start

MOVWF EEADR

CALL WRITEEE

MOVF MIN10,W

MOVWF EEDATA

MOVLW H'04' ; EEPROM location 4 +

ADDWF OFFSET,W ; offset from start

MOVWF EEADR

CALL WRITEEE

RETURN

;-------------------------------------------------------------------------;

; This is the main routine, the program starts here ;

;-------------------------------------------------------------------------;

MAIN CALL INIT ; set up ports etc.

;-------------------------------------------------------------------------;

; We will return to this point when alarm is shut off. ;

;-------------------------------------------------------------------------;

EE2D CALL GETEE ; put eeprom in display regs.

BCF RUNFLG, 0 ; clear run flag so no countdown

BCF ALARM, 0 ; clear alarm flag

CALL WAITSTARTUP ; wait till no switches pressed

CALL WAITSETUP

CALL WAITSELECT

;-------------------------------------------------------------------------;

; This loop checks for either pushbutton and acts accordingly ;

;-------------------------------------------------------------------------;

KEYCHKLOOP BTFSS PORTB,START_PB ; check for start pressed

GOTO STARTCNT ; yes, start count

BTFSS PORTB,SET_PB ; check for set pressed

GOTO SETDISP ; yes, set display

BTFSS PORTA,SELECT_PB ; check select pushbutton pressed

GOTO SETSELECT ; yes, select starting count

GOTO KEYCHKLOOP ; loop to catch key press

;-------------------------------------------------------------------------;

; If start key has been pressed then start countdown process, ;

; I initially released this code with only the setting of the ;

; run flag included. If you think about it you must also reset ;

; TMR0 to zero. TMR0 is free running and could have any value ;

; 0-255 when the button in pressed. Also INTCNT has to be ;

; initialized because the previous count could have been cancelled. ;

;-------------------------------------------------------------------------;

STARTCNT CALL WAITSTARTUP ; wait for release of start key

MOVLW D'244' ; reset INTCNT

MOVWF INTCNT

CLRF TMR0 ; and clear timer 0

BSF RUNFLG, 0 ; start the countdown

;-------------------------------------------------------------------------;

; Once started just loop looking for cancel or reaching 0000 ;

;-------------------------------------------------------------------------;

MAINLOOP BTFSS PORTB,START_PB ; countdown in progress, check start

GOTO EE2D ; start over again if pressed

BTFSC ALARM, 0 ; reached 0000 yet?

GOTO SOUNDALARM ; yes, turn alarm on

GOTO MAINLOOP ; no start switch, continue looping

;-------------------------------------------------------------------------;

; This code sounds the alarm and waits on start to be pressed ;

;-------------------------------------------------------------------------;

SOUNDALARM

FINALWAIT BCF PORTB,RB4 ; speaker leads set up

BSF PORTB,RB5 ; opposite polarity

MOVLW 2 ; delay 2 milliseconds

CALL NMSEC

BSF PORTB,RB4 ; flip the speaker leads

BCF PORTB,RB5

MOVLW 2 ; another 2 msec delay

CALL NMSEC

BTFSC PORTB,START_PB ; start button pressed

GOTO FINALWAIT ; not yet

CALL DLY20 ; debounce just to make sure

BTFSC PORTB,START_PB ; second look

GOTO FINALWAIT ; nah, keep waiting

BCF PORTB,RB4 ; speaker leads set to same polarity

BCF PORTB,RB5

CALL WAITSTARTUP ; now wait for the switch up

GOTO EE2D ; start all over again

;-------------------------------------------------------------------------;

; Wait for release of start button ;

;-------------------------------------------------------------------------;

WAITSTARTUP BTFSS PORTB,START_PB ; wait for release

GOTO WAITSTARTUP ; not released yet

CALL DLY20 ; debounce release

BTFSS PORTB,START_PB ; 2nd check, make sure released

GOTO WAITSTARTUP ; keep checking

RETURN

;-------------------------------------------------------------------------;

; Wait for release of set button ;

;-------------------------------------------------------------------------;

WAITSETUP BTFSS PORTB,SET_PB ; wait for release

GOTO WAITSETUP ; not yet

CALL DLY20 ; debounce release

BTFSS PORTB,SET_PB ; 2nd check, make sure released

GOTO WAITSETUP ; keep checking

RETURN

;-------------------------------------------------------------------------;

; Wait for release of select button ;

;-------------------------------------------------------------------------;

WAITSELECT BTFSS PORTA,SELECT_PB ; wait for release

GOTO WAITSELECT ; not yet

CALL DLY20 ; debounce release

BTFSS PORTA,SELECT_PB ; 2nd check, make sure released

GOTO WAITSELECT ; keep checking

RETURN

;-------------------------------------------------------------------------;

; Routine to follow sets the countdown time digit by digit ;

;-------------------------------------------------------------------------;

SETDISP CALL WAITSETUP ; wait for set key to be released

MOVLW H'0A' ; put A's in digits, (no display)

MOVWF MIN10 ; 10's of minutes

MOVWF MIN ; minutes

MOVWF SEC10 ; 10's of seconds

MOVWF SEC ; seconds

STARTMIN10 CLRF MIN10 ; 0 now in MIN10

MOREMIN10 MOVLW H'32' ; 50 delays of 20 msec

MOVWF SECNT ; into counting register

WAIT1 CALL DLY20

BTFSS PORTB,SET_PB ; set key pressed?

GOTO MINSET ; yes MIN10 now set

DECFSZ SECNT,f ; finished 1 sec delay?

GOTO WAIT1 ; continue wait

INCF MIN10,f ; every second increment 10's MIN

MOVLW H'0A' ; reached 10?

SUBWF MIN10,W

BTFSC STATUS,Z ; Z set if reached 10

GOTO STARTMIN10 ; start again with 0

GOTO MOREMIN10 ; set up another 1 sec delay

MINSET CALL WAITSETUP ; wait for release of set key

STARTMIN CLRF MIN ; 0 into MIN

MOREMIN MOVLW H'32' ; 50 delays of 20 msec

MOVWF SECNT ; into counting register

WAIT2 CALL DLY20

BTFSS PORTB,SET_PB ; set pressed?

GOTO SETSEC10 ; yes, finished with MIN

DECFSZ SECNT,f ; finished 1 sec delay?

GOTO WAIT2 ; continue wait

INCF MIN,f ; every second increment MIN

MOVLW H'0A' ; reached 10?

SUBWF MIN,W

BTFSC STATUS,Z ; Z set if reached 10

GOTO STARTMIN ; put zero in if Z set

GOTO MOREMIN ; set up another 1 sec delay

SETSEC10 CALL WAITSETUP ; wait release

STARTSEC10 CLRF SEC10 ; 0 into SEC10

MORESEC10 MOVLW H'32' ; 50 delays of 20 msec

MOVWF SECNT ; into counting register

WAIT3 CALL DLY20

BTFSS PORTB,SET_PB ; set pressed?

GOTO SETSEC ; yes quit incrementing

DECFSZ SECNT,f ; finished 1 sec delay?

GOTO WAIT3 ; continue wait

INCF SEC10,f ; every second increment 10's SEC

MOVLW H'06' ; reached 6?

SUBWF SEC10,W

BTFSC STATUS,Z ; Z set if reached 6

GOTO STARTSEC10 ; put zero in if Z set

GOTO MORESEC10 ; set up another 1 sec delay

SETSEC CALL WAITSETUP ; wait for release

STARTSEC CLRF SEC ; 0 into SEC

MORESEC MOVLW H'32' ; 50 delays of 20 msec

MOVWF SECNT ; into counting register

WAIT4 CALL DLY20

BTFSS PORTB,SET_PB ; set button pressed?

GOTO FINSET ; yes finished setting digits

DECFSZ SECNT,f ; finished 1 sec delay?

GOTO WAIT4 ; continue wait

INCF SEC,f ; every second increment SEC

MOVLW H'0A' ; reached 10?

SUBWF SEC,W

BTFSC STATUS,Z ; Z set if reached 10

GOTO STARTSEC ; put zero in if Z set

GOTO MORESEC ; set up another 1 sec delay

FINSET BCF INTCON, GIE ; disable interrupts

CALL PUTEE ; put new digits into EEPROM

BSF INTCON, GIE ; re-enable interrupts

CALL WAITSETUP ; make sure set switch up

GOTO KEYCHKLOOP ; start checking buttons again

;-------------------------------------------------------------------------;

; Selects starting count by changing EEPROM location 0 ;

;-------------------------------------------------------------------------;

SETSELECT MOVLW D'4' ; offset up 4

ADDWF OFFSET,F ; next offset position

MOVLW D'60' ; reached 16th yet?

SUBWF OFFSET,W ; will give zero if yes

BTFSC STATUS,Z ; skip if not 64

CLRF OFFSET ; reset position to zero

MOVLW 0 ; EEPROM location

MOVWF EEADR ; set up address

MOVF OFFSET,W ; offset # into W

MOVWF EEDATA ; set up data

BCF INTCON,GIE ; clear GIE, disable interrupts

CALL WRITEEE ; save # in location 0

BSF INTCON,GIE ; re-enable interrupts

CALL GETEE ; get new start count into display

CALL WAITSELECT ; make sure select switch is up

GOTO KEYCHKLOOP ; start checking buttons again

;-------------------------------------------------------------------------;

; The following are various delay routines based on instruction length. ;

; The instruction length is assumed to be 1 microsecond (4Mhz crystal). ;

;-------------------------------------------------------------------------;

DLY20 MOVLW 20 ; delay for 20 milliseconds

;*** N millisecond delay routine ***

NMSEC MOVWF CNTMSEC ; delay for N (in W) milliseconds

MSECLOOP MOVLW D'248' ; load takes 1 microsec

CALL MICRO4 ; by itself CALL takes ...

; 2 + 247 X 4 + 3 + 2 = 995

NOP ; 1 more microsec

DECFSZ CNTMSEC,f ; 1 when skip not taken, else 2

GOTO MSECLOOP ; 2 here: total 1000 per msecloop

RETURN ; final time through takes 999 to here

; overhead in and out ignored

;*** 1 millisecond delay routine ***

ONEMSEC MOVLW D'249' ; 1 microsec for load W

; loops below take 248 X 4 + 3 = 995

MICRO4 ADDLW H'FF' ; subtract 1 from 'W'

BTFSS STATUS,Z ; skip when you reach zero

GOTO MICRO4 ; loops takes 4 microsec, 3 for last

RETURN ; takes 2 microsec

; call + load W + loops + return =

; 2 + 1 + 995 + 2 = 1000 microsec

;-------------------------------------------------------------------------;

; Here we set up the initial values of the digits in data EEPROM ;

;-------------------------------------------------------------------------;

ORG H'2100'

DE 0, 1, 0, 0, 0 ; 1st starting #

DE 2, 0, 0, 0 ; 2nd starting #

DE 3, 0, 0, 0 ; 3rd starting #

DE 4, 0, 0, 0 ; 4th starting #

DE 5, 0, 0, 0 ; 5th starting #

DE 6, 0, 0, 0 ; 6th starting #

DE 7, 0, 0, 0 ; 7th starting #

DE 8, 0, 0, 0 ; 8th starting #

DE 9, 0, 0, 0 ; 9th starting #

DE 0, 1, 0, 0 ; 10th starting #

DE 1, 1, 0, 0 ; 11th starting #

DE 2, 1, 0, 0 ; 12th starting #

DE 3, 1, 0, 0 ; 13th starting #

DE 4, 1, 0, 0 ; 14th starting #

DE 5, 1, 0, 0 ; 15th starting #

END

Link al commento
Condividi su altri siti


Consiglio generale.

Un progetto, anche minimo come questo, è composto da più funzioni di base che si uniscono per formare l'insieme.

Comincia con il suddividere il progetto software in più finzioni come, ad esempio, gestione dei visualizzatori, gestione del timer del micro con relativo conteggio, introduzione dei dati, comparatore e gestione delle uscite.

Ognuna di queste funzioni può essere verificata e provata a se stante. Una volta messe a punto le singole funzioni cominci ad integrare l'insieme aggiungendo una funzione alla volta.

Così è molto più semplice verificare il software.

Ricorda che la progettazione è costituita, al 20% di competenza ed allo 80% di pazienza. smile.gif

Link al commento
Condividi su altri siti

Crea un account o accedi per commentare

Devi essere un utente per poter lasciare un commento

Crea un account

Registrati per un nuovo account nella nostra comunità. è facile!

Registra un nuovo account

Accedi

Hai già un account? Accedi qui.

Accedi ora
×
×
  • Crea nuovo/a...