Programació en C del PIC 16F690 amb PICkit 2

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

La placa de la matriu de vuit per vuit LED

Aquesta és una placa que hem desenvolupat per a fer projectes. En ella hi tenim els mateixos elements que a la placa PICkit 2 i, a més, una pantalla sèrie, un brunzidor piezoelèctric, un conjunt de cinc polsadors connectats a una entrada analògica i una matriu de vuit per vuit LED tricolor que podrem fer servir com ens sembli més convenient.

Placa de la matriu de LED

En la placa, les següents potes del microcontrolador ja tenen utilitat:

Nom Entrada Pota PIC Utilització
ICSPDAT RA0 19 Programació
ICSPCLK RA1 18
VPP RA3 4
T1G RA4 3
AN0 RA0 19 Potenciòmetre
AN2 RA2 17 Cinc polsadors
RA3 RA3 4 Polsador
RA5 RA5 2 Lliure
RB4 RB4 13 Matriu LED
RB5 RB5 12
RB6 RB6 11
TX RB7 10 Pantalla sèrie
RC0 RC0 16 LED
RC1 RC1 15
RC2 RC2 14
RC3 RC3 7
P1A RC5 5 Brunzidor piezoelèctric
RC4 RC4 6 Lliures
AN8 RC6 8
AN9 RC7 9

Important: Si es fa servir la pantalla sèrie i la matriu de LED en el mateix programa hi pot haver conflictes. Quan s'inicia la comunicació sèrie (activant el bit SPEN) la pota RB5 passa a estar configurada com a entrada (independentment de l'estat de TRISC) i, per tant, la comunicació amb la matriu de LED queda bloquejada. Per evitar el problema convé desactivar les interrupcions (per evitar que aquestes enviïn dades a la matriu de LED) i activar la comunicació sèrie abans de cada transmissió. A l'acabar la transmissió desactivarem la comunicació i tornarem a activar les interrupcions.

void EnviaL(char Caracter) {
	INTCONbits.GIE = 0;			// Desactiva les interrupcions momentàniament
	RCSTAbits.SPEN = 1;			// Activa comunicació sèrie
	TXSTAbits.TXEN = 1;			// Activa comunicació
	TXREG = Caracter;			// Agafa el caràcter i l'envia
	__delay_ms(1);				// Donem temps
	while (PIR1bits.TXIF == 0);		// Esperem a que s'acabi d'enviar
		;				// No fem res
	RCSTAbits.SPEN = 0;			// Desactiva comunicació sèrie
	TXSTAbits.TXEN = 0;			// Desactiva comunicació
	INTCONbits.GIE = 1;			// Activa les interrupcions
}

L'entrada RA3 està habitualment activada i es desactiva quan es prem el polsador.

No és convenient emprar els pins de programació si es preveu alimentar la placa a través del programador.

La pota RA3 en la que està connectat el polsador també és emprada pel programador. Això pot fer que hi hagi conflictes entre ells. A l'exemple PB es comenten les precaucions que cal tenir per a evitar-ho.

Matriu de LED

La matriu de LED conté 64 LED tricolor o sigui que hi ha 192 elements. Seria realment complex fer el connexionat d'aquests elements amb el microcontrolador, fins i tot fent servir registres de desplaçament. Per això el fabricant ha optat per un disseny en el que només cal connectar 32 potes, que ja és prou complicat. La següent imatge mostra com estan disposats els LED i el lloc on queden les potes. Encara que les potes estan a la part inferior, la imatge és vista des de la part superior.

Connexions internes de la matriu de LED

Els LED estan connectats de manera que tots els LED de la mateixa filera tenen el càtode (born negatiu) comú i tots els de la mateixa columna i el mateix color tenen l'ànode (born positiu) comú. La següent imatge ens mostra l'esquema de connexionat en el que s'indica el número de pota que correspon a cada punt de connexió.

Distribució de potes a la matriu de LED

Aquestes matrius no permeten encendre simultàniament tots els LED desitjats ja que per activar un LED cal posar a 1 la seva columna (ànode, positiu) i a 0 la seva filera (càtode, negatiu). La manera de funcionar serà doncs treballar de forma seqüencial, filera per filera o columna per columna.

