Programació en mpasm del PIC 16F690

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

Monitor cardíac

Programa del grup 4

El programa és el següent:

#include <p16F690.inc>
	__config (_INTRC_OSC_NOCLKOUT&_WDT_OFF&_PWRTE_OFF&_MCLRE_OFF&_CP_OFF&_BOR_OFF&_IESO_OFF&_FCMEN_OFF)
#define	ValComp	.6	; Nombre de repeticions per eliminar soroll
	cblock 0x20	; Zona de memòria de dades habitual 
Caract
pantalla		; variable que guarda las pulsaciones cada 6s. És la copia de comptador.
pantalla2		; pantalla x 10. Pulsacions per minut.
tiempo:2
comptador		; nombre de pulsacions en 6s.
comptador2		; utilitzat en el BucleSum. Multiplicar per deu.
D1			; Variable unitats	
D2			; Variable desenes	
D3			; Variable centenes	
Control			; Bits de control (port B)
Caracter		; Caràcter o codi a enviar (port C)
Retard1			; Variables per als cicles de retard
Retard2	
Lectura			; Valor llegit a l'entrada analògica	
Temps:2			; S'incrementa cada cop que es fa la interrupció (cada 2 ms)	
Max			; Valor màxim del senyal en un període	
Min			; Valor mínim del senyal en un període	
Centre			; Valor mig del senyal en un període	
Periode:2		; Quart de període
			; Guarda la meitat del nombre d'interrupcions entre dos inicis de pols
Comp			; Comptador per filtrar soroll
Bits			; Variable on guardarem els bits d'estat que fem servir	
			; Pols	Bits,0	S'activa quan el senyal està per sobre del valor mig
			; Tenim1 Bits,3	S'activa quan ja hem detectat l'inici del primer pols
			; Estable Bits,2 S'activa quan ja hem detectat l'inici del segon pols
			; i, per tant, ja tenim dades útils
W_Copia			; Guardarà el contingut de W durant la interrupció
ST_Copia		; Guardarà STATUS durant la interrupció	
	endc
	org 0
	goto	Inici		; Saltem al lloc on hi ha el programa principal
	nop			; Zona de memòria de programa que no utilitzem
	nop
	nop
Interrup
	bcf	INTCON,GIE	; Desactiva les interrupcions momentàniament
	movwf	W_Copia		; Copiem l'acumulador a W_Copia
	swapf	STATUS,w	; Copiem STATUS a l'acumulador permutant els nibbles
	clrf	STATUS		; Posa a 0 i així segur que el banc és el 0
	movwf	ST_Copia	; Guarda STATUS permutat a ST_Copia
	btfss	INTCON,T0IF	; Mira si Timer0 ha arribat a zero
				; Si hi ha arribat, no fa la instrucció següent
	goto	FiInt		; Si la interrupció no és del Timer0 no fem res
Timer0				; Programa corresponent a Timer0
	movlw	.7		; Nova preselecció
	movwf	TMR0		; Ho posem a TMR0
	bcf	INTCON,T0IF	; Si ha arribat, desactivem el bit
				; Llegim el sensor
	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 1
	movf	ADRESH,w	; Llegeix el valor (8 bits)
	movwf	Lectura		; I el guarda
	incf	Temps,f		; Incrementem Temps
	btfsc	STATUS,Z	; Si s'activa Z vol dir que hem incrementat un 255
	incf	Temps+1,f	; Si s'activa, incrementem el byte superior
	movf	Centre,w
	subwf	Lectura,w	; W = Lectura - Centre
	btfss	STATUS,C	; C = 1 si Lectura >= Centre
	goto	baix		; Lectura < Centre
				; Lectura >= Centre
	movf	Max,w
	subwf	Lectura,w	; W = Lectura - Max
	btfss	STATUS,C	; C = 1 si Lectura >= Max
	goto	mirapols	; Lectura < Max
				; Lectura >= Max
	movf	Lectura,w
	movwf	Max		; Guarda el nou màxim
	goto	mirapols	; Passem a la segona part
