Programació en C del PIC 16F690

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

Monitor cardíac

En aquest projecte volem fer un sistema per monitoritzar el ritme cardíac. Per fer-ho disposarem d'un sensor que ens dona un senyal analògic amb una forma aproximada del pols cardíac. Aquest sensor el tindrem connectat a l'entrada analògica AN8 de la placa amb una matriu de vuit per vuit LED tricolor que incorpora una pantalla sèrie, un brunzidor i cinc polsadors.

sensor

El sensor incorpora un LED i un sensor de llum, a part d'altres elements electrònics. Es coloca sobre el dit (amb una cinta que l'aguanta) o al lòbul de l'orella (amb una pinça). El sensor de llum rep més o menys llum provinent del LED segons el moment del cicle cardíac. El senyal de sortida del sensor és similar al que es mostra a la figura següent. Els valors concrets poden ser diferents segons el ritme cardíac, la tensió d'alimentació i la forma com està col·locat el sensor.

senyal

Veiem que, fonamentalment, el senyal té una zona vall i un pols. Ens interessen els polsos. Seguint les recomanacions del fabricant, considerarem que es passa de pols a vall en el centre del senyal. Per trobar el centre agafarem el valor màxim i el mínim i cercarem el punt mig. Considerarem que el cicle cardíac comença cada cop que travessem el valor central del senyal en sentit ascendent. A la següent gràfica s'indiquen els valors que acabem de comentar i, en vermell, el nom de la variable que farem servir per guardar-los. Els noms en verd no es corresponen estrictament amb les variables del mateix nom.

mesura

Atès que no ens cal molta precisió, llegirem el senyal analògic amb només vuit bits. El nostre programa detecta els inicis de pols i en mesura el període; a més encén un LED quan hi ha el pols i l'apaga a la zona vall. Farem servir el Timer 1 per fer una lectura cada 2 ms. Anem a veure quina pot ser la configuració del Timer 1. La taula següent té les possibles opcions:

Bits Escala Període Iteracions Preselecció
11 1/8 8 μs 250 65286
10 1/4 4 μs 500 65036
01 1/2 2 μs 1000 64536
00 1/1 1 μs 2000 63536

Hem escollit un factor de 8, de manera que el temporitzador s'incrementarà cada 8 μs. Atès que cal fer 250 iteracions per tenir 2 ms, calculem les preseleccions:

	TMR1 = 65536 - 250 = 65286
	TMR1H = 65286 / 256 = 255
	TMR1L = 65286 % 256 = 6

Presentarem dues formes de llegir el sensor. En la primera, més senzilla, tindrem una funció que anirà fent lectures del sensor cada 15 s i ens retornarà el nombre de pulsacions per minut. En el segon mètode farem servir una funció d'interrupció que anirà determinant, pràcticament en temps real, el període del ritme cardíac. Cada mètode presenta avantatges i inconvenients. Amb el primer triguem més de 15 s entre l'inici de la mesura i el resultat però ja tenim directament les pulsacions; en canvi, amb el segon tenim mesures més seguides. Si fem servir la matriu de LED, atès que el segon mètode fa servir interrupcions, pot interferir-se amb les interrupcions de la matriu (que, recordem, tenen una funció que dura força temps) i això pot portar a mesures que no siguin del tot correctes.

Versió senzilla

Veiem que, fonamentalment, el senyal té una zona vall i un pols. Ens interessen els polsos. El fabricant, recomana considerar que es passa de pols a vall (o al contrari) en el centre del senyal. Per trobar el centre agafarem el valor màxim i el mínim i cercarem el punt mig, la mitjana. Per evitar problemes causats per petites oscil·lacions, considerarem que el pols comença quan el senyal supera la mitjana entre el centre i el màxim i que acaba quan baixa de la mitjana entre el centre i el mínim. A la següent gràfica s'indiquen els valors que acabem de comentar i, en vermell, el nom de la variable que farem servir per guardar-los. En verd s'indica el període del senyal, que no farem servir.

mesura

A continuació presentarem una funció que primer cerca els valors que hem indicat a la imatge anterior (mentrestant Centre = 0) i després compta el nombre de polsos que es produeixen en quinze segons. Amb aquesta dada, calcula les pulsacions per minut, que és el valor que retorna. La funció també encén un LED quan hi ha el pols i l'apaga a la zona vall. Això és útil per veure si tenim el sensor ben posat en el dit. La determinació dels valors màxim, mínim i central es fa durant 2 s, temps suficient per veure entre un i uns pocs polsos. Les variables que emprarem en la funció seran les següents:

