Vai al contenuto
PLC Forum


Suono Buzzer


Eduardo Cassisi

Messaggi consigliati

Eduardo Cassisi

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

user_offline.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...