Els LED tricolor no només ens permeten obtenir els tres colors que incorporen (vermell, blau i verd) sinó alguns colors més. En teoria, combinant aquests tres colors (amb diferents intensitats) podem obtenir quasi infinits colors. Però nosaltres només podem tenir els colors activats o desactivats (sense variar-ne la intensitat) i, per tant, el nombre de possibles colors és reduït. En principi, disposem dels de la taula següent:

Vermell (R) Verd (G) Blau (B) Color
1 0 0 Vermell
0 1 0 Verd
0 0 1 Blau
1 1 0 Groc
1 0 1 Magenta
0 1 1 Cian
1 1 1 Blanc

Alternant de forma ràpida dues o més combinacions podem fer alguns colors intermedis; per exemple:

Vermell (R) Verd (G) Blau (B) Color
1 0 1 Morat
0 0 1

Aquests LED els controlarem amb uns xips especials per controlar blocs de LED, els MAX7221.

El circuit que farem servir és el següent. Només hem representat la part corresponent a la matriu de LED, els polsadors i el brunzidor.

Circuit per a la matriu de LED

Cada un dels tres MAX7221 es connecta a les fileres i a les columnes d'un determinat color. Per tant, hi ha un MAX7221 per a cada un dels tres colors. Per poder controlar tots aquests LED cal fer-ho filera per filera o columna per columna. D'això se n'ocuparà directament el MAX7221 i el microcontrolador no se n'haurà d'ocupar.

A l'hora de funcionar, anirem activant seqüencialment un dels tres xips que s'encarregarà d'encendre els LED corresponents al seu color. Anant prou ràpid com perquè no es noti que els colors s'activen seqüencialment, donarem la sensació de que els tres colors estan actius al mateix temps en els LED que els correspon. Aquesta activació seqüencial dels tres xips sí que serà responsabilitat del microcontrolador. Cal repartir els temps entre els tres xips de manera equilibrada perquè sinó els colors no es combinaran correctament. Per això aquesta tasca l'encomanarem a una imterrupció controlada amb el Timer0

Cada MAX7221 és capaç de memoritzar l'estat dels 64 LED que controla. Això vol dir que nosaltres enviarem als xips el patró del dibuix que volem mostrar un cop i no caldrà tornar-ho a enviar fins que canviem el dibuix. Aquesta és una diferència important respecte als registres de desplaçament als que hauríem hagut d'estar enviant les dades constantment i això ens hauria fet necessari un microcontrolador més ràpid. Per enviar les dades als MAX7221 ho farem en forma sèrie, com amb els registres de desplaçament. A cada xip li haurem d'enviar vuit blocs (un per filera) de vuit bits però ho haurem de fer enviant conjunts de setze bits en els que hi haurà la indicació de la filera i l'estat dels LED d'aquesta filera. Com els xips els connectarem un darrera l'altre (com amb els registres de desplaçament), haurem d'enviar blocs de 48 bits (sis bytes). Atès que només enviem una filera cada cop, només cal enviar aquelles fileres que hagin canviat respecte a la situació anterior.

A l'hora d'enviar els setze bits a un MAX7221, primer hem d'enviar el bit més significatiu (15) i després els següents. Si enviem més de setze bits, els primers que hem enviat passaran cap al xip següent de la cadena. La comunicació es fa mitjançant tres potes dels xips: Data (DIN, 1), Clock (CLK, 13) i Latch (CS, 12). Si CS està desactivat, cada cop que activem CLK es considerarà que el valor a DIN és un nou bit; aquest entrarà i farà rodar tots els que ja estan a dins i els primers que haguem entrat sortiran cap al xip següent. Quan haguem acabat d'enviar-los, activarem CS i cada xip memoritzarà els bits que ha rebut.

Dels setze bits que rep un xip, els bits 12 a 15 no serveixen per a res i nosaltres els posarem sempre a zero. Els bits 8 a 11 són els de control i serveixen per indicar quina filera estem enviant o si enviem valors de configuració. Els bits 0 a 7 són els estats dels LED de la filera o els valors de configuració corresponents. La següent taula indica els valors (en hexadecimal) dels bits de control (8 a 15) segons el que es vol enviar.

