Programació en pic-as del PIC 16F690

Referència Trucs Perifèrics   Recursos CITCEA
Tutorial Exemples Projectes   Inici

Diversos polsadors connectats a una sola entrada

En alguns casos ens cal fer servir uns quants polsadors (o interruptors) però ens preocupa ocupar moltes entrades amb ells. Una solució al problema és llegir tots els polsadors des d'una entrada analògica. Hi ha diverses formes per a fer-ho però la que presentem aquí ens permet connectar fins a cinc polsadors i de forma que podem detectar si es premen dos o més polsadors al mateix temps. El circuit que farem servir es el de la figura següent:

Esquema de connexió

Mentre no hi ha cap polsador premut, atès que no pot circular corrent, l'entrada RA2 està connectada a 0 V a través de la resistència d'1 kΩ; per tant, llegirem aproximadament un valor zero.

Si premem el polsador P1 tindrem dues resistències en sèrie i, per tant, el corrent que circularà tindrà aproximadament el següent valor:

Equació

A l'entrada analògica hi haurà una tensió que correspon al producte de la resistència comuna pel corrent que hi passa:

Equació

Fent la conversió, podem saber el valor aproximat que veurem a la sortida del conversor analògic-digital:

Equació

La següent taula ens indica els valors corresponents als cinc polsadors. Atès que és més fàcil comparar amb només vuit bits, la darrera columna ens mostra els valors que obtindríem a ADRESH si configurem el conversor amb el resultat justificat per l'esquerra.

Polsador Resistència Tensió Lectura ADRESH
P1 220 Ω 4,1 V 839 210
P2 390 Ω 3,6 V 737 184
P3 680 Ω 3,0 V 610 153
P4 2200 Ω 1,6 V 320 80
P5 4700 Ω 0,9 V 180 45

Les lectures no seran exactament aquests valors ja que depenen de la tensió d'alimentació i de la precisió de les resistències que fem servir. Per això és recomanable fer correspondre un rang de valors a cada polsador. En el nostre cas, hem posat que la lectura estigui entre deu unitats per sota i deu unitats per sobre del valor de la taula.

Si premem dos polsadors a la vegada, per exemple P1 i P3, tindrem les dues resistències en paral·lel:

Equació

que dona una tensió de 4,3 V i una lectura de 878.

Si volem detectar la pulsació de més d'un polsador, haurem de fer servir marges de comparació força estrets. En aquest cas és recomanable veure quines són les lectures reals a l'hora de definir els marges.

La següent funció llegeix els polsadors i retorna en una variable el bit que correspon al polsador actiu. No s'ha contemplat que es puguin prémer dos polsadors al mateix temps.

El programa de l'exemple PA permet provar-ho.

Polsador EQU 0x20  ; Variable que conté un bit per a cada polsador per saber si està premut	
...
;
; Funció que llegeix els polsadors
;
Llegir:
  clrf Polsador  ; Si aquest valor no es canvia és que no hi ha cap polsador premut
  nop  ; espera un microsegon
  nop  ; espera un microsegon
  nop  ; espera un microsegon
  nop  ; espera un microsegon
  nop  ; espera un microsegon
  bsf GO_DONE  ; Inicia la conversió
  btfsc GO_DONE  ; Quan el bit sigui 0 la conversió haurà acabat
  goto $-1  ; repetim la línia fins que deixi de ser 0
            ; Comparació P1
  movlw 220  ; Límit superior de P1
  subwf ADRESH,w  ; W = ADRESH - W
  btfsc CARRY  ; C = 1 si ADRESH >= W
  goto NoEsP1  ; ADRESH >= W
  movlw 200  ; Límit inferior de P1
  subwf ADRESH,w  ; W = ADRESH - W
  btfss CARRY  ; C = 1 si ADRESH >= W
  goto NoEsP1  ; ADRESH < W
  movlw 00000001B  ; Polsador P1
  movwf Polsador  ; Ho copia a Polsador
  goto NoEsP5
NoEsP1:  ; Comparació P2
  movlw 194  ; Límit superior de P2
  subwf ADRESH,w  ; W = ADRESH - W
  btfsc CARRY  ; C = 1 si ADRESH >= W
  goto NoEsP2  ; ADRESH >= W
  movlw 174  ; Límit inferior de P2
  subwf ADRESH,w  ; W = ADRESH - W
  btfss CARRY  ; C = 1 si ADRESH >= W
  goto NoEsP2  ; ADRESH < W
  movlw 00000010B  ; Polsador P2
  movwf Polsador  ; Ho copia a Polsador
  goto NoEsP5
