Programació en pic-as del PIC 16F690

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

Exemple PC - Comptador de programa

En aquest cas també convertirem el valor d'un comptador a codi Gray (com a l'exemple AI) però ho farem d'una manera diferent. La nostra funció de conversió a codi Gray tindrà 16 diferents adreces de retorn del tipus retlw (retorn amb un valor a W) i anirem a la instrucció que correspon al valor actual a base de modificar el comptador de programa.

El programa següent és una versió simplificada en la que ja sabem que no cal tocar PCH:

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
Polsador EQU 0x20  ; Una variable amb l'estat del polsador (1 = premut)
Previ EQU 0x21  ; I una amb l'estat previ del polsador
Visualit EQU 0x22  ; Una variable on guardem el que mostraran els LED
Compta EQU 0x23  ; Una variable per comptar iteracions
Retard1 EQU 0x24  ; Variable per al bucle de retard
temp EQU 0x25  ; Variable temporal
PSECT code, class=CODE, delta=2, abs
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 TRISC  ; Posa tots els bits del port C com a sortida
  bcf RP0
  movlw 5  ; Retard d'1 s
  call Rets  ; Retard per evitar problemes amb el polsador
  clrf Compta  ; Posa el comptador d'iteracions a valor zero
  clrf Visualit  ; Posa el comptador dels LED a valor zero
  clrf Previ  ; L'estat previ del polsador és no premut
  clrf PORTC  ; Comencem amb els LED apagats
Bucle:
  movlw 00000001B
  movwf Polsador  ; Activem polsador abans de comprovar
  btfsc PORTA,3  ; Mira si està desactivada l'entrada A3
                 ; Si desactivat (premut), no fa la instrucció següent
  clrf Polsador  ; Si no està premut, desactiva polsador
  movf Previ,w  ; Copia Previ a l'acumulador
  xorwf Polsador,w  ; Compara Previ amb Polsador, si són iguals s'activa Z
  btfsc ZERO  ; Si són iguals va a Final
  goto Esborra
  incf Compta,f  ; Si són iguals, incrementa el valor de Compta
  movf Compta,w  ; Copia Compta a l'acumulador
  xorlw 4  ; Comprova si val 4, si ho val s'activa Z
  btfss ZERO  ; Si val 4 no fa la instrucció següent
  goto Final  ; Si no era 4 va a Final
  movf Polsador,w  ; Copia Polsador a W, si val 0 s'activa Z
  btfsc ZERO  ; Si Polsador valia 1 (Z=0) no fa la instrucció següent
  goto Invert  ; Si no està premut, ja estem
  incf Visualit,f  ; Si ho està, incrementa el valor de Visualit
  btfsc Visualit,4  ; Mira si hem arribat a 16
  clrf Visualit  ; Si hem arribat a 16, torna a posar el comptador a zero
  movf Visualit,w  ; El valor actual el guardem a W
  call Conversio  ; funció de conversió a codi Gray
  movwf PORTC  ; Posa el valor de W als LED
Invert:
  movf Previ,w  ; Copia Previ a l'acumulador
  xorlw 00000001B  ; Inverteix el valor
  movwf Previ  ; I ho guarda a Previ
Esborra:
  clrf Compta  ; Posa el comptador d'iteracions a valor zero
Final:  ; Funció de retard 1 ms
  nop
  decfsz Retard1,f	
  goto Final
  goto Bucle  ; Repetim-ho...
;
; Funció de retard de 0,2 W s
;
Rets:
  movwf Retard1+2
Bucles:
  decfsz Retard1,f		
  goto Bucles		
  decfsz Retard1+1,f		
  goto Bucles		
  decfsz Retard1+2,f	
  goto Bucles
  return
;
; funció de conversió a codi Gray
;
Conversio:
  andlw 0x0F  ; Preventivament, posa a zero els quatre bits superiors
  movwf temp  ; Ho guardem a la variable temporal per tenir lliure l'acumulador
              ; Aquest és el número que buscarem a la taula
  movlw Taula  ; Carrega l'adreça de la taula
  addwf temp,w  ; Hi afegeix el número que busquem (entre 0 i 15)
                ; i ho guarda a l'acumulador
  movwf PCL  ; Modifica el valor de PCL
Taula:
  retlw 00000000B  ; Si el punter és zero retornem amb el codi Gray de 0 a l'acumulador
  retlw 00000001B  ; Torna amb 1
  retlw 00000011B  ; Torna amb 2
  retlw 00000010B  ; Torna amb 3
  retlw 00000110B  ; Torna amb 4
  retlw 00000111B  ; Torna amb 5
  retlw 00000101B  ; Torna amb 6
  retlw 00000100B  ; Torna amb 7
  retlw 00001100B  ; Torna amb 8
  retlw 00001101B  ; Torna amb 9
  retlw 00001111B  ; Torna amb 10
  retlw 00001110B  ; Torna amb 11
  retlw 00001010B  ; Torna amb 12
  retlw 00001011B  ; Torna amb 13
  retlw 00001001B  ; Torna amb 14
  retlw 00001000B  ; Torna amb 15