baix				; Lectura < Centre
				; Anem a mirar si Temps:2 > Periode:2
				; Si Temps+1 > Periode+1 segur que sí
				; Si Temps+1 < Periode+1 segur que no
				; Si Temps+1 = Periode+1 cal comprovar si Temps > Periode
	movf	Periode+1,w	
	subwf	Temps+1,w	; W = Temps+1 - Periode+1
	btfss	STATUS,C	; C = 1 si Temps+1 >= Periode+1
	goto	mirapols	; Temps+1 < Periode+1
				; Temps+1 >= Periode+1
	movf	Periode+1,w	
	xorwf	Temps+1,w	; Ho comparem amb Temps+1
	btfss	STATUS,Z
	goto	miramin		; Si són diferents és que Temps+1 > Periode+1
	movf	Periode,w
	subwf	Temps,w		; W = Temps - Periode
	btfss	STATUS,C	; C = 1 si Temps >= Periode
	goto	mirapols	; Temps < Periode
miramin				; Temps >= Periode
	movf	Min,w
	subwf	Lectura,w	; W = Lectura - Min
	btfsc	STATUS,C	; C = 1 si Lectura >= Min
	goto	mirapols	; Lectura >= Min
				; Lectura < Min
	movf	Lectura,w
	movwf	Min		; Guarda el nou mínim
mirapols
	btfsc	Bits,0		; Mira si Pols està activat
	goto	activat		; Sí ho està
	movf	Centre,w
	subwf	Lectura,w	; W = Lectura - Centre
	btfss	STATUS,C	; C = 1 si Lectura >= Centre
	goto	miratemps	; Lectura < Centre
				; Lectura >= Centre
				; Anem a mirar si Temps:2 > Periode:2
				; Si Temps+1 > Periode+1 segur que sí
				; Si Temps+1 < Periode+1 segur que no
				; Si Temps+1 = Periode+1 cal comprovar si Temps > Periode
	movf	Periode+1,w
	subwf	Temps+1,w	; W = Temps+1 - Periode+1
	btfss	STATUS,C	; C = 1 si Temps+1 >= Periode+1
	goto	miratemps	; Temps+1 < Periode+1
				; Temps+1 >= Periode+1
	movf	Periode+1,w
	xorwf	Temps+1,w	; Ho comparem amb Temps+1
	btfss	STATUS,Z
	goto	sipols		; Si són diferents és que Temps+1 > Periode+1
	movf	Periode,w
	subwf	Temps,w		; W = Temps - Periode
	btfss	STATUS,C	; C = 1 si Temps >= Periode
	goto	miratemps	; Temps < Periode
sipols
	decfsz	Comp,f		; Decrementa Comp
	goto	miratemps	; Si no ha arribat a zero, ja estem
	bsf	Bits,0		; Activa Pols
	incf	comptador,f		; L'afegim al byte de la dreta
	movf	Temps+1,w
	movwf	Periode+1	; Periode+1 = Temps+1
	movf	Temps,w
	movwf	Periode		; Periode = Temps
	bcf	STATUS,C	; Volem entrar un zero
	rrf	Periode+1,f	; Dividim Periode per 2
	rrf	Periode,f
	clrf	Temps		; Posem Temps a zero
	clrf	Temps+1		; Posem Temps+1 a zero
	movlw	ValComp		; Nombre de repeticions per eliminar soroll
	movwf	Comp		; Ho posa a Comp
	btfss	Bits,3		; Mira si Tenim1 està activat
	goto	tenimpols	; Si no ho està, l'activa i surt
	btfss	Bits,2		; Mira si Estable està activat
	bsf	Bits,2		; Si no ho estava, l'activa
	goto	miratemps
