Eduardo Cassisi Inserito: 13 gennaio 2014 Segnala Share Inserito: 13 gennaio 2014 Salve, a tutti sono nuovo del forum è la prima volta che posto qualcosa in quanto avrei bisogno di un grosso aiuto da parte vostra, in quanto è un esame il 17 di questo mese e sono agli sgoccioli. Dovrei scrivere un programma in assembler per il pic 16f887 ma non so dove mettere le mani. Il programma da scrivere è il seguente : Si realizzi un programma che conti quante volte l utente preme un pulsante,terminando il conteggio quanto un time-out di 1 s trascorre senza che sia premuto il tasto,quindi emetta brevi suoni con il buzzer, con n pari al numero di pressioni di contatto. Il problema è che il buzzer suona di continuo, premo il reset e premo il pulsante e suona tante volte quante volte ho premuto il tasto, però se non lo premo più suona continua a suonaredi continuo...come faccioa risolverlo? Spero in un vostro aiuto Grazie Metto in allegato il codice in assembly list p=16f887 ; direttiva che definisce il tipo di processore #include <P16F887.INC> ; file che contiene le definizioni dei simboli ;****************************************** ; ******CONFIGURATION BIT******** __CONFIG _CONFIG1, _INTRC_OSC_NOCLKOUT & _CP_OFF & _WDT_OFF & _BOR_OFF & _PWRTE_OFF & _LVP_OFF & _DEBUG_OFF & _CPD_OFF ;****************************************** ; ******** DEFINIZIONE COSTANTI********* ; Costanti con cui settare il contatore del timer per contare un determinato intervallo di tempo. tmr_50ms EQU (.259 - .195) ;********************************************************************** ; *** Definizione variabili *** ; La direttiva UDATA_SHR (uninitialized data shared) dichiara una sezione di dati ; da allocare in RAM, e precisamente nella sezione di RAM comune a tutti ; i banchi, in modo da poter accedere ai dati indipendentemente dal banco ; impostato. udata_shr counter RES 1 ; riserva un byte di memoria associato alla label counter (= contatore) oscil RES 1 ; BYTE PER FAR OSCILLARE IL BUZZER ;********************************************************************** ; *** Vettore di reset *** ; Il vettore di reset è l'istruzione che viene eseguita per prima ; dopo un reset del microcontrollore. ; La direttiva CODE dichiara una sezione di codice da allocare in ROM. ; Viene specificato esplicitamente l'indirizzo 0000, in quanto il ; vettore di reset deve trovarsi in questa posizione (codice non rilocabile). ; La label non è necessaria, ma è utilizzata per chiarezza del codice. RST_VECTOR CODE 0x0000 pagesel start ; imposta la pagina della memoria di programma in cui si trova ;l'indirizzo della label start goto start ; salta all'indirizzo indicato dalla label start ;********************************************************************** ; *** Programma principale *** ; La direttiva CODE dichiara una sezione di codice da allocare in ROM. ; Non viene specificato un indirizzo esplicito, il linker successivamente ; assegnerà un indirizzo assoluto di inizio per la sezione (codice rilocabile) MAIN CODE start ; N.B: l'assembler non accetta una label sulla ;stessa riga di una direttiva ; inizializzazione hardware pagesel INIT_HW ; direttiva che imposta la pagina della memoria ;di programma in cui risiede la subroutine INIT_HW call INIT_HW ; chiamata alla subroutine indicata dalla label INIT_HW banksel PORTD clrf PORTD clrf counter ; loop principale main_loop ; N.B: l'assembler non accetta una label su una direttiva movlw 0x80 banksel TMR1H movwf TMR1H banksel PIR1 bcf PIR1,TMR1IF ; loop di attesa pressione pulsante banksel PORTB ; banco di PORTB wait_press clrwdt ; azzera timer watchdog per evitare reset btfss PORTB,0 ; se il bit 0 della porta B è = 0 (pulsante premuto) salta l'istruzione seguente goto premuto ; ripete il loop ; pulsante premuto: debounce e inizio conteggio di 1 s per determinare pressione successiva banksel PIR1 btfsc PIR1,TMR1IF goto buzzer goto wait_press ; periodo timer scaduto (1s) premuto pagesel DELAY movlw tmr_50ms call DELAY ; *** provare a commentare la chiamata a subroutine DELAY per evitare il debouncing *** ; loop di attesa rilascio pulsante banksel PORTB ; banco di PORTB asp_press clrwdt ; azzera timer watchdog per evitare reset btfss PORTB,0 ; se il bit 0 della porta B è = 1 (pulsante rilasciato) salta l'istruzione seguente goto asp_press ; ripete il loop ; pulsante rilasciato: attesa debouncing e ripetizione loop principale pagesel DELAY ; imposta la pagina della memoria di programma in cui risiede la subroutine DELAY ; carica in W la costante (precedentemente definita) per la misura di 10 ms movlw tmr_50ms call DELAY ; *** provare a commentare la chiamata a subroutine DELAY per evitare il debouncing *** incfsz counter,f ; incrementa counter goto main_loop buzzer banksel PORTD bsf PORTD,0 loop_buzzer call beep movlw tmr_50ms call DELAY decfsz counter goto loop_buzzer goto main_loop beep movlw .200 movwf oscil beep1 movlw B'00000100' ; carico il valore binario in W banksel PORTC xorwf PORTC,f ; inversione del bit movlw .253 call DELAY decfsz oscil,f goto beep1 return ; *** Subroutine DELAY: attesa di un tempo selezionabile *** ; nel registro W viene passato il valore da impostare come contatore iniziale del timer. DELAY ; Utilizzo del timer in polling: settare il contatore al valore iniziale voluto, ; azzerare il flag e attendere tramite un loop che il flag venga settato di nuovo. banksel TMR0 movwf TMR0 ; copia W in TMR0 (contatore del timer) bcf INTCON,T0IF ; azzera il flag di overflow di TMR0 wait_delay clrwdt ; azzera timer watchdog per evitare reset btfss INTCON,T0IF ; se il flag di overflow del timer è = 1, salta l'istruzione seguente goto wait_delay ; ripeti il loop di attesa return ; uscita da subroutine e ritorno al punto del codice in cui era stata chiamata INIT_HW ; registro OPTION_REG: ; - pull-up porta B abilitati. ; - TMR0 incrementato da clock interno (1 MHz) ; - prescaler assegnato a TMR0 ; - valore prescaler 1:256 (clock TMR0 = 3.90625 kHz) ; Le impostazioni precedenti determinano per TMR0 i seguenti valori: ; - periodo di un singolo incremento (tick) = 256 us ; - periodo totale (da 00 a FF) = 65.536 ms banksel OPTION_REG ; banco di OPTION_REG movlw B'00000111' ; carica costante binaria 00000110 in W movwf OPTION_REG ; copia W (11000110b) in OPTION_REG ; registro INTCON: ; - tutti gli interrupt disabilitati clrf INTCON ; INTCON = 0 ; Porte I/O: ; - porte A,C,B,E settate come input digitali per tutti i pin, ; tranne RA0 settato come input analogico ; - porta D: pin 0..3 settati come output (LED), pin 4..7 come input banksel TRISA ; banco di TRISA, stesso banco anche per gli altri registri TRISx movlw 0xFF ; carica costante FF in W movwf TRISA ; copia W (FF) in TRISA movwf TRISB ; copia W (FF) in TRISB movwf TRISE ; copia W (FF) in TRISE movlw 0xF0 ; carica costante F0 in W movwf TRISD ; copia W (F0) in TRISD movlw B'11111011' ; movwf TRISC ; ; Di default, tutti i pin connessi all'ADC sono settati come input analogici, ; impedendone l'uso come I/O digitali. L'impostazione seguente rende I/O digitali ; i pin RB0..RB3 banksel ANSELH ; banco di ANSELH clrf ANSELH ; AN8..AN13 disattivati movlw B'00001011' banksel T1CON movwf T1CON return end Link al commento Condividi su altri siti More sharing options...
Messaggi consigliati
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 accountAccedi
Hai già un account? Accedi qui.
Accedi ora