Delay/Block debouncer

Questo articolo della Rubrica Firmware Reload descrive come implementare via software un blocco che effettua un ritardo su PIC10F322 e utilizzarlo come anti-rimbalzo per interruttori.

INTRODUZIONE

L’obiettivo è realizzare un blocco di attesa che accetti valori tra 2μs e 193μs. L’intento è quello di sfruttarlo come discriminatore del rumore o come anti-rimbalzo per un interruttore. Utilizzato come ritardo, può essere usato dall’applicazione per effettuare operazioni sui segnali a basso livello ad un determinato intervallo, utilizzato per il “debouncing” invece può agire su un interruttore meccanico per ripulire il segnale o alimentare qualsiasi altra circuiteria elettronica. Per la realizzazione si utilizza la periferica CLC (Configurable Logic Cell) per realizzare una commutazione veloce in uscita, se ciò non fosse indispensabile si possono utilizzare solamente delle porte logiche, in tal caso più cicli di istruzioni devono essere elaborati prima che l’uscita commuti in funzione dell’ingresso. Utilizzando il CLC il segnale viene pilotato direttamente e ha solo il ritardo di propagazione tra il segnale di entrata e quello di uscita. Per velocizzare ulteriormente e ottenere la massima performance, il codice viene scritto in assembly. Il codice viene scritto in-line, senza subroutine per ottimizzare le performance durante i salti di codice. Il codice occupa solo 43 locazioni sulle 512 disponibili di flash e solo un byte di RAM. L’applicazione è stata sviluppata sulla scheda demo PIC10F322 (AC103011). Le versioni degli strumenti utilizzati sono le seguenti: MPASMWIN.exe v5.45, mplink.exe v4.43, mplib.exe v4.43.

GENERAZIONE DEL RITARDO

Come detto, il ritardo può essere impostato tra 2μs e 193μs per incrementi discreti di 750ns (in base al clock interno a 16MHz e alle 3 istruzioni necessarie per eseguire un loop di attesa). Ovviamente, la dimensione massima del ritardo può essere aumentata, o riducendo la frequenza di clock oppure aumentando il numero di cicli del loop di ritardo. I ritardi sono sincronizzati sui fronti di salita o di discesa del segnale in esame, tramite due #define si possono abilitare:

;; 2 lines below enable rising
and falling
edge delays
#defi ne RISING_EDGE_DELAY
#defi ne FALLING_EDGE_DELAY
;; specify length of falling
and rising edge
below
RISE_EDGE_DELAY equ 0x01
FALL_EDGE_DELAY equ 0x01
;#defi ne MS_DELAY

o disabilitare, due ulteriori righe consentono di definire il valore del ritardo, che verrà calcolato in base alla definizione o meno di MS_DELAY, nel caso sia definita, il ritardo viene considerato in millisecondi, oppure in alternativa se la #define è commentata in step da 750ns. Se la situazione è quella del codice riportato in precedenza, allora il valore di ritardo si ottiene come: delay = 2μs + (delay_value x 750ns). Attivando il ritardo su entrambi i fronti, la situazione è quella di Figura 1.

Figura 1: Misura dei ritardi sui fronti di salita e di discesa.

Figura 1: Misura dei ritardi sui fronti di salita e di discesa

Il segnale di uscita viene sfasato rispetto al segnale d’ingresso, a seconda dei ritardi impostati per i due fronti. Se analizziamo un singolo fronte, quello di discesa, dei segnali in ingresso e in uscita, possiamo ottenere il ritardo di propagazione, approssimativamente intorno ai 50ns, vedi Figura 2.

Figura 2: Ritardo di propagazione.

Figura 2: Ritardo di propagazione

REALIZZAZIONE DEL RITARDO CON CLC

In Figura 3 è possibile vedere lo schema a blocchi del blocco di ritardo realizzato utilizzando la periferica CLC.

Figura 3: Schema a blocchi.

Figura 3: Schema a blocchi

Se il blocco viene configurato per non generare un ritardo, un sotto-blocco dedicato di pass-through realizzato tramite la periferica CLC, permette di portare il segnale d’ingresso direttamene all’uscita. In alternativa, il segnale del mix di uscita viene preso dal canale alternativo dove il PIC Device Core genera l’attesa. Per realizzare il pass-through l’unico blocco CLC disponibile nel PIC10F322 viene configurato come in Figura 4.

Figura 4: Configurazione del CLC.

Figura 4: Configurazione del CLC

 

Figura 5: Configurazione del CLC con uscita invertente.

Figura 5: Configurazione del CLC con uscita invertente

Viene utilizzata la TAB logica dedicata all’AND. Come si può vedere dalla Figura 4 nella prima porta OR abbiamo il segnale d’ingresso che è l’unica entrata del GATE1. Le restanti porte logiche OR (GATE2, GATE3 e GATE4) non collegate sono invertite in uscita in maniera che presentino un livello logico alto all’ingresso della porta logica AND. Infine, il segnale risultante va in uscita dopo essere stato bufferizzato con un buffer non invertente. Se ci fosse l’esigenza di invertire il segnale in uscita, sarebbe sufficiente far diventare il buffer invertente come in Figura 9, per ottenere un segnale in uscita speculare a quello in ingresso (vedi Figura 6).

