Programació en mpasm del PIC 16F690

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

Exemple ST - Funcions

A l'Exemple RB tenim dos bucles de retard. Podríem definir aquest bucle com una funció i anar-hi des dels dos llocs on el necessitem. En realitat, passarem un paràmetre (a través de W) a la funció, així que es comportarà com una funció.

En el programa següent hem substituït els dos Bucles de retard per crides (call) a la funció i passem el nombre de cicles a través de l'acumulador.

#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)
Memoria			; El bit 0 és l'estat previ del polsador i el bit 1 és el sentit de gir
Visualit		; Una variable on guardem el que mostraran els LED
Compta			; Una variable per comptar iteracions
Retard1			; Variable per al bucle de retard
Retard2
	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
	movlw	b'00010000'
	movwf	ADCON1		; Posa el conversor a 1/8 de la freqüència
	bcf	STATUS,RP0
	bsf	STATUS,RP1	; Tria el banc 2
	movlw	b'00000001'
	movwf	ANSEL		; Posa AN0 com entrada analògica
	bcf	STATUS,RP0
	bcf	STATUS,RP1	; Tria el banc 0
	movlw	b'00000001'	; activa el conversor A/D connectat a AN0
	movwf	ADCON0		; amb el resultat justificat per l'esquerra
	movlw	b'00001000'	; Activa el bit 3
	movwf	Visualit	; Ho copia sobre la variable Visualit
	clrf	Memoria		; Inicialment, rotació a dreta i polsador és no premut
Bucle
	movf	Visualit,w	; Copia la variable Visualit a l'acumulador
	movwf	PORTC		; Copia el resultat sobre els LED
	nop			; espera un microsegon
	nop			; espera un microsegon
	nop			; espera un microsegon
	nop			; espera un microsegon
	nop			; espera un microsegon, en total 5
	bsf	ADCON0,GO	; Inicia la conversió
	btfsc	ADCON0,GO	; Quan el bit sigui 0 la conversió haurà acabat
	goto	$-1		; repetim la línia fins que deixi de ser 0
	movf	ADRESH,w	; Copia els bits superiors a l'acumulador
	addlw	1		; Li suma 1 i tenim la durada variable del cicle
	call	Retard
	movlw	.13		; El punt indica que es un valor decimal
	call	Retard
	movlw	b'00000001'	; Polsador activat
	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	Memoria,w	; Copia Memoria a l'acumulador
	andlw	b'00000001'	; Conserva només el bit 0 (Previ)
	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	Rotar
	movf	Memoria,w	; Copia Memoria a l'acumulador
	xorlw	b'00000010'	; Inverteix el valor del bit 1 (Sentit)
	movwf	Memoria		; I ho guarda a Sentit
Rotar
	bcf	STATUS,C	; posa a zero el bit d'arrossegament
				; Això cal en qualsevol sentit
	btfsc	Memoria,1	; En quin sentit rodem? 
	goto	Esquerra	; 1 = Esquerra
Dreta				; Gir a la dreta
	rrf	Visualit,f	; Fa rodar els bits cap a la dreta
				; el bit d'arrossegament entra per l'esquerra
				; i el bit de la dreta passa a l'arrossegament
	btfsc	STATUS,C	; Comprova si s'ha activat l'arrossegament
				; Si no s'ha activat, salta una instrucció
	bsf	Visualit,3	; Si s'ha activat, torna a posar un 1 (0000 1000)
	goto	Bucle		; Repetim-ho...
Esquerra			; Gir a l'esquerra
	rlf	Visualit,f	; Fa rodar els bits cap a l'esquerra
	btfss	Visualit,4	; Hem sortit fora dels 4 bits dels LED?
	goto	Bucle		; No, repetim-ho...
	bcf	Visualit,4	; Sí, desactivem el 4
	bsf	Visualit,0	; i tornem a activar el primer
	goto	Bucle		; i repetim-ho...
					;
					; Bucle de retard
					;
Retard
	movwf	Retard2		; Ho copia a la variable Retard2
RetVar
	decfsz	Retard1,f	; Decrementa la variable 1
				; si dona zero, no es fa la instrucció següent
	goto	RetVar		; Salta, excepte si el resultat ha estat zero
	decfsz	Retard2,f	; Decrementa la variable 2
	goto	RetVar		; Salta, excepte si el resultat ha estat zero
	return
	end

