Programació en mpasm 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:

#include <p16F690.inc>
	__config (_INTRC_OSC_NOCLKOUT&_WDT_OFF&_PWRTE_OFF&_MCLRE_OFF&_CP_OFF&_BOR_OFF&_IESO_OFF&_FCMEN_OFF)
	cblock	0x20
Polsador		; Una variable amb l'estat del polsador (1 = premut)
Previ			; I una amb l'estat previ del polsador
Visualit		; Una variable on guardem el que mostraran els LED
Compta			; Una variable per comptar iteracions
Retard1			; Variable per al bucle de retard
temp			; Variable temporal
	endc
	org 0
Inici
	bsf		STATUS,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		STATUS,RP0
	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		b'00000001'
	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		STATUS,Z	; 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		STATUS,Z	; 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		STATUS,Z	; 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		b'00000001'	; 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 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		b'00000000'	; Si el punter és zero retornem amb el codi Gray de 0 a l'acumulador
	retlw		b'00000001'	; Torna amb 1
	retlw		b'00000011'	; Torna amb 2
	retlw		b'00000010'	; Torna amb 3
	retlw		b'00000110'	; Torna amb 4
	retlw		b'00000111'	; Torna amb 5
	retlw		b'00000101'	; Torna amb 6
	retlw		b'00000100'	; Torna amb 7
	retlw		b'00001100'	; Torna amb 8
	retlw		b'00001101'	; Torna amb 9
	retlw		b'00001111'	; Torna amb 10
	retlw		b'00001110'	; Torna amb 11
	retlw		b'00001010'	; Torna amb 12
	retlw		b'00001011'	; Torna amb 13
	retlw		b'00001001'	; Torna amb 14
	retlw		b'00001000'	; Torna amb 15
	end

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

Taula
	dt	b'00001111', 0xFA, "PICkit", .15

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 b'00001111'
	retlw		0xFA	; 0xFA 
	retlw		0x50	; Equival a 'P'
	retlw		0x49	; Equival a 'I'
	retlw		0x43	; Equival a 'C'
	retlw		0x6B	; Equival a 'k'
	retlw		0x69	; Equival a 'i'
	retlw		0x74	; Equival a 't'
	retlw		0xF	; Equival a .15

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

#include <p16F690.inc>
	__config (_INTRC_OSC_NOCLKOUT&_WDT_OFF&_PWRTE_OFF&_MCLRE_OFF&_CP_OFF&_BOR_OFF&_IESO_OFF&_FCMEN_OFF)
	cblock	0x20
Polsador		; Una variable amb l'estat del polsador (1 = premut)
Previ			; I una amb l'estat previ del polsador
Visualit		; Una variable on guardem el que mostraran els LED
Compta			; Una variable per comptar iteracions
Retard1			; Variable per al bucle de retard
temp			; Variable temporal
	endc
	org 0
Inici
	bsf		STATUS,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		STATUS,RP0
	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		b'00000001'
	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		STATUS,Z	; 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		STATUS,Z	; 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		STATUS,Z	; 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		b'00000001'	; 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 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
	dt	b'00000000', b'00000001', b'00000011', b'00000010'
	dt	b'00000110', b'00000111', b'00000101', b'00000100'
	dt	b'00001100', b'00001101', b'00001111', b'00001110'
	dt	b'00001010', b'00001011', b'00001001', b'00001000'
	end

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:

#include <p16F690.inc>
	__config (_INTRC_OSC_NOCLKOUT&_WDT_OFF&_PWRTE_OFF&_MCLRE_OFF&_CP_OFF&_BOR_OFF&_IESO_OFF&_FCMEN_OFF)
	cblock	0x20
Polsador		; Una variable amb l'estat del polsador (1 = premut)
Previ			; I una amb l'estat previ del polsador
Visualit		; Una variable on guardem el que mostraran els LED
Compta			; Una variable per comptar iteracions
Retard1			; Variable per al bucle de retard
temp			; Variable temporal
	endc
	org 0
Inici
	bsf		STATUS,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		STATUS,RP0
	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		b'00000001'
	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		STATUS,Z	; 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		STATUS,Z	; 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		STATUS,Z	; 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		b'00000001'	; 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...
	org		0xf0		; Adreça triada perquè segur canviï PCH
					;
					; funció de conversió a codi Gray
					;
Conversio				; funció de conversió a codi Gray
	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		STATUS,C	; 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		b'00000000'	; Si el punter és zero retornem amb el codi Gray de 0 a l'acumulador
	retlw		b'00000001'	; Torna amb 1
	retlw		b'00000011'	; Torna amb 2
	retlw		b'00000010'	; Torna amb 3
	retlw		b'00000110'	; Torna amb 4
	retlw		b'00000111'	; Torna amb 5
	retlw		b'00000101'	; Torna amb 6  (aquesta instrucció està a 0FFh)
	retlw		b'00000100'	; Torna amb 7  (aquesta instrucció està a 100h)
	retlw		b'00001100'	; Torna amb 8
	retlw		b'00001101'	; Torna amb 9
	retlw		b'00001111'	; Torna amb 10
	retlw		b'00001110'	; Torna amb 11
	retlw		b'00001010'	; Torna amb 12
	retlw		b'00001011'	; Torna amb 13
	retlw		b'00001001'	; Torna amb 14
	retlw		b'00001000'	; Torna amb 15
	end

 

 

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