Nom Mida Finalitat Observacions
Max 1 byte Valor màxim del senyal en un període
Min 1 byte Valor mínim del senyal en un període
Centre 1 byte Valor mig del senyal en un període Centre = (Max + Min) / 2
Polsos 1 byte Durant l'execució, compta els polsos
Al final, conté les pulsacions per minut
Temps 2 bytes Compta el nombre de finals del timer, per comptar el temps
Lectura 1 byte Valor llegit a l'entrada analògica
Pols 1 byte Val 1 quan el senyal està per sobre del centre, sinó val 0

A continuació tenim un programa senzill que llegeix les pulsacions i les envia a la pantalla sèrie.

#pragma config FOSC = INTRCIO, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF
#pragma config CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF
#include "pic16f690.h"				// Carrega el fitxer d'adreces i paràmetres del PIC 16F690
#include <xc.h>					// Carrega el fitxer de funcions necessari per al compilador XC8
#define _XTAL_FREQ  4000000			// La freqüència del rellotge és 4 MHz
unsigned char Lectura;				// Valor llegit del sensor
unsigned char Pols;				// Val 1 quan el senyal està per sobre del valor mig
unsigned char Pulsac;	 			// Pulsacions per minut
char Digits[3];					// Variable amb el número dígit a dígit
						// Digits[0] són les unitats
						// Definició de les funcions que farem servir 