Valor Nom Funció Comentaris
0x01 Filera 1
0x02 Filera 2
0x03 Filera 3
0x04 Filera 4
0x05 Filera 5
0x06 Filera 6
0x07 Filera 7
0x08 Filera 8
0x00 No-Op No fer res Serveix quan vols enviar dades a un altre MAX7221 però no en vols enviar a aquest
0x09 Decode mode Conversió per a 7 segments Per a matrius de LED ha d'enviar-se 0x00 (no decode)
0x0B Scan limit Nombre de fileres (des de 0) Nosaltres enviarem 0x07 perquè tenim vuit fileres
0x0C Shutdown mode Activa o desactiva el xip Només n'hi pot haver un d'activat (0x01) cada vegada; la resta desactivats (0x00)

Programa bàsic de prova per a la matriu de LED

El programa de l'exemple NM permet provar el brunzidor i el programa de l'exemple PA permet provar els polsadors. El següent programa permet provar la matriu.

Per tal que no es noti el pampallugueig dels LED cal treballar a una freqüència d'oscil·lació de 25 Hz o superior. Si treballem a 25 Hz vol dir que cada cicle ha de durar un màxim de 40 ms. En cada cicle hem d'activar, seqüencialment, els tres colors, per tant hem de canviar de color cada 13,3 ms o menys. Hem decidit fer-ho, més o menys, cada 7,5 ms; per això posarem el temporitzador a 1/64 (incrementarà TMR0 cada 64 μs) i farem una interrupció cada 117 iteracions, és a dir que posarem una preselecció de 139 a TMR0.

La funció d'interrupció per al Timer 0 és la que s'encarrega de canviar els colors. El color actual es controla, amb la variable Actiu, segons la següent taula:

Actiu Color
0 Matriu apagada
1 Vermell actiu
2 Verd actiu
3 Blau actiu

Si el valor de la variable Actiu no és zero, a cada interrupció es canvia el color. Si, en canvi, val zero es manté a zero. Per tant, a l'estat de desactivació s'hi entra i se'n surt des del programa principal. La funció d'interrupció activa el xip del color que correspon o cap d'ells.

Atès que a la funció Envia3max se la crida tant des del programa principal com de la interrupció, podríem tenir problemes si la interrupció es produeix mentre la funció s'està executant ja que canviaria l'estat de les variables. Per evitar-ho, a la interrupció podríem guardar tots els valors de les variables que fa servir Envia3max i restituir-los a l'acabar. Però també podem tenir problemes si un color s'activa quan s'està a mig enviar. Per això el que hem fet és desactivar les interrupcions durant l'enviament i així ens estalviem de guardar els valors de les variables.

La funció d'interrupció (inclosa la funció Envia3max) dura aproximadament 3,7 ms. Atès que la interrupció es repeteix cada 7,5 ms vol dir que la interrupció dura la meitat del temps total i que qualsevol bucle de retard que posem al programa principal durarà el doble. L'enviament de les dades a una matriu completa dura uns 18,5 ms.

Si necessitem que la interrupció duri proporcionalment menys temps, podem fer anar el microcontrolador al doble de velocitat, tal com es comenta més avall.

En l'exemple següent el programa és llarg però senzill. En la part d'inicialització configura el microcontrolador. En el bucle simplement va alternant els dos patrons de les figures següents deixant un temps entre canvi i canvi per tal que els patrons es puguin veure suficientment bé.

Sentit prohibit           Fletxa verda amunt

#pragma config FOSC = INTRCIO, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF, 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
#define _XTAL_FREQ  4000000			// La freqüència del rellotge és 4 MHz
char Sortida[6];				// Valors a enviar al MAX7221 (16 bits)
char Actiu; 					// Variable que diu quin color està actiu
						// Actiu = 0		Apagat
						// Actiu = 1		Vermell
						// Actiu = 2		Verd
						// Actiu = 3		Blau
						// Definició de les funcions que farem servir 
