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

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