unsigned char Llegir(void);			// Llegeix les pulsacions
void Esborra(void);				// Esborra la pantalla i posa el cursor a l'inici
void BCD(unsigned char Valor);			// Converteix un nombre a BCD i a ASCII
void EnviaL(char Caracter);			// Envia un caràcter
void Cursor(char Filera, char Columna);		// Posiciona el cursor (filera 1 a 2 i columna 1 a 32, segons pantalla)
void main (void) {
	TRISA = 0xFF;				// Posa tots els bits del port A com a entrada
	TRISB = 0;				// Tot el port B és de sortida
	TRISC = 0xF0;				// Els LED són de sortida
	ADCON1 = 0b00010000;			// Posa el conversor a 1/8 de la freqüència
	TXSTAbits.BRGH = 1;			// Configuració de velocitat
	BAUDCTLbits.BRG16 = 0;			// Paràmetre de velocitat de 8 bits
	SPBRG = 25;				// Velocitat de 9600 baud
	TXSTAbits.SYNC = 0;			// Comunicació asíncrona
	TXSTAbits.TX9 = 0;			// Comunicació de 8 bits
	ANSEL = 0b00000101;			// Configura port AN0 i AN2 com entrades analògiques
	ANSELH = 0b00000001;			// Configura AN8 com entrada analògica
	RCSTAbits.SPEN = 1;			// Activa comunicació sèrie
	TXSTAbits.TXEN = 1;			// Activa comunicació
	 __delay_ms(100);	   	 	// Retard d'un segon
	Esborra();				// Esborra la pantalla i posa el cursor a l'inici
	T1CON = 0b00110000;			// Configuració de Timer1
						// 11 - Factor d'escala de 8
	ADCON0 = 0b00100001;			// activa el conversor A/D connectat a AN8
						// amb el resultat justificat per l'esquerra			
	PORTC = 0;				// Apaguem tots els LED
	TMR1L = 6;				// Nova preselecció
	TMR1H = 255;
	T1CONbits.TMR1ON = 1;			// Engega el Timer1
	PIR1bits.TMR1IF = 0;			// Desactiva el final de Timer1
	while (1) {				// Inici del bucle de programa
		Cursor(1, 1);			// Posició
		Pulsac = Llegir();		// llegeix les pulsacions per minut
		BCD(Pulsac);			// Converteix la lectura a BCD en ASCII
		for (int k = 3; k > 0; k--) {
			EnviaL(Digits[k-1]);	// Envia un caràcter
		}
		__delay_ms(5000);	   	// Retard de cinc segons
	}
}
unsigned char Llegir(void){
	unsigned char Max = 0;			// Valor màxim del senyal en un període	
	unsigned char Min = 255;		// Valor mínim del senyal en un període	
	unsigned char Centre = 0;		// Valor mig del senyal en un període	
	unsigned char Polsos = 0;		// Durant l'execució, compta els polsos
						//   al final, conté les pulsacions per minut
	unsigned int Temps = 0;			// Compta el nombre de finals del timer, per comptar el temps	
	unsigned char Pols = 0;			// Desactivem Pols
	unsigned char Lectura;			// Valor llegit a l'entrada analògica
	while(Temps <= 7500){			// Farem mesures durant 15 s
						// a partir del moment en el que trobem el centre
		if(PIR1bits.TMR1IF) {		// Només ho fa quan han passat 2 ms
			T1CONbits.TMR1ON = 0;	// Atura momentàniament el Timer1
			TMR1L = 6;		// Nova preselecció
			TMR1H = 255;
			T1CONbits.TMR1ON = 1;	// Engega el Timer1
			PIR1bits.TMR1IF = 0;	// Desactiva el final de Timer1
			ADCON0bits.GO = 1;	// Inicia la conversió
			while(ADCON0bits.GO==1)	// Mentre no acabi
				;		// ens esperem
			Lectura = ADRESH;	// Llegeix el valor (8 bits)
			Temps++;		// Incrementa Temps
			if(Centre == 0){	// Estem a la primera fase, buscant el centre
				if(Lectura > Max){
					Max = Lectura;
				}
				if(Lectura < Min){
					Min = Lectura;
				}
				if(Temps > 1000){
					Centre = (Max + Min) / 2;
						// Ja tenim el valor del centre de l'ona
					Temps = 0;		// Torna a iniciar el temps
				}
			} else {
				if(Pols == 1){	// Si busquem la vall
					if(Lectura < (Centre + Min)/2){
						Pols = 0;	// Hem trobat la vall
						RC0 = 0;		// Apaga el LED
					}
				} else {
					if(Lectura > (Centre + Max)/2){
						Pols = 1;	// Hem trobat el pic
						RC0 = 1;		// Encén el LED
						Polsos++;	// Afegim un pols
					}
				}
			}
		}
	}
	Polsos = Polsos * 4;
	return Polsos;
}
void BCD(unsigned char Valor) {
	Digits[0] = Valor % 10;			// Unitats
	Valor = Valor / 10;
	Digits[1] = Valor % 10;			// Milers
	Digits[2] = Valor / 10;			// Desenes de milers
	for (int j = 0; j < 3; j++){		// 5 dígits
		Digits[j] = Digits[j] + '0';	// Li sumem el codi ASCII de 0
	}
	if (Digits[2] == '0') {			// I mirem si ho és el tercer
		Digits[2] = ' ';		// Si ho és, hi posem un espai
		if (Digits[1] == '0') {		// I mirem si ho és el quart
			Digits[1] = ' ';	// Si ho és, hi posem un espai
		}				// El 0 de les unitats el mostrarem sempre
	}
}
void Esborra(void) {
	EnviaL(254);				// Caràcter de control
	EnviaL(1);				// Esborra la pantalla i posa el cursor a l'inici
}
void EnviaL(char Caracter) {
	TXREG = Caracter;			// Agafa el caràcter i l'envia
	_delay(5);				// Donem temps
	while (PIR1bits.TXIF == 0)		// Esperem que s'acabi d'enviar
		;				// No fem res
}
void Cursor(char Filera, char Columna) {
	char Posicio = 0;			// Variable per a calcular la posició
	if (Filera == 2) {
		Posicio = 64;			// La primera columna de la segona fila és 64;
	}
	if (Columna > 0 && Columna < 33) {	// Comprovem que sigui un valor raonable
		Posicio = Posicio + Columna;	// Sumem les adreces
		Posicio = Posicio - 1;		// Restem 1 perquè numera des de 0
	}
	Posicio = Posicio + 128;		// Posa el bit de posicionat a 1
	EnviaL(254);				// Control de la posició del cursor
	EnviaL(Posicio);			// Canvia el cursor de lloc
}

Versió basada en interrupcions

La lectura i el tractament del sensor el farem amb una funció d'interrupció que es representa al diagrama següent. En el diagrama hem indicat, amb text de color verd, les etiquetes a les que salta el programa en cada punt. Podem observar que la funció té tres parts: una primera en la que es guarden els valors màxims i mínims del senyal mesurat, una segona en la que es fa el tractament del senyal per detectar els inicis i finals de pols i una tercera en la que es detecta que el ritme cardíac és inferior a 30 pulsacions per minut.