Figura 6: Ingresso e uscita senza ritardo ma con inversione.

Figura 6: Ingresso e uscita senza ritardo ma con inversione

IL SOFTWARE

Il software che realizza il blocco di ritardo può essere scaricato dal sito Microchip dal link dedicato [2]. Di seguito riportiamo il file DELAY.ASM proposto da Microchip per far vedere come è realizzato il loop di ritardo.

;/********************************************************************
;* FileName:delay.asm
;* Dependencies:
;* Processor:PIC10F322
;* Hardware:
;* Compiler:MPASM 5.45 or later
;* Company:Microchip Technology, Inc.
;*
;* Copyright © 2007-2012 Microchip Technology Inc. All rights r eserved.
;*
;*/
#include <p10f322.inc>
list p=p10f322
;; Defi ne parameters here
;; 2 lines below enable rising and falling edge delays
#defi ne RISING_EDGE_DELAY
#defi ne FALLING_EDGE_DELAY
;; specify length of falling and rising edge below
RISE_EDGE_DELAY equ 0x05
FALL_EDGE_DELAY equ 0x04
#defi ne MS_DELAY
;; Confi guration Fuses
__confi g _FOSC_INTOSC & _BOREN_OFF & _WDTE_OFF & _PWRTE_OFF & _MCLRE_O FF & _CP_OFF
& _WRT_OFF
;; pin-out
;; 1 - RA0 - pin available for use as scope trigger.
;; 2 - VSS
;; 3 - RA1 - Data Out / CLC1
;; 4 - RA2 - Data In / CLC1IN2
;; 5 - VDD
;; 6 - MCLR
#defi ne input_signal PORTA,2
#defi ne output_signal LATA,1
; single RAM location used for countdown_timer
countdown_timer equ 0x51
;; additional RAM location required if millisecond delay is ena bled.
#ifdef MS_DELAY
ms_timer equ 0x52 ; delay counter for specifying time delay in milliseconds.
#endif
org 0x00
start
bcf TRISA,0 ; RA0 output - this can be used as a scope trigger.
bcf TRISA,1 ; RA1 output
clrf ANSELA ; all pins are digital.
movlw 0x70
movwf OSCCON ; 16 MHz clock - change this value for longer dela ytimes
; and to lower current consumption.
;; CLC is set up here with the following include:
#include “CLC_pass_through.inc” ; Confi gure CLC for falling edge.
; bsf CLC1POL,LC1POL; option to invert signal through CLC block .
;; input level test
btfss input_signal ; What is the current value of my input sign al?
goto signal_low ; Low.
goto signal_high ; High.
;; ===== This is the start of my main loop
signal_high ; Signal just transitioned high.
#ifdef RISING_EDGE_DELAY ; If I have rising edge delay,
movlw RISE_EDGE_DELAY
movwf countdown_timer ; load countdown timer with rising edge d elay.
rising_edge_delay_loop ; insert ‘nop’s’ below this line to incr ease delay.
#ifdef MS_DELAY ; option for millisecond delay
call millisecond_delay
#endif
#ifndef MS_DELAY
decfsz countdown_timer,1 ; Has countdown timer expired?
goto rising_edge_delay_loop; no, continue delay loop
#endif
bsf output_signal ; and drive pin high.
#endif
#ifdef FALLING_EDGE_DELAY
bsf output_signal ; drive latch high
bcf CLC1CON,LC1OE ; PORT -> pin
#endif
#ifndef FALLING_EDGE_DELAY
bsf CLC1CON,LC1OE ; CLC -> pin
#endif
wait_for_falling_edge
btfsc input_signal
goto wait_for_falling_edge
signal_low ; Signal just transitioned low.
#ifdef FALLING_EDGE_DELAY
movlw FALL_EDGE_DELAY
movwf countdown_timer ; load countdown timer with falling edge delay.
#endif
falling_edge_delay_loop ; insert ‘nop’s’ below this line to inc rease delay.
#ifdef MS_DELAY ; option for millisecond delay
call millisecond_delay
#endif
#ifndef MS_DELAY
decfsz countdown_timer,1 ; Has countdown timer expired?
goto falling_edge_delay_loop ; no, continue delay loop
#endif
bcf output_signal ; and drive pin low.
#ifdef RISING_EDGE_DELAY
bcf output_signal ; drive latch low
bcf CLC1CON,LC1OE ; PORT -> pin
#endif
#ifndef RISING_EDGE_DELAY
bsf CLC1CON,LC1OE ; CLC -> pin
#endif
wait_for_rising_edge
btfss input_signal
goto wait_for_rising_edge
goto signal_high
;;;;;; end of main loop
#ifdef MS_DELAY
millisecond_delay
movlw .250 ; 250 loops x 16
cycles per loop = 4000 Tcy = 1 ms
movwf ms_timer
millisecond_delay_loop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
decfsz ms_timer ; has countdown
timer reached 0?
goto millisecond_delay_loop; No.
continue looping
decfsz countdown_timer ; Do I need
to have another millisecond delay?
goto millisecond_delay ; Yes.
retlw 0x00 ; No - done.
#endif
end

Scarica subito una copia gratis

Scrivi un commento

Seguici anche sul tuo Social Network preferito!

Send this to a friend