void Envia3max(char Valor[6]);			// Envia un joc de valors als tres MAX7221
void Ini3max(void);				// Inicialitza els tres MAX7221
void Apaga(void);				// Apaga tots els LED
void main (void) {
	OPTION_REG = 0b10000101;       		// Configuració de Timer0
						// Com a temporitzador basat en rellotge
						// 101 - Factor d'escala de 64
						// I resistències de pull-up desactivades (valor per defecte)
	TRISC = 0;				// Tot el port C és de sortida
	TRISB = 0;				// Tot el port B és de sortida
	TRISA = 0xFF;				// Tot el port A és d'entrada
	ANSEL = 0b00000101;			// Configura AN0 i AN2 com entrada analògica
	ANSELH = 0;				// Desactiva les altres entrades analògiques
	PORTC = 0;				// Inicialitza a 0 el port C
	PORTB = 0;				// Inicialitza a 0 el port B
	Ini3max();				// Inicialitza els tres MAX7221
	Apaga();				// Apaga tots els LED
	Actiu = 1;				// Activa el color vermell
	TMR0 = 139;				// Presselecció de 139, que són 117 iteracions
						// Correspon a una interrupció cada 7,5 ms
	INTCON = 0b10100000;			// Activem GIE i T0IE
	while (1) {
						// Matriu 1
		Sortida[1] = 0x01;		// Filera 1
		Sortida[3] = 0x01;
		Sortida[5] = 0x01;
		Sortida[0] = 0b00111100;	// Vermells
		Sortida[2] = 0b00000000;	// Verds
		Sortida[4] = 0b00000000;	// Blaus
		Envia3max(Sortida);		// Ho envia al MAX7221
		Sortida[1] = 0x02;		// Filera 2
		Sortida[3] = 0x02;
		Sortida[5] = 0x02;
		Sortida[0] = 0b01111110;	// Vermells
		Sortida[2] = 0b00000000;	// Verds
		Sortida[4] = 0b00000000;	// Blaus
		Envia3max(Sortida);		// Ho envia al MAX7221
		Sortida[1] = 0x03;		// Filera 3
		Sortida[3] = 0x03;
		Sortida[5] = 0x03;
		Sortida[0] = 0b11111111;	// Vermells
		Sortida[2] = 0b00000000;	// Verds
		Sortida[4] = 0b00000000;	// Blaus
		Envia3max(Sortida);		// Ho envia al MAX7221
		Sortida[1] = 0x04;		// Filera 4
		Sortida[3] = 0x04;
		Sortida[5] = 0x04;
		Sortida[0] = 0b11111111;	// Vermells
		Sortida[2] = 0b01111110;	// Verds
		Sortida[4] = 0b01111110;	// Blaus
		Envia3max(Sortida);		// Ho envia al MAX7221
		Sortida[1] = 0x05;		// Filera 5
		Sortida[3] = 0x05;
		Sortida[5] = 0x05;
		Sortida[0] = 0b11111111;	// Vermells
		Sortida[2] = 0b01111110;	// Verds
		Sortida[4] = 0b01111110;	// Blaus
		Envia3max(Sortida);		// Ho envia al MAX7221
		Sortida[1] = 0x06;		// Filera 6
		Sortida[3] = 0x06;
		Sortida[5] = 0x06;
		Sortida[0] = 0b11111111;	// Vermells
		Sortida[2] = 0b00000000;	// Verds
		Sortida[4] = 0b00000000;	// Blaus
		Envia3max(Sortida);		// Ho envia al MAX7221
		Sortida[1] = 0x07;		// Filera 7
		Sortida[3] = 0x07;
		Sortida[5] = 0x07;
		Sortida[0] = 0b01111110;	// Vermells
		Sortida[2] = 0b00000000;	// Verds
		Sortida[4] = 0b00000000;	// Blaus
		Envia3max(Sortida);		// Ho envia al MAX7221
		Sortida[1] = 0x08;		// Filera 8
		Sortida[3] = 0x08;
		Sortida[5] = 0x08;
		Sortida[0] = 0b00111100;	// Vermells
		Sortida[2] = 0b00000000;	// Verds
		Sortida[4] = 0b00000000;	// Blaus
		Envia3max(Sortida);		// Ho envia al MAX7221
						// Fi de la matriu 1
		__delay_ms(1400);		// Retard d'1,4 s teòrics
						// Correspon a uns 2,8 s
						// Matriu 2
		Sortida[1] = 0x01;		// Filera 1
		Sortida[3] = 0x01;
		Sortida[5] = 0x01;
		Sortida[0] = 0b00000000;	// Vermells
		Sortida[2] = 0b00011000;	// Verds
		Sortida[4] = 0b00000000;	// Blaus
		Envia3max(Sortida);		// Ho envia al MAX7221
		Sortida[1] = 0x02;		// Filera 2
		Sortida[3] = 0x02;
		Sortida[5] = 0x02;
		Sortida[0] = 0b00000000;	// Vermells
		Sortida[2] = 0b00111100;	// Verds
		Sortida[4] = 0b00000000;	// Blaus
		Envia3max(Sortida);		// Ho envia al MAX7221
		Sortida[1] = 0x03;		// Filera 3
		Sortida[3] = 0x03;
		Sortida[5] = 0x03;
		Sortida[0] = 0b00000000;	// Vermells
		Sortida[2] = 0b01111110;	// Verds
		Sortida[4] = 0b00000000;	// Blaus
		Envia3max(Sortida);		// Ho envia al MAX7221
		Sortida[1] = 0x04;		// Filera 4
		Sortida[3] = 0x04;
		Sortida[5] = 0x04;
		Sortida[0] = 0b00000000;	// Vermells
		Sortida[2] = 0b11111111;	// Verds
		Sortida[4] = 0b00000000;	// Blaus
		Envia3max(Sortida);		// Ho envia al MAX7221
		Sortida[1] = 0x05;		// Filera 5
		Sortida[3] = 0x05;
		Sortida[5] = 0x05;
		Sortida[0] = 0b00000000;	// Vermells
		Sortida[2] = 0b00011000;	// Verds
		Sortida[4] = 0b00000000;	// Blaus
		Envia3max(Sortida);		// Ho envia al MAX7221
		Sortida[1] = 0x06;		// Filera 6
		Sortida[3] = 0x06;
		Sortida[5] = 0x06;
		Sortida[0] = 0b00000000;	// Vermells
		Sortida[2] = 0b00011000;	// Verds
		Sortida[4] = 0b00000000;	// Blaus
		Envia3max(Sortida);		// Ho envia al MAX7221
		Sortida[1] = 0x07;		// Filera 7
		Sortida[3] = 0x07;
		Sortida[5] = 0x07;
		Sortida[0] = 0b00000000;	// Vermells
		Sortida[2] = 0b00011000;	// Verds
		Sortida[4] = 0b00000000;	// Blaus
		Envia3max(Sortida);		// Ho envia al MAX7221
		Sortida[1] = 0x08;		// Filera 8
		Sortida[3] = 0x08;
		Sortida[5] = 0x08;
		Sortida[0] = 0b00000000;	// Vermells
		Sortida[2] = 0b00011000;	// Verds
		Sortida[4] = 0b00000000;	// Blaus
		Envia3max(Sortida);		// Ho envia al MAX7221
						// Fi de la matriu 2
		__delay_ms(1400);		// Retard d'1,4 s teòrics
						// Correspon a uns 2,8 s
	}
}
void interrupt temporit(void) {
	INTCONbits.GIE = 0;			// Desactiva les interrupcions momentàniament
	if (INTCONbits.T0IF) {			// Comprovem que hi ha interrupció per Timer 0
		TMR0 = 139;			// Preselecció de Timer0
		INTCONbits.T0IF = 0;		// Desactiva el bit que indica interrupció pel Timer0
		if (Actiu != 0) {		// Si la matriu no està apagada
			Actiu--;		// Passem a activar un altre color
			if (Actiu == 0) {	// Si hem arribat a zero
				Actiu = 3;	// Torna a posar el 3
			}
		}
						// D'entrada els desactivem els tres
		Sortida[0] = 0x00;		// Vermell
		Sortida[2] = 0x00;		// Verd
		Sortida[4] = 0x00;		// Blau
		if (Actiu == 1) {		// Si és vermell
			Sortida[0] = 0x01;	// Vermell activat
		}
		if (Actiu == 2) {		// Si és verd
			Sortida[2] = 0x01;	// Verd activat
		}
		if (Actiu == 3) {		// Si és blau
			Sortida[4] = 0x01;	// Blau activat
		}
		Sortida[1] = 0x0C;		// Shutdown mode
		Sortida[3] = 0x0C;		// Shutdown mode
		Sortida[5] = 0x0C;		// Shutdown mode
		Envia3max(Sortida);		// Ho envia al MAX7221
	}
	INTCONbits.GIE = 1;			// Reactiva les interrupcions a l'acabar
}
void Envia3max(char Valor[6]) {			// Envia un joc de valors als tres MAX7221
	INTCONbits.GIE = 0;			// Desactiva les interrupcions momentàniament
	char Port = 0;				// Variable on guardem l'estat del port B
	char Temp;				// Variable temporal
	for (int j = 5; j >= 0; j--){		// Hem d'enviar 6 bytes
		for (int k = 1; k < 9; k++){			// De 8 bits
			Temp = Valor[j] & 0b10000000;		// Agafa el bit de més a l'esquerra
								// Temp només podrà valer 0 o 128
			if (Temp == 0) {			// Si val 0
				Port = Port & 0b11101111;	// Desactiva Data (bit 4)
			} else {				// Si val 128
				Port = Port | 0b00010000;	// Activa Data (bit 4)
			}
			Valor[j] = Valor[j] << 1;		// Rodem els bits per situar el següent
			PORTB = Port;				// Ho posa al port B
			Port = Port | 0b00100000;		// Activa Clock (bit 5) i força lectura
			PORTB = Port;				// Ho posa al port B
			Port = Port & 0b11011111;		// Desactiva Clock (bit 5)
			PORTB = Port;				// Ho posa al port B
		}
	}
	Port = Port | 0b01000000;		// Activa Latch (bit 6) per copiar a les sortides
	PORTB = Port;				// Ho posa al port B
	INTCONbits.GIE = 1;			// Reactiva les interrupcions a l'acabar
}
void Ini3max(void) {				// Inicialitza els tres MAX7221
	char Bytes[6];				// Els sis bytes que cal enviar
	Bytes[0] = 0x00;			// Desactivat
	Bytes[1] = 0x0C;			// Shutdown mode
	Bytes[2] = 0x00;
	Bytes[3] = 0x0C;
	Bytes[4] = 0x00;
	Bytes[5] = 0x0C;
	Envia3max(Bytes);			// Els envia
	Bytes[0] = 0x00;			// No decode
	Bytes[1] = 0x09;			// Decode mode
	Bytes[2] = 0x00;
	Bytes[3] = 0x09;
	Bytes[4] = 0x00;
	Bytes[5] = 0x09;
	Envia3max(Bytes);			// Els envia
	Bytes[0] = 0x07;			// Vuit fileres
	Bytes[1] = 0x0B;			// Scan limit
	Bytes[2] = 0x07;
	Bytes[3] = 0x0B;
	Bytes[4] = 0x07;
	Bytes[5] = 0x0B;
	Envia3max(Bytes);			// Els envia
}
void Apaga(void) {				// Apaga tots els LED
	char Bytes[6];				// Els sis bytes que cal enviar
	for (int j = 0; j <= 8; j++){		// Hem d'enviar 8 fileres
		Bytes[1] = j;			// Filera
		Bytes[3] = j;
		Bytes[5] = j;
		Bytes[0] = 0x00;		// Vermells
		Bytes[2] = 0x00;		// Verds
		Bytes[4] = 0x00;		// Blaus
		Envia3max(Bytes);		// Els envia
	}
}