programa

Les variables que emprarem seran les següents:

Nom Mida Finalitat Observacions
Lectura unsigned char Valor llegit a l'entrada analògica
Temps unsigned int S'incrementa cada cop que es fa la interrupció
(cada 2 ms)
Max unsigned char Valor màxim del senyal en un període
Min unsigned char Valor mínim del senyal en un període
Centre unsigned char Valor mig del senyal en un període Centre = (Max + Min) / 2
Periode unsigned int Quart de període (en ms) Guarda la meitat del nombre d'interrupcions
entre dos inicis de pols
Comp unsigned char Comptador per filtrar soroll
Port unsigned char Valor que enviarem al port C
Pols unsigned char S'activa quan el senyal està per sobre del valor mig Bit 0 del port C
Tenim1 unsigned char S'activa quan ja hem detectat l'inici del primer pols Bit 3 del port C
Estable unsigned char S'activa quan ja hem detectat l'inici del segon pols i,
per tant, ja tenim dades útils
Bit 2 del port C

La primera cosa que fem a cada interrupció és llegir l'entrada AN8, on tenim el sensor, i incrementar la variable Temps. Si el valor llegit és superior a Centre, mirarem si és més gran que el màxim que tenim guardat. En cas afirmatiu guardarem el nou valor com a màxim. Per al mínim fem una cosa similar però amb un afegit. És freqüent que, després del pic, hi hagi un segon pic en sentit contrari i, també, que hi hagi soroll en la zona vall. Per això no començarem a cercar el mínim fins que hagi passat mig període. Atès que no sabem el que dura un cicle fins que no ha acabat, fem servir les dades del cicle anterior.

A la segona part de la funció mirem si estàvem (a la interrupció anterior) en la part superior (Pols = 1) o en la inferior (Pols = 0). En la superior comprovem si estem per sota de la meitat, en quin cas voldria dir que ja deixem d'estar a la part superior. Una comprovació similar fem en la part inferior però comprovant que hem passat de mig període com a mesura per filtrar soroll. En tots dos casos no fem res fins que hem detectat que estem per sobre o per sota del mig sis vegades (que comptem amb la variable Comp) per tal de filtrar soroll. Quan ja està clar que estem per sota del valor mig desactivem Pols i calculem uns nous valors de Max, Min i Centre a partir del pols que acabem de veure. D'altra banda, quan ja està clar que estem per sobre del valor mig actualitzem el valor de la variable Periode i reinicialitzem la variable Temps. En tots dos casos reiniciem Comp.

Els valors de les variables només són fiables quan ja hem vist dos inicis de pols. Tenim dos bits de control que ens indiquen si les dades són estables o no. Inicialment els bits Tenim1 i Estable valen zero. Quan s'ha detectat el primer inici de pols s'activarà Tenim1 i quan es detecti el segon s'activarà Estable.

A la tercera part es mira si el temps transcorregut és superior a 2,048 s (la variable Temps és més gran que 1024) i si és així es reinicialitzen totes les variables per tornar a buscar el primer pols.

Disposarem també d'una pantalla sèrie on podrem indicar, per exemple, les pulsacions per minut. També podem mostrar altres valors o escriure text.

Si, per exemple, ens interessés mostrar les pulsacions a la pantalla, podríem comptar quants polsos es fan en un temps determinat. Per comptar el temps, podem incrementar una variable apropiada sabent que la funció d'interrupció s'executa cada 2 ms.

El programa de prova que conté la funció d'interrupció que hem comentat és el següent. Podem observar que en el bucle principal no hi ha gran cosa, només escrivim el valor de la variable Periode a la pantalla.

#pragma config FOSC = INTRCIO, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF
#pragma config CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF
#include "pic16f690.h"				// Carrega el fitxer d'adreces i paràmetres del PIC 16F690
#define	ValComp	6				// Nombre de repeticions per eliminar soroll
#include <xc.h>					// Carrega el fitxer de funcions necessari per al compilador XC8
#define _XTAL_FREQ  4000000			// La freqüència del rellotge és 4 MHz
unsigned char Lectura;				// Valor llegit a l'entrada analògica	
unsigned int Temps;				// S'incrementa cada cop que es fa la interrupció (cada 2 ms)	
unsigned char Max;				// Valor màxim del senyal en un període	
unsigned char Min;				// Valor mínim del senyal en un període	
unsigned char Centre;				// Valor mig del senyal en un període	
unsigned int Periode;				// Quart de període
						// Guarda la meitat del nombre d'interrupcions entre dos inicis de pols
