;Controlla il brandeggio della webcam sul ponte R0 list P=PIC16F84A , R=DEC #INCLUDE P16F84A.inc __FUSES _CP_OFF&_WDT_ON&_XT_OSC CBLOCK 0ch Timer1 ;Subcontatore per timer Timer2 ;Subcontatore per timer Timer3 ;Contatore per timer Time_set ;valore programmabile di conteggio tempo StepNo ;numero di step attuale Posizione ;posizione attuale del motore Bit1 ;memorie a bit n.1 w_temp ;memoria temporanea per Work in ISR stat_temp ;memoria temporanea per status in ISR Rxtmp ;buffer di ricezione seriale Rxcnt ;contatore numero di bit ricevuti da seriale Rxtime ;contatempo per ricezione seriale ENDC #define Rxed Bit1,0 ;memoria dato ricevuto dalla seriale Timer2Preset=10 ;valore presettato di subtimer2 ;parametri motore SpeedStandard=10 ;valore iniziale per velocita' rotazione motore LimitePosizione=96 ;Numero massimo step rotazione motore ;inizio programma dopo un reset org 0 goto START org 4 goto Isr START ;inizializzazione sistema e variabili clrf TMR0 ;come da datasheet azzerial il prescaler prima di assegnarlo al watchdog clrwdt bsf STATUS,RP0 movlw 01110001b ;0=uscita 1=ingresso movwf TRISB movlw 11110000b movwf TRISA bsf OPTION_REG,PSA ;assegna il prescaler al watchdog bsf OPTION_REG,PS0 ;e settalo al massimo valore bsf OPTION_REG,PS1 bsf OPTION_REG,PS1 bcf STATUS,RP0 ;torna in banco zero movlw SpeedStandard ;valore iniziale di Time_set movwf Time_set movlw 1 ;inizializza posizione stepper a 1 movwf StepNo movwf Posizione ;setta contatore posizione motore a 1 che è il minimo bcf Rxed ;azzera flag ricezione dati da seriale ;azzera l'asse btfsc PORTB,6 ;se siamo già sul finecorsa, muovi subito in negativo fino ad uscirne goto Zero_2 Zero_1 call StepNeg call Delay btfss PORTB,6 goto Zero_1 ;muove in negativo fino a leggere il finecorsa di zero Zero_2 call StepNeg call Delay btfsc PORTB,6 goto Zero_2 ;fa un passo in piu per sicurezza call StepNeg call Delay ;ora muove in positivo fino ad uscirne Zero_3 call StepPos call Delay btfss PORTB,6 goto Zero_3 clrf PORTA ;spegne il motore per evitarne il surriscaldamento ;abilita gli interrupt per ricezione seriale PORTB,0 bsf STATUS,RP0 bsf INTCON,INTE ;abilita trap PORTB,0 bcf OPTION_REG,INTEDG ;interrupt sul fronte di discesa bsf INTCON,GIE ;abilita tutti gli interrupt bcf STATUS,RP0 ;loop principale programma Loop btfsc Rxed ;verifica la ricezione di un dato call RxData call Button ;aggiorna il valore del timer in base allo stato dei pulsanti bsf PORTB,2 call Delay bcf PORTB,2 call Delay clrwdt goto Loop ;ricomincia da capo ;************************************************ ;RxData: alla ricezione di un valore di posizione, vi muove il motore ;************************************************ RxData movf Rxtmp,w ;preleva il valore di posizione da raggiungere subwf Posizione,w btfsc STATUS,Z ;controlla se uguale goto RxDataEnd btfss STATUS,C goto RxDataP ;posizione target minore della attuale, muoviamo in negativo RxData1 decfsz Posizione,f ;decrementa la posizione attuale, e se diventa zero... goto RxData2 movlw 1 movwf Posizione ;...ricaricalo con uno ed esci goto RxDataEnd RxData2 call StepNeg call Delay movf Posizione,w subwf Rxtmp,w btfss STATUS,Z goto RxData1 goto RxDataEnd RxDataP ;posizione target maggiore della attuale, muoviamo in positivo RxData5 incf Posizione,f movlw LimitePosizione subwf Posizione,w btfss STATUS,C goto RxData6 movlw LimitePosizione movwf Posizione goto RxDataEnd RxData6 call StepPos call Delay movf Posizione,w subwf Rxtmp,w btfss STATUS,Z goto RxData5 RxDataEnd bcf Rxed clrf PORTA ;spegne il motore return ;************************************************ ;muove il motore di un passo in direzione positiva ;************************************************ StepPos incf StepNo,f ;incrementa contatore posizione stepper movlw 9 ;il range deve essere 1-8 subwf StepNo,w ;sottrae w a StepNo ma NON altera StepNo stesso !!! btfss STATUS,Z ;se e' diventato zero, allora StepNo e' diventato 9 goto StepP1 movlw 1 ;quindi lo dobbiamo reinizializzare ad 1 movwf StepNo StepP1 movf StepNo,w ;preleva step attuale call Tabella ;converti il numero di passo in valore per PORTA movwf PORTA ;emetti dato clrwdt return ;************************************************ ;muove il motore di un passo in direzione negativa ;************************************************ StepNeg decfsz StepNo,f ;decrementa contatore posizione stepper... goto StepN1 ;...se diventato zero, lo... movlw 8 ;...reinizializza ad 1 movwf StepNo StepN1 movf StepNo,w ;preleva step attuale call Tabella ;converti il numero di passo in valore per PORTA movwf PORTA ;emetti dato clrwdt return ;************************************************ ;tabella posizioni stepper ;************************************************ Tabella addwf PCL,f ;W deve contenere il puntatore alla tabella nop ;il valore zero non lo usiamo retlw 2 retlw 6 retlw 4 retlw 5 retlw 1 retlw 9 retlw 8 retlw 10 ;************************************************ ;subroutine Delay. Ritarda l'esecuzione di un valore programmabile da Time_set ;************************************************ Delay clrf Timer1 ;azzera i timer movlw Timer2Preset ;presetta invece timer2 ad un valore prefissato movwf Timer2 movf Time_set,w ;preleva il settaggio di tempo movwf Timer3 D1 nop nop decfsz Timer1,f goto D1 decfsz Timer2,f goto D1 movlw Timer2Preset ;dato che non ricomincia da zero, timer2 va' ogni volta ricaricato movwf Timer2 decfsz Timer3,f goto D1 return ;************************************************ ;subroutine Button , legge lo stato dei pulsanti e modifica il valore di Time_set ;************************************************ Button ;pulsante 1: incrementa timer btfsc PORTB,4 ;leggi lo stato del pulsante 1 incf Time_set,f ;se premuto incrementa il valore del settaggio tempo ;pulsante 2: decrementa timer btfss PORTB,5 ;controlla ora il pulsante di decremento goto Butt_end ;esce se NON premuto decf Time_set,f ;decrementa il timer btfss STATUS,Z ;controlla se diventato zero goto Butt_end ;esce se non diventato zero movlw 1 ;ricarica il timer con il valore minimo movwf Time_set Butt_end return ;esce dalla subroutine ;************************************************ ;Rx4800: dall'interrupt riceve w su linea seriale ;4800 baud 8n1 ;NB: a 4800 baud 1 bit dura 208 microsecs. ;************************************************ Isr movwf w_temp ;salva W movf STATUS,w movwf stat_temp ;salva STATUS bcf STATUS,RP0 ;banco 0 bsf PORTB,3 ;accende il led di debug movlw 10 ;1/4 tempo call _TEMPO btfsc PORTB,0 ;controlla che sia ancora a 0 !! goto IsrEnd ;termina se spike... movlw 11 call _TEMPO btfsc PORTB,0 ;controlla ancora che sia a 0 !!! goto IsrEnd ;esci se spike... ;se stiamo proseguendo, allora e' una transizione valida !!! clrf Rxtmp ;azzera buffer movlw 8 ;numero bit da ricevere movwf Rxcnt ;in puntatore movlw 49 ;salta al centro bit successivo call _TEMPO _EMT1 btfsc PORTB,0 ;guarda ingresso goto _Emt2 bcf STATUS,C ;se e' 0, resetta carry goto _Emt3 _Emt2 bsf STATUS,C ;se e' 1 setta carry nop ;per rendere uguali i cicli _Emt3 rrf Rxtmp,f ;ruota a destra dato con carry movlw 48 ;salta al centro bit successivo call _TEMPO decfsz Rxcnt,f ;decrementa contatore goto _EMT1 ;reitera fine a 8 bit trasmessi ;in Rxtmp abbiamo il dato ricevuto, bsf Rxed IsrEnd bcf PORTB,3 ;spegne il led di debug bsf STATUS,RP0 bcf INTCON,INTF ;azzera flag interrupt pin esterno bcf STATUS,RP0 movf stat_temp,w ;salva STATUS movwf STATUS movf w_temp,w ;salva W retfie ;routine di delay per ricezione seriale ;perde 4 cicli/valorepassato + 3 ;a 4 Mhz 1 cliclo e' 1 microsec. _TEMPO movwf Rxtime ;metti in file buffer che useremo per decrementare _Tempo1 clrwdt decfsz Rxtime,f goto _Tempo1 return end