NoEsP2:  ; Comparació P3
  movlw 163  ; Límit superior de P3
  subwf ADRESH,w  ; W = ADRESH - W
  btfsc CARRY  ; C = 1 si ADRESH >= W
  goto NoEsP3  ; ADRESH >= W
  movlw 143  ; Límit inferior de P3
  subwf ADRESH,w  ; W = ADRESH - W
  btfss CARRY  ; C = 1 si ADRESH >= W
  goto NoEsP3  ; ADRESH < W
  movlw 00000100B  ; Polsador P3
  movwf Polsador  ; Ho copia a Polsador
  goto NoEsP5
NoEsP3:  ; Comparació P4
  movlw 90  ; Límit superior de P4
  subwf ADRESH,w  ; W = ADRESH - W
  btfsc CARRY  ; C = 1 si ADRESH >= W
  goto NoEsP4  ; ADRESH >= W
  movlw 70  ; Límit inferior de P4
  subwf ADRESH,w  ; W = ADRESH - W
  btfss CARRY  ; C = 1 si ADRESH >= W
  goto NoEsP4  ; ADRESH < W
  movlw 00001000B  ; Polsador P4
  movwf Polsador  ; Ho copia a Polsador
  goto NoEsP5
NoEsP4:  ; Comparació P5
  movlw 55  ; Límit superior de P5
  subwf ADRESH,w  ; W = ADRESH - W
  btfsc CARRY  ; C = 1 si ADRESH >= W
  goto NoEsP5  ; ADRESH >= W
  movlw 35  ; Límit inferior de P5
  subwf ADRESH,w  ; W = ADRESH - W
  btfss CARRY  ; C = 1 si ADRESH >= W
  goto NoEsP5  ; ADRESH < W
  movlw 00010000B  ; Polsador P5
  movwf Polsador  ; Ho copia a Polsador
NoEsP5:
  return

El següent programa ens permet mostrar a la pantalla els valors llegits a l'entrada analògica. Així, podem veure quin valor correspon a cada polsador i ajustar els rangs a les resistències concretes de la nostra placa i a la tensió d'alimentació que estem fent servir.

PROCESSOR 16F690
#include <xc.inc>
config FOSC = INTRCIO, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF
config CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF
Compta EQU 0x20  ; Comptador d'iteracions
D1 EQU 0x21  ; Variable unitats	
D2 EQU 0x22  ; Variable desenes	
D3 EQU 0x23  ; Variable centenes
Caracter EQU 0x24  ; Caràcter o codi a enviar
Retard1 EQU 0x25  ; Variables de retard	
Retard2 EQU 0x26
Retard3 EQU 0x27
PSECT code, class=CODE, delta=2, abs  ; A l'inici de la memòria
main:
  bsf RP0  ; Tria el banc 1
  movlw 0xFF  ; Posa l'acumulador a FFh (tot uns)
  movwf TRISA  ; Posa tots els bits del port A com a entrada
  clrf TRISB  ; Tot el port B és de sortida
  clrf TRISC  ; Posa tots els bits del port C com a sortida
  bsf BRGH  ; Configuració de velocitat
  bcf BRG16  ; Paràmetre de velocitat de 8 bits
  movlw 25  ; Velocitat de 9600 baud
  movwf SPBRG  ; Paràmetre de velocitat
  bcf SYNC  ; Comunicació asíncrona
  bcf TX9  ; Comunicació de 8 bits
  bcf RP0  ; Tria el banc 0
  bsf SPEN  ; Activa comunicació sèrie
  bsf RP0  ; Tria el banc 1
  bsf TXEN  ; Activa comunicació
  movlw 00010000B  ; Posa el conversor a 1/8 de la freqüència
  movwf ADCON1  ; Copia W a la configuració del conversor A/D
  bcf RP0
  bsf RP1  ; Tria el banc 2
  movlw 0xFF  ; Posa l'acumulador a FFh (tot uns)
  movwf ANSEL  ; Configura AN0-AN7 com entrades analògiques
  clrf ANSELH  ; Desactiva les altres entrades analògiques
  bcf RP0
  bcf RP1  ; Tria el banc 0
  movlw 10  ; Retard de 2 s
  call Rets  ; Esperem que arrenqui la pantalla
  movlw 00001001B  ; activa el conversor A/D connectat a AN2
  movwf ADCON0  ; amb el resultat justificat per l'esquerra
Bucle:
  movlw 254  ; Caràcter de control
  movwf Caracter  ; Ho guarda a la variable
  call EnviaL  ; Ho envia
  movlw 1  ; Esborra la pantalla i posa el cursor a l'inici
  movwf Caracter  ; Ho guarda a la variable
  call EnviaL  ; Ho envia
  nop  ; espera un microsegon
  nop  ; espera un microsegon
  nop  ; espera un microsegon
  nop  ; espera un microsegon
  nop  ; espera un microsegon
  bsf GO_DONE  ; Inicia la conversió
  btfsc GO_DONE  ; Quan el bit sigui 0 la conversió haurà acabat
  goto $-1  ; repetim la línia fins que deixi de ser 1
  movf ADRESH,w  ; Llegeix els polsadors
  call BCD  ; Els passa a BCD (cinc nibbles en tres bytes)
  ; Anem a convertir-los a ASCII i enviar-los
  movlw '0'  ; Carrega el codi ASCII del número 0
             ; Sumant-li la xifra tindrem el codi ASCII
  addwf D3,w  ; Ho afegeix al dígit i se'l queda a W
  movwf Caracter  ; Ho guarda a la variable
  call EnviaL  ; Ho envia
  movlw '0'  ; Carrega el codi ASCII del número 0
             ; Sumant-li la xifra tindrem el codi ASCII
  addwf D2,w  ; Ho afegeix al dígit i se'l queda a W
  movwf Caracter  ; Ho guarda a la variable
  call EnviaL  ; Ho envia
  movlw '0'  ; Carrega el codi ASCII del número 0
             ; Sumant-li la xifra tindrem el codi ASCII
  addwf D1,w  ; Ho afegeix al dígit i se'l queda a W
  movwf Caracter  ; Ho guarda a la variable
  call EnviaL  ; Ho envia
  movlw 5  ; Retard d'1 s
  call Rets  ; Deixem temps a llegir-ho
  goto Bucle
;
; Funció que converteix un número de 8 bits a BCD (3 dígits)
;
BCD:
  clrf D3  ; Posa D3 (centenes) a zero
  clrf D2  ; Posa D2 (desenes) a zero
  movwf D1  ; Guarda W (valor a convertir) a D1
            ; D1 són les unitats
Cent:  ; Anem a trobar les centenes (D3)
  movlw 100  ; Carrega 100 decimal a W
  subwf D1,w  ; Li resta W a D1
  btfss CARRY  ; Mira C i si és 1 no fa la següent
               ; Si és 1 vol dir resultat positiu
  goto Desen  ; Si el resultat és negatiu les centenes ja estan
              ; el valor de W es perd i anem a les desenes
  movwf D1  ; Guarda el resultat (W) a D1
  incf D3,f  ; La centena restada a D1 l'afegeix a D3
  goto Cent  ; Tornem-ho a fer
Desen:  ; Anem a trobar les desenes
  movlw 10  ; Carrega 10 decimal a W
  subwf D1,w  ; Li resta W a D1
  btfss CARRY  ; Mira C i si és 1 no fa la següent
               ; Si és 1 vol dir resultat positiu
  goto Final  ; Si el resultat és negatiu les desenes ja estan
              ; el valor de W es perd i anem a ASCII
  movwf D1  ; Guarda el resultat (W) a D1
  incf D2,f  ; La desena restada a D1 l'afegeix a D2
  goto Desen  ; Tornem-ho a fer
Final:
  retlw 0  ; Retorn amb un 0 a W
;
; Enviem caràcters a visualitzar
;
EnviaL:
  movf Caracter,w  ; Agafa el caràcter
  movwf TXREG  ; L'envia
  nop			
  nop  ; Espera 2 us
  btfss TXIF  ; El registre TXREG ha quedat lliure?
  goto $-1  ; No, doncs esperem
  return  ; Tornem al lloc des d'on hem vingut
;
; Funció de retard de 0,2 W s
;
Rets:
  movwf Retard3
Bucles:
  decfsz Retard1,f		
  goto Bucles		
  decfsz Retard2,f		
  goto Bucles		
  decfsz Retard3,f	
  goto Bucles
  return
END main

 

 

Llicència de Creative Commons
Aquesta obra d'Oriol Boix està llicenciada sota una llicència no importada Reconeixement-NoComercial-SenseObraDerivada 3.0.