unsigned char Comp;				// Comptador per filtrar soroll
unsigned char Port;				// Valor que enviarem al port C	
unsigned char Pols;				// S'activa quan el senyal està per sobre del valor mig
unsigned char Tenim1;				// S'activa quan ja hem detectat l'inici del primer pols
unsigned char Estable;				// S'activa quan ja hem detectat l'inici del segon pols
char Digits[5];					// Variable amb el número dígit a dígit
						// Digits[0] són les unitats
						// Definició de les funcions que farem servir 
void BCD(unsigned int Valor);			// Converteix un nombre a BCD i a ASCII
void EnviaL(char Caracter);			// Envia un caràcter
void Cursor(char Filera, char Columna);		// Posiciona el cursor (filera 1 a 2 i columna 1 a 32, segons pantalla)
void main (void) {
	TRISA = 0xFF;				// Posa tots els bits del port A com a entrada
	TRISB = 0;				// Tot el port B és de sortida
	TRISC = 0xF0;				// Els LED són de sortida
	ADCON1 = 0b00010000;			// Posa el conversor a 1/8 de la freqüència
	PIE1bits.TMR1IE = 1;			// Activa les interrupcions del timer 1
	TXSTAbits.BRGH = 1;			// Configuració de velocitat
	BAUDCTLbits.BRG16 = 0;			// Paràmetre de velocitat de 8 bits
	SPBRG = 25;				// Velocitat de 9600 baud
	TXSTAbits.SYNC = 0;			// Comunicació asíncrona
	TXSTAbits.TX9 = 0;			// Comunicació de 8 bits
	RCSTAbits.SPEN = 1;			// Activa comunicació sèrie
	TXSTAbits.TXEN = 1;			// Activa comunicació
	ANSEL = 0b00000101;			// Configura port AN0 i AN2 com entrades analògiques
	ANSELH = 0b00000001;			// Configura AN8 com entrada analògica
	ADCON0 = 0b00100001;			// activa el conversor A/D connectat a AN8
						// amb el resultat justificat per l'esquerra			
	Temps = 0;				// Inicialització de variables
	Periode = 0;
	Pols = 0;
	Tenim1 = 0;
	Estable = 0;
	Centre = 127;
	Max = 127;
	Min = 127;
	Port = 0b00000000;			// Tots els bits a zero
	PORTC = Port;				// Apaguem tots els LED
	Comp = ValComp;				// Nombre de repeticions per eliminar soroll
	TMR1L = 6;				// Nova preselecció
	TMR1H = 255;
	T1CON = 0b00110000;			// Configuració de Timer1
						// 11 - Factor d'escala de 8
	PIR1bits.TMR1IF = 0;			// Desactivem el bit de fi del temporitzador
	T1CONbits.TMR1ON = 1;			// Engega el Timer1
	INTCON = 0b11000000;			// Activa les interrupcions globals i les de PIE1 i PIE2
	while (1) {				// Inici del bucle de programa
		Cursor(1, 1);			// Posició
		BCD(Periode);
		for (int k = 5; k > 0; k--) {
			EnviaL(Digits[k-1]);	// Envia un caràcter
		}
		__delay_ms(1000);	   	// Retard d'un segon
	}
}
void BCD(unsigned int Valor) {
	Digits[0] = Valor % 10;			// Unitats
	Valor = Valor / 10;
	Digits[1] = Valor % 10;			// Desenes
	Valor = Valor / 10;
	Digits[2] = Valor % 10;			// Centenes
	Valor = Valor / 10;
	Digits[3] = Valor % 10;			// Milers
	Digits[4] = Valor / 10;			// Desenes de milers
	for (int j = 0; j < 5; j++){		// 5 dígits
		Digits[j] = Digits[j] + '0';	// Li sumem el codi ASCII de 0
	}
	if (Digits[4] == '0') {			// Mirem si el primer dígit és 0
		Digits[4] = ' ';		// Si ho és, hi posem un espai
		if (Digits[3] == '0') {		// I mirem si ho és el segon
			Digits[3] = ' ';	// Si ho és, hi posem un espai
			if (Digits[2] == '0') {			// I mirem si ho és el tercer
				Digits[2] = ' ';		// Si ho és, hi posem un espai
				if (Digits[1] == '0') {		// I mirem si ho és el quart
					Digits[1] = ' ';	// Si ho és, hi posem un espai
				}		// El 0 de les unitats el mostrarem sempre
			}
		}
	}
}
void EnviaL(char Caracter) {
	TXREG = Caracter;			// Agafa el caràcter i l'envia
	_delay(5);				// Donem temps
	while (PIR1bits.TXIF == 0)		// Esperem que s'acabi d'enviar
		;				// No fem res
}
void Cursor(char Filera, char Columna) {
	char Posicio = 0;			// Variable per a calcular la posició
	if (Filera == 2) {
		Posicio = 64;			// La primera columna de la segona fila és 64;
	}
	if (Columna > 0 && Columna < 33) {	// Comprovem que sigui un valor raonable
		Posicio = Posicio + Columna;	// Sumem les adreces
		Posicio = Posicio - 1;		// Restem 1 perquè numera des de 0
	}
	Posicio = Posicio + 128;		// Posa el bit de posicionat a 1
	EnviaL(254);				// Control de la posició del cursor
	EnviaL(Posicio);			// Canvia el cursor de lloc
}
void __interrupt() temporit(void){
	if  (PIR1bits.TMR1IF) {			// Comprovem que hi ha interrupció per Timer 1
		T1CONbits.TMR1ON = 0;		// Atura momentàniament el Timer1
		TMR1L = 6;			// Nova preselecció
		TMR1H = 255;
		T1CONbits.TMR1ON = 1;		// Torna a activar el Timer1
		PIR1bits.TMR1IF = 0;		// Desactivem el bit
		ADCON0bits.GO = 1;		// Inicia la conversió
		while (ADCON0bits.GO == 1)	// Mentre no acabi
			;    			// ens esperem
		Lectura = ADRESH;		// Llegeix el valor (8 bits)
		Temps++;			// Incrementem Temps
		if (Lectura > Centre) {
			if (Lectura > Max) {
				Max = Lectura;	// Guarda el nou màxim
			}
		} else {
			if ((Temps > Periode) && (Lectura < Min)) {
				Min = Lectura;	// Guarda el nou mínim
			}
		}
		if (Pols == 1) {
			if (Lectura < Centre) {
				Comp--;		// Decrementa Comp
				if (Comp == 0) {
					Pols = 0;		// Desactiva Pols
					Centre = Max/2 + Min/2;
					Max = Centre;
					Min = Centre;
					Comp = ValComp;		// Nombre de repeticions per eliminar soroll
				}
			}
		} else {
			if ((Temps > Periode) && (Lectura > Centre)) {
				Comp--;		// Decrementa Comp
				if (Comp == 0) {
					Pols = 1;		// Activa Pols
					Periode = Temps/2;	// Nou valor de Periode
					Temps = 0;		// Reiniciem Temps
					Comp = ValComp;		// Nombre de repeticions per eliminar soroll
					if (Tenim1 == 0) {
						Tenim1 = 1;	// Ja tenim un inici de pols
					} else {
						if (Estable == 0) { 
							Estable = 1;		// Ja tenim dos inicis de pols
						}
					}
				}
			}
		}
		if (Temps > 1024) {
			Temps = 0;		// Reinici de variables
			Periode = 0;
			Pols = 0;
			Tenim1 = 0;
			Estable = 0;
			Centre = 127;
			Max = 127;
			Min = 127;
			Comp = ValComp;		// Nombre de repeticions per eliminar soroll
		}
		if (Pols == 1) {
			Port = Port | 0b00000001;		// Activa bit 0
		} else {
			Port = Port & 0b11111110;		// Desactiva bit 0
		}
		if (Tenim1 == 1) {
			Port = Port | 0b00001000;		// Activa bit 3
		} else {
			Port = Port & 0b11110111;		// Desactiva bit 3
		}
		if (Estable == 1) {
			Port = Port | 0b00000100;		// Activa bit 2
		} else {
			Port = Port & 0b11111011;		// Desactiva bit 2
		}
		PORTC = Port;			// Ho copiem als LED
	}
}

 

 

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