activat
	movf	Centre,w
	subwf	Lectura,w	; W = Lectura - Centre
	btfsc	STATUS,C	; C = 1 si Lectura >= Centre
	goto	miratemps	; Lectura > Centre
				; Lectura <= Centre
	decfsz	Comp,f		; Decrementa Comp
	goto	miratemps	; Si no ha arribat a zero, ja estem
	bcf	Bits,0		; Desactiva Pols
	movf	Min,w
	movwf	Centre		; Guarda Min, provisionalment, a Centre
	movf	Max,w
	addwf	Centre,f	; Centre = Max + Min
				; Si ens en portem, quedarà a C
	rrf	Centre,f	; Dividim la resta per dos (les que portem entren per l'esquerra)
	movf	Centre,w	; El resultat queda a Centre
	movwf	Max		; I el copiem a Max
	movwf	Min		; i a Min
	movlw	ValComp		; Nombre de repeticions per eliminar soroll
	movwf	Comp		; Ho posa a Comp
miratemps
	movlw	.4		; Equival a menys de 30 pulsacions per minut
	subwf	Temps+1,w	; W = Temps+1 - 4
	btfss	STATUS,C	; C = 1 si Temps+1 >= 4
	goto	Decr		; Temps+1 < 4
reinici
	clrf	Bits		; Posa tots els bits a zero
	clrf	Periode		; Posem Periode a zero
	clrf	Periode+1	; Posem Periode+1 a zero
	clrf	Temps		; Posem Temps a zero
	clrf	Temps+1		; Posem Temps+1 a zero
	movlw	.127		; Valor central del conversor (255/2)
	movwf	Centre		; Ho posa a Centre
	movwf	Max		; Ho posa a Max
	movwf	Min		; Ho posa a Min
	movlw	ValComp		; Nombre de repeticions per eliminar soroll
	movwf	Comp		; Ho posa a Comp
	goto	Decr
tenimpols
	bsf	Bits,3		; Si no ho estava, l'activa
Decr
	movf	Bits,w		; Agafa el valor de Bits
	movwf	PORTC		; Ho posa al port C; Només actúa el bit 0 (Pols)
	movf	tiempo,f		; Copiem Resul sobre ell mateix per veure si és zero
	btfsc	STATUS,Z	; Mirem si s'activa Z
	decf	tiempo+1,f	; Si s'activa, decrementem el byte superior
	decfsz	tiempo,f	; Decrementem el byte de la dreta
	goto	nozero
	movf	tiempo+1,f
	btfsc	STATUS,Z	
	goto	panta
nozero
	goto	FiInt
panta	
	movf	comptador,w
	movwf	pantalla
	clrf 	pantalla2
	movlw 	.4
	movwf 	comptador2
BucleSum
	movf 	pantalla,w
	addwf 	pantalla2,f
	decfsz 	comptador2,f
	goto 	BucleSum
	clrf	comptador
	movlw	b'01001100'    
	movwf	tiempo
	movlw	b'11101'
	movwf	tiempo+1	
FiInt
	swapf	ST_Copia,w	; Copia permutant ST_Copia a l'acumulador
	movwf	STATUS		; I ho passa a STATUS recuperant el valor d'abans
				; de la interrupció
	swapf	W_Copia,f	; Permuta els bits de W_Copia
	swapf	W_Copia,w	; Torna a permutar els bits de W_Copia
				; i els guarda a l'acumulador sense variar STATUS
	bsf	INTCON,GIE	; Reactiva les interrupcions a l'acabar
	retfie			; Torna al programa principal, on s'havia quedat		
Inici
	clrf 	pantalla2
	movlw 	.4
	movwf 	comptador2
	movlw	b'01001100'    
	movwf	tiempo
	movlw	b'11101'
	movwf	tiempo+1
	clrf	comptador
	bsf	STATUS,RP0	; Tria el banc 1
	movlw	b'10000010'	; Configuració de Timer0
				; Com a temporitzador basat en rellotge
				; 010 - Factor d'escala de 8
				; I resistències de pull-up desactivades (valor per defecte)
	movwf	OPTION_REG	; Ho guarda al registre de configuració del Timer0
	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		; Tot el port C és de sortida
	movlw	b'00010000'	; Posa el conversor a 1/8 de la freqüència
	movwf	ADCON1		; Copia W a la configuració del conversor A/D	
	bcf	STATUS,RP0
	bsf	STATUS,RP1	; Tria el banc 2
	movlw	b'00000101'
	movwf	ANSEL		; Configura port AN0 i AN2 com entrades analògiques
	bcf	STATUS,RP1	; Tria el banc 0
	movlw	b'00001001'	; activa el conversor A/D connectat a AN2
	movwf	ADCON0		; amb el resultat justificat per l'esquerra
				; Inicialització de variables
	clrf	Bits		; Posa tots els bits a zero
	clrf	Periode		; Posem Periode a zero
	clrf	Periode+1	; Posem Periode+1 a zero
	clrf	Temps		; Posem Temps a zero
	clrf	Temps+1		; Posem Temps+1 a zero
	movlw	.127		; Valor central del conversor (255/2)
	movwf	Centre		; Ho posa a Centre
	movwf	Max		; Ho posa a Max
	movwf	Min		; Ho posa a Min
				; Configurem el Timer i activem interrupcions
	movlw	ValComp		; Nombre de repeticions per eliminar soroll
	movwf	Comp		; Ho posa a Comp
	movlw	.7		; Presselecció de 7, que són 249 iteracions
	movwf	TMR0		; Ho posa com a preselecció del temporitzador
	movlw	b'10100000'	; Activem GIE i T0IE
	movwf	INTCON		; Activa les interrupcions globals i la de Timer0
Bucle	
	movlw	0x00		; Adreça DDRAM (Filera 1 - Posició 1)
	iorlw	b'10000000'	; Posa el bit de DDRAM a 1
	movwf	Caracter	; Ho guarda a la variable
	call	EnviaC		; Ho envia
Canvipant	
	call	IniPant		; Inicialització del mode de funcionament de la pantalla
	call	ConfPant	; Configuració de la pantalla
	movf	pantalla2,w
	btfsc	STATUS,Z
	goto	Calculator
	call	BCD
	call	ASCII
	movf	D3,w
	movwf	Caracter
	call	EnviaL
	movf	D2,w
	movwf	Caracter
	call	EnviaL
	movf	D1,w
	movwf	Caracter
	call	EnviaL
	goto	Bucle		; En el bucle no hi ha res
Calculator
	movlw	'C'		; Lletra
	movwf	Caracter	; Ho guarda a la variable
	call	EnviaL		; Ho envia
	movlw	'A'		; Lletra
	movwf	Caracter	; Ho guarda a la variable
	call	EnviaL		; Ho envia
	movlw	'L'		; Lletra
	movwf	Caracter	; Ho guarda a la variable
	call	EnviaL		; Ho envia
	movlw	'C'		; Lletra
	movwf	Caracter	; Ho guarda a la variable
	call	EnviaL		; Ho envia
	movlw	'.'		; Lletra
	movwf	Caracter	; Ho guarda a la variable
	call	EnviaL		; Ho envia
	movlw	'.'		; Lletra
	movwf	Caracter	; Ho guarda a la variable
	call	EnviaL	
	movlw	'.'		; Lletra
	movwf	Caracter	; Ho guarda a la variable
	call	EnviaL	
	goto	Canvipant
IniPant					
	movlw	0		; Comença un cicle de durada fixa (0,2 s)
				; Temps que cal esperar després d'un reset
	call	Retard		; Crida a la funció Retard, el paràmetre està a W
	movlw	b'00100000'	; Function set - Configuració inicial  0010 al nibble de l'esquerra
	movwf	Caracter	; Ho guarda a la variable
	call	EnviaI		; Envia els 4 bits superiors
				; Ara enviem la configuració 2 línea, 5x8 píxels  0010 1000
	call	EnviaI		; Enviem la part esquerra (ja ho teníem a Caracter)
	movlw	b'10000000'	; I ara la part dreta (però posada a l'esquerra)
	movwf	Caracter	; Ho guarda a la variable
	call	EnviaI		; Envia els 4 bits superiors
	return			; Fi de la inicialització del mode de funcionament
				;
				; Configuració de la pantalla
				;
ConfPant			
	movlw	b'00001111'	; Display ON/OFF control - Activa la pantalla amb cursor intermitent
	movwf	Caracter	; Ho guarda a la variable
	call	EnviaC		; Ho envia
	movlw	b'00000001'	; Clear display - Buida la pantalla i inicialitza
	movwf	Caracter	; Ho guarda a la variable
	call	EnviaC		; Ho envia
	movlw	.5		; El punt indica que es un valor decimal
				; Comença un cicle de durada fixa (3,9 ms)
	call	Retard		; Crida a la funció Retard, el paràmetre està a W
	movlw	b'00000110'	; Entry mode - Buida la pantalla, sentit dreta i despl. automàtic
	movwf	Caracter	; Ho guarda a la variable
	call	EnviaC		; Ho envia
	return			; Fi de la configuració de la pantalla
				;
				; Enviem caràcters 
				;
EnviaC				; Enviem caràcters de control
	bcf	Control,7	; Desactiva E
	bcf	Control,5	; Desactiva RS
	goto	Envia
EnviaL				; Enviem caràcters a visualitzar
	bcf	Control,7	; Desactiva E
	bsf	Control,5	; Activa RS
Envia	
	call	EnviaN		; Envia els 4 bits més alts
	swapf	Caracter,f	; Permuta els nibbles
	call	EnviaN		; Envia els 4 bits més alts
	swapf	Caracter,f	; Torna a deixar els nibbles com estaven
	return				; Tornem al lloc des d'on hem vingut
EnviaI					; Enviem nibbles de caràcters de control
	bcf	Control,7	; Desactiva E
	bcf	Control,5	; Desactiva RS
EnviaN					; Enviem nibbles
	decfsz	Retard1,f	; Funció de retard de 0,8 ms
	goto	EnviaN
	movf	Control,w	; Copia Control a l'acumulador
	movwf	PORTB		; I ho posa al PORTB
	nop			; Espera 1 us
	nop			; Espera 1 us
	nop			; Espera 1 us
	movf	Caracter,w	; Llegeix el caràcter
	andlw	0xF0		; Agafa els 4 bits més alts
	movwf	PORTC		; Envia el byte
	bsf	Control,7	; Activa E
	movf	Control,w	; Copia Control a l'acumulador
	movwf	PORTB		; I ho posa al PORTB
	nop			; Espera 1 us
	nop			; Espera 1 us
	nop			; Espera 1 us
	nop			; Espera 1 us
	nop			; Espera 1 us
	bcf	Control,7	; Desactiva E
	movf	Control,w	; Copia Control a l'acumulador
	movwf	PORTB		; I ho posa al PORTB
	return			; Tornem al lloc des d'on hem vingut
				;
				; Funció Retard, W conté el nombre de cicles de 771 us que cal fer 
				;
Retard				
	movwf	Retard2		; Ho copia a la variable Retard2
BucRet	
	decfsz	Retard1,f	; Decrementa la variable 1
				; si dona zero, no es fa la instrucció següent
	goto	BucRet		; Salta, excepte si el resultat ha estat zero
	decfsz	Retard2,f	; Decrementa la variable 2
	goto	BucRet		; Salta, excepte si el resultat ha estat zero
	return			; Tornem al lloc des d'on hem vingut
				;
				; 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	STATUS,C	; 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	STATUS,C	; 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
ASCII
	movlw	'0'		; Carrega el codi ASCII del número 0
				; Sumant-li la xifra tindrem el codi ASCII
	addwf	D3,f		; Ho afegeix al dígit
	addwf	D2,f		; Ho afegeix al dígit
	addwf	D1,f		; Ho afegeix al dígit
	movf	D3,w		; Llegeix el dígit
	xorlw	'0'		; Compara amb 0
	btfss	STATUS,Z	; Si Z està activat eren iguals
	return			; Si no eren iguals, ja estem
	movlw	' '		; Carrega un espai en blanc
	movwf	D3		; Substitueix el 0 per l'espai
	movf	D2,w		; Llegeix el dígit
	xorlw	'0'		; Compara amb 0
	btfss	STATUS,Z	; Si Z està activat eren iguals
	return			; Si no eren iguals, ja estem
	movlw	' '		; Carrega un espai en blanc
	movwf	D2		; Substitueix el 0 per l'espai
	return
	end	

 

 

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