Si fem anar el microcontrolador més ràpid, podem fer que hi hagi més temps disponible per al programa principal. Això ho farem afegint o canviant algunes línies. A continuació posem els trossos de programa que tindrien canvis, ressaltant aquests en color. Amb aquesta velocitat el programa principal dura només un 32 % més en lloc del doble.

...
#define _XTAL_FREQ  8000000			// La freqüència del rellotge és 8 MHz
void main (void) {
	OSCCON = 0b01111000;			// IRCF = 111, rellotge a 8 MHz
	OPTION_REG = 0b10000101;       		// Configuració de Timer0
						// Com a temporitzador basat en rellotge
						// 101 - Factor d'escala de 64
						// I resistències de pull-up desactivades (valor per defecte)
...
	TMR0 = 21;				// Presselecció de 21, que són 234 iteracions
						// Correspon a una interrupció cada 7,5 ms
...
		__delay_ms(1400);		// Retard d'1,4 s teòrics
						// Correspon a uns 1,85 s
...
		__delay_ms(1400);		// Retard d'1,4 s teòrics
						// Correspon a uns 1,85 s
...
		TMR0 = 21;			// Preselecció de Timer0
...

 

 

Licencia de Creative Commons
This obra by Oriol Boix is licensed under a Creative Commons Reconocimiento-NoComercial-SinObraDerivada 3.0 Unported License.