Les subfuncions (i altres parts del programa) poden estar en fitxers separats, de manera que estiguin ja preparats i comprovats i només calgui incloure'ls. Això permet reutilitzar fàcilment codi d'un programa a un altre.

Per exemple, la funció podria estar en el fitxer Retards.inc i llavors el nostre fitxer de programa podria ser:

#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)
Memoria			; El bit 0 és l'estat previ del polsador i el bit 1 és el sentit de gir
Visualit		; Una variable on guardem el que mostraran els LED
Compta			; Una variable per comptar iteracions
Retard1			; Variable per al bucle de retard
Retard2
	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
	movlw	b'00010000'
	movwf	ADCON1		; Posa el conversor a 1/8 de la freqüència
	bcf	STATUS,RP0
	bsf	STATUS,RP1	; Tria el banc 2
	movlw	b'00000001'
	movwf	ANSEL		; Posa AN0 com entrada analògica
	bcf	STATUS,RP0
	bcf	STATUS,RP1	; Tria el banc 0
	movlw	b'00000001'	; activa el conversor A/D connectat a AN0
	movwf	ADCON0		; amb el resultat justificat per l'esquerra
	movlw	b'00001000'	; Activa el bit 3
	movwf	Visualit	; Ho copia sobre la variable Visualit
	clrf	Memoria		; Inicialment, rotació a dreta i polsador és no premut
Bucle
	movf	Visualit,w	; Copia la variable Visualit a l'acumulador
	movwf	PORTC		; Copia el resultat sobre els LED
	nop			; espera un microsegon
	nop			; espera un microsegon
	nop			; espera un microsegon
	nop			; espera un microsegon
	nop			; espera un microsegon, en total 5
	bsf	ADCON0,GO	; Inicia la conversió
	btfsc	ADCON0,GO	; Quan el bit sigui 0 la conversió haurà acabat
	goto	$-1		; repetim la línia fins que deixi de ser 0
	movf	ADRESH,w	; Copia els bits superiors a l'acumulador
	addlw	1		; Li suma 1 i tenim la durada variable del cicle
	call	Retard
	movlw	.13		; El punt indica que es un valor decimal
	call	Retard
	movlw	b'00000001'	; Polsador activat
	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	Memoria,w	; Copia Memoria a l'acumulador
	andlw	b'00000001'	; Conserva només el bit 0 (Previ)
	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	Rotar
	movf	Memoria,w	; Copia Memoria a l'acumulador
	xorlw	b'00000010'	; Inverteix el valor del bit 1 (Sentit)
	movwf	Memoria		; I ho guarda a Sentit
Rotar
	bcf	STATUS,C	; posa a zero el bit d'arrossegament
				; Això cal en qualsevol sentit
	btfsc	Memoria,1	; En quin sentit rodem? 
	goto	Esquerra	; 1 = Esquerra
Dreta				; Gir a la dreta
	rrf	Visualit,f	; Fa rodar els bits cap a la dreta
				; el bit d'arrossegament entra per l'esquerra
				; i el bit de la dreta passa a l'arrossegament
	btfsc	STATUS,C	; Comprova si s'ha activat l'arrossegament
				; Si no s'ha activat, salta una instrucció
	bsf	Visualit,3	; Si s'ha activat, torna a posar un 1 (0000 1000)
	goto	Bucle		; Repetim-ho...
Esquerra			; Gir a l'esquerra
	rlf	Visualit,f	; Fa rodar els bits cap a l'esquerra
	btfss	Visualit,4	; Hem sortit fora dels 4 bits dels LED?
	goto	Bucle		; No, repetim-ho...
	bcf	Visualit,4	; Sí, desactivem el 4
	bsf	Visualit,0	; i tornem a activar el primer
	goto	Bucle		; i repetim-ho...
#include    <Retards.inc>
	end

I el fitxer Retards.inc seria:

					;
					; Bucle de retard
					;
Retard
	movwf	Retard2		; Ho copia a la variable Retard2
RetVar
	decfsz	Retard1,f	; Decrementa la variable 1
				; si dona zero, no es fa la instrucció següent
	goto	RetVar		; Salta, excepte si el resultat ha estat zero
	decfsz	Retard2,f	; Decrementa la variable 2
	goto	RetVar		; Salta, excepte si el resultat ha estat zero
	return

Fixem-nos que en assemblador cal posar la directiva #include en el lloc exacte on volem carregar el fitxer. Si, per exemple, l'haguéssim posat al començament (entre org0 i Inici) el microcontrolador començaria executant la funció com si fos el programa principal.

 

 

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