END main

La directiva IRP ens permet entrar les dades de manera compacta. Si, per exemple, escrivim aquest tros de programa:

Taula:
IRP number, 00001111B, 0xFA, "P", 15
  retlw number
ENDM

obtindrem a la memòria de programa les instruccions retlw corresponents a cada un dels valors incloent-hi una línia per a cada lletra del text que està entre cometes:

Taula:
  retlw 0xF  ; Equival a 00001111B
  retlw 0xFA  ; 0xFA 
  retlw 0x50  ; Equival a 'P'
  retlw 0xF  ; Equival a 15

La següent versió del programa fa el mateix que el primer que hem vist però emprant la directiva IRP.

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
Polsador EQU 0x20  ; Una variable amb l'estat del polsador (1 = premut)
Previ EQU 0x21  ; I una amb l'estat previ del polsador
Visualit EQU 0x22  ; Una variable on guardem el que mostraran els LED
Compta EQU 0x23  ; Una variable per comptar iteracions
Retard1 EQU 0x24  ; Variable per al bucle de retard
temp EQU 0x25  ; Variable temporal
PSECT code, class=CODE, delta=2, abs
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 TRISC  ; Posa tots els bits del port C com a sortida
  bcf RP0
  movlw 5  ; Retard d'1 s
  call Rets  ; Retard per evitar problemes amb el polsador
  clrf Compta  ; Posa el comptador d'iteracions a valor zero
  clrf Visualit  ; Posa el comptador dels LED a valor zero
  clrf Previ  ; L'estat previ del polsador és no premut
  clrf PORTC  ; Comencem amb els LED apagats
Bucle:
  movlw 00000001B
  movwf Polsador  ; Activem polsador abans de comprovar
  btfsc PORTA,3  ; Mira si està desactivada l'entrada A3
                 ; Si desactivat (premut), no fa la instrucció següent
  clrf Polsador  ; Si no està premut, desactiva polsador
  movf Previ,w  ; Copia Previ a l'acumulador
  xorwf Polsador,w  ; Compara Previ amb Polsador, si són iguals s'activa Z
  btfsc ZERO  ; Si són iguals va a Final
  goto Esborra
  incf Compta,f  ; Si són iguals, incrementa el valor de Compta
  movf Compta,w  ; Copia Compta a l'acumulador
  xorlw 4  ; Comprova si val 4, si ho val s'activa Z
  btfss ZERO  ; Si val 4 no fa la instrucció següent
  goto Final  ; Si no era 4 va a Final
  movf Polsador,w  ; Copia Polsador a W, si val 0 s'activa Z
  btfsc ZERO  ; Si Polsador valia 1 (Z=0) no fa la instrucció següent
  goto Invert  ; Si no està premut, ja estem
  incf Visualit,f  ; Si ho està, incrementa el valor de Visualit
  btfsc Visualit,4  ; Mira si hem arribat a 16
  clrf Visualit  ; Si hem arribat a 16, torna a posar el comptador a zero
  movf Visualit,w  ; El valor actual el guardem a W
  call Conversio  ; funció de conversió a codi Gray
  movwf PORTC  ; Posa el valor de W als LED
Invert:
  movf Previ,w  ; Copia Previ a l'acumulador
  xorlw 00000001B  ; Inverteix el valor
  movwf Previ  ; I ho guarda a Previ
Esborra:
  clrf Compta  ; Posa el comptador d'iteracions a valor zero
Final:  ; Funció de retard 1 ms
  nop
  decfsz Retard1,f	
  goto Final
  goto Bucle  ; Repetim-ho...
;
; Funció de retard de 0,2 W s
;
Rets:
  movwf Retard1+2
Bucles:
  decfsz Retard1,f		
  goto Bucles		
  decfsz Retard1+1,f		
  goto Bucles		
  decfsz Retard1+2,f	
  goto Bucles
  return
;
; funció de conversió a codi Gray
;
Conversio:
  andlw 0x0F  ; Preventivament, posa a zero els quatre bits superiors
  movwf temp  ; Ho guardem a la variable temporal per tenir lliure l'acumulador
              ; Aquest és el número que buscarem a la taula
  movlw Taula  ; Carrega l'adreça de la taula
  addwf temp,w  ; Hi afegeix el número que busquem (entre 0 i 15)
                ; i ho guarda a l'acumulador
  movwf PCL  ; Modifica el valor de PCL
Taula:
IRP valors, 00000000B, 00000001B, 00000011B, 00000010B, 00000110B, 00000111B, 00000101B, 00000100B
  retlw valors
ENDM
IRP valors, 00001100B, 00001101B, 00001111B, 00001110B, 00001010B, 00001011B, 00001001B, 00001000B
  retlw valors
ENDM
END main

A continuació tenim una nova versió en la que la funció està posada de tal manera que una part de la taula està a PCH 00h i una altra a 01h; així ens veiem obligats a controlar PCH:

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
Polsador EQU 0x20  ; Una variable amb l'estat del polsador (1 = premut)
Previ EQU 0x21  ; I una amb l'estat previ del polsador
Visualit EQU 0x22  ; Una variable on guardem el que mostraran els LED
Compta EQU 0x23  ; Una variable per comptar iteracions
Retard1 EQU 0x24  ; Variable per als bucles de retard (3 bytes)
temp EQU 0x27  ; Variable temporal
PSECT code, class=CODE, delta=2, abs
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 TRISC  ; Posa tots els bits del port C com a sortida
  bcf RP0
  movlw 5  ; Retard d'1 s
  call Rets  ; Retard per evitar problemes amb el polsador
  clrf Compta  ; Posa el comptador d'iteracions a valor zero
  clrf Visualit  ; Posa el comptador dels LED a valor zero
  clrf Previ  ; L'estat previ del polsador és no premut
  clrf PORTC  ; Comencem amb els LED apagats
Bucle:
  movlw 00000001B
  movwf Polsador  ; Activem polsador abans de comprovar
  btfsc PORTA,3  ; Mira si està desactivada l'entrada A3
                 ; Si desactivat (premut), no fa la instrucció següent
  clrf Polsador  ; Si no està premut, desactiva polsador
  movf Previ,w  ; Copia Previ a l'acumulador
  xorwf Polsador,w  ; Compara Previ amb Polsador, si són iguals s'activa Z
  btfsc ZERO  ; Si són iguals va a Final
  goto Esborra
  incf Compta,f  ; Si són iguals, incrementa el valor de Compta
  movf Compta,w  ; Copia Compta a l'acumulador
  xorlw 4  ; Comprova si val 4, si ho val s'activa Z
  btfss ZERO  ; Si val 4 no fa la instrucció següent
  goto Final  ; Si no era 4 va a Final
  movf Polsador,w  ; Copia Polsador a W, si val 0 s'activa Z
  btfsc ZERO  ; Si Polsador valia 1 (Z=0) no fa la instrucció següent
  goto Invert  ; Si no està premut, ja estem
  incf Visualit,f  ; Si ho està, incrementa el valor de Visualit
  btfsc Visualit,4  ; Mira si hem arribat a 16
  clrf Visualit  ; Si hem arribat a 16, torna a posar el comptador a zero
  movf Visualit,w  ; El valor actual el guardem a W
  call Conversio  ; funció de conversió a codi Gray
  movwf PORTC  ; Posa el valor de W als LED
Invert:
  movf Previ,w  ; Copia Previ a l'acumulador
  xorlw 00000001B  ; Inverteix el valor
  movwf Previ  ; I ho guarda a Previ
Esborra:
  clrf Compta  ; Posa el comptador d'iteracions a valor zero
Final:  ; Funció de retard 1 ms
  nop
  decfsz Retard1,f	
  goto Final
  goto Bucle  ; Repetim-ho...
;
; Funció de retard de 0,2 W s
;
Rets:
  movwf Retard1+2
Bucles:
  decfsz Retard1,f		
  goto Bucles		
  decfsz Retard1+1,f		
  goto Bucles		
  decfsz Retard1+2,f	
  goto Bucles
  return
;
; funció de conversió a codi Gray
;
ORG 0xf0  ; Adreça triada perquè segur canviï PCH
Conversio:
  andlw 0x0F  ; Preventivament, posa a zero els quatre bits superiors
  movwf temp  ; Ho guardem a la variable temporal per tenir lliure l'acumulador
              ; Aquest és el número que buscarem a la taula
  movlw high Taula  ; Carrega la part alta de l'adreça de la taula
  movwf PCLATH  ; Ho posa a la part alta de PC
  movlw low Taula  ; Carrega la part baixa de l'adreça de la taula
  addwf temp,w  ; Hi afegeix el número que busquem (entre 0 i 15)
                ; i ho guarda a l'acumulador
  btfsc CARRY  ; S'ha activat C?
  incf PCLATH,f  ; Si s'ha activat, incrementem PCLATH
  movwf PCL  ; Modifica el valor de PCL (i, per tant, també el de PCH)
Taula:
  retlw 00000000B  ; Si el punter és zero retornem amb el codi Gray de 0 a l'acumulador
  retlw 00000001B  ; Torna amb 1
  retlw 00000011B  ; Torna amb 2
  retlw 00000010B  ; Torna amb 3
  retlw 00000110B  ; Torna amb 4
  retlw 00000111B  ; Torna amb 5
  retlw 00000101B  ; Torna amb 6
  retlw 00000100B  ; Torna amb 7
  retlw 00001100B  ; Torna amb 8
  retlw 00001101B  ; Torna amb 9
  retlw 00001111B  ; Torna amb 10
  retlw 00001110B  ; Torna amb 11
  retlw 00001010B  ; Torna amb 12
  retlw 00001011B  ; Torna amb 13
  retlw 00001001B  ; Torna amb 14
  retlw 00001000B  ; Torna amb 15
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.