Programació en C del PIC 16F690

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

Sensor de temperatura i humitat

Programa del grup 1

El grup 1 va fer un programa que, a més de mostrar la temperatura i la humitat, disposava de dos nivells d'alarma.

El programa d'aquest grup és el següent:

#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
#define Sens   RA5			// Li assigna un nom a l'adreça del sensor
unsigned int Valor;				// Variable de treball
unsigned int Valor2;				// Variable de treball 2
unsigned int Error;				// Error de lectura
unsigned int Lectura[3];			// Valor llegit
						// Lectura[0] és la suma de comprovació
						// Lectura[1] és la temperatura
						// Lectura[2] és la humitat
char Digits[5];					// Vector amb el número dígit a dígit
						// Digits[0] és el decimal
bit Negatiu;					// Guarda si el valor de la temperatura és negatiu o positiu
						// Definició de les funcions que farem servir
char Sortida[6];				// Valors a enviar al MAX7221 (48 bits)
char Actiu;					// Variable que diu quin color està actiu
						// Actiu = 0		Apagat
						// Actiu = 1		Vermell
						// Actiu = 2		Verd
						// Actiu = 3		Blau
char Polsad;					// Polsador que s'ha premut
char sona=1;					// Inicialitzem la variable sona igual a 1, tal que soni a l'inici
						// Definició de les funcions que farem servir
char Sensor(void);				// Lectura del sensor. dona 0 si la suma de control és correcta
char Polsador(void);				// Funció de lectura dels polsadors
void EnviaL(char Caracter);			// Envia un caràcter
void EnviaNum(char Nom);			// Envia un número sencer precedit d'un nom
void Transforma(void);				// Un número es converteix en un grup de caràcters ASCII
void Esborra(void);				// Esborra la pantalla i posa el cursor a l'inici
void Cursor(char Filera, char Columna);		// Posiciona el cursor (filera 1 a 2 i columna 1 a 32, segons pantalla)
void Envia3max(char Valors[6]);			// Envia un joc de valors als tres MAX7221
void Ini3max(void);				// Inicialitza els tres MAX7221
void Apaga(void);				// Apaga tots els LED
void matriu(void);				// encén la matriu
void TocaNota(char ValPR2, char ValCCPR1L, char ValDC1B);	// Toca una nota depenen dels valors d'entrada
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)
	ANSEL = 0b0000101;			// Configura AN0 com entrada analògica
	ANSELH = 0;				// Desactiva les altres entrades analògiques
	TRISC = 0b00100000;			// Definim com volem les E/S del port C
						// RC5 (sortida del PWM), de moment, com a entrada
	TRISB = 0;				// Tot el port B és de sortida
	TRISA = 0b11011111;			// Tot el port A és d'entrada excepte, de moment, RA5
	PORTA = 0b00100000;			// RA5 a 1
	T1CON = 0b00100001;			// Configuració de Timer1
						// Com a temporitzador basat en rellotge
						// 10 - Factor d'escala de 4
						// TMR1L s'incrementarà cada 2 us
	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ó
	PORTC = 0;				// Inicialitza a 0 el port C
	PORTB = 0;				// Inicialitza a 0 el port B
	ADCON1 = 0b00010000;			// Posa el conversor a 1/8 de la freqüència
	ADCON0 = 0b00001001;			// Activa el conversor A/D connectat a AN2
						// amb el resultat justificat per l'esquerra
	Ini3max();				// Inicialitza els tres MAX7221
	Esborra();				// Esborra la pantalla i posa el cursor a l'inici
	Apaga();				// Esborra qualsevol dibuix de la matriu
	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
	CCP1CON = 0b00001100;			// Configura el PWM, bits P1M (bits 7-6) a 00 mode senzill
						// DC1B = 11 (bits 5-4) els dos bits de menys pes són 0
						// CCP1M = 11xx en mode senzill els bit 0 i 1 no afecten
						// Ho posa com a configuració del PWM
	CCPR1L = 49;				// Valor que correspon a un cicle del 35 % a 440 Hz
						// Registre que ens dona l'amplada de tON
	PIR1bits.TMR2IF = 0;			// Desactiva el bit d'interrupció del Timer 2
	T2CON = 0b00000011;			// Configura el Timer 2
						// bits T2KCPS (bits 1-0) a 11 prescalat de 16
						// bit 2 (TMR2ON) a 0, Timer aturat
						// Postscaler TOUTPS (bits 6-3) no afecten al PWM
	while (1) {				// Inici del bucle de programa
		Ini3max();			// Inicialitza els tres MAX7221
		Apaga;				// Esborra qualsevol dibuix de la matriu
		INTCONbits.GIE = 0;		// Desactiva les interrupcions momentàniament
		OSCCON = 0b01111000;		// IRCF = 111, rellotge a 8 MHz
		Error = Sensor();
		OSCCON = 0b01101000;		// IRCF = 110, rellotge a 4 MHz
		INTCONbits.GIE = 1;		// Desactiva les interrupcions momentàniament
		if (Error == 0) {		// Llegeix el sensor i si és correcte segueix
			Valor=Lectura[2];	// Humitat
			Transforma();		// Transformem un número a un grup de caràcters ASCII
			Cursor(1, 1);		// Posició
			EnviaNum('H');		// Envia el número de la Lectura amb el nom H
			EnviaL('%');		// Tant per cent
			Valor = Lectura[1];	// Temperatura
			if (Valor >= 32768) {	// Si el bit més significatiu està activat és negatiu
				Negatiu = 1;		// És negatiu
				Valor = Valor -32768;	// Agafem el valor absolut
			} else {
				Negatiu = 0;	// És positiu
			}
			Transforma();		// Transformem un número a un grup de caràcters ASCII
			Cursor(2, 1);		// Posició
			EnviaNum('T');		// Envia el número de la Lectura amb el nom T
			EnviaL(0b11011111);	// Graus
			EnviaL('C');		// Lletra
			Polsad = Polsador();	// Llegim els polsadors
			if (Polsad==1){
				if(sona!=0) {	// Si sona es diferent de 0
					sona=0;	// Li assignem 0
				} else {	// o
					sona=1;	// 1
				}
			}
			Valor=Lectura[1];       // Temperatura
			Valor2=Lectura[2];      // Humitat
			if (((Valor<160)|| (Valor>230))|| ((Valor2<600) || (Valor2>720))) {
						// Quan la temperatura i humitat
				matriu();	// sigui fora dels dos intervals encen la matriu
						// Fixem un cas extrem
				if (((Valor>300) || (Valor<120)) || ((Valor2<300) || (Valor2>800))) {
					sona=2;	// Li determinem un altre valor 
				}
				if  (sona==1) {
					TocaNota(238,119,2);	// sona una nota greu
				}
				if  (sona==2) {
					TocaNota(118,59,2);	// sona una nota aguda
				}
			} else {
				Apaga();	// apaguem la matriu
				sona=1;		// quan estigui als interals idonis
			}			// el pròxim cop que surti fora, sonarà
		} else {
			Cursor(1, 1);           // Posició
			EnviaL('E');
			EnviaL('r');
			EnviaL('r');
			EnviaL('o');
			EnviaL('r');
			EnviaL(' ');
			Error = Error + '0';    // Passa el valor a ASCII
			EnviaL(Error);          // Número
		}
        
		__delay_ms(500);		// Retard d'1 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 Valors[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 = Valors[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)
			}
			Valors[j] = Valors[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
	}
}
void matriu(void) {
        Sortida[1] = 0x01;			// Filera 1
        Sortida[3] = 0x01;
        Sortida[5] = 0x01;
        Sortida[0] = 0b10000001;		// 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] = 0b01000010;		// 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] = 0b00100100;		// 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] = 0b00011000;		// Vermells
        Sortida[2] = 0b00000000;		// Verds
        Sortida[4] = 0b00000000;		// Blaus
        Envia3max(Sortida);			// Ho envia al MAX7221
        Sortida[1] = 0x05;			// Filera 5
        Sortida[3] = 0x05;
        Sortida[5] = 0x05;
        Sortida[0] = 0b00011000;		// Vermells
        Sortida[2] = 0b00000000;		// Verds
        Sortida[4] = 0b00000000;		// Blaus
        Envia3max(Sortida);			// Ho envia al MAX7221
        Sortida[1] = 0x06;			// Filera 6
        Sortida[3] = 0x06;
        Sortida[5] = 0x06;
        Sortida[0] = 0b00100100;		// 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] = 0b01000010;		// 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] = 0b10000001;		// Vermells
        Sortida[2] = 0b00000000;		// Verds
        Sortida[4] = 0b00000000;		// Blaus		
        Envia3max(Sortida);			// Ho envia al MAX7221
						// Fi de la matriu 
}
char Sensor(void) {
	char Bytes[5];				// Vector per a guardar els cinc bytes que envia el sensor
	char Temps;				// Guarda el valor de TMR1L
	for (int j = 0; j < 5; j++){		// 5 bytes
		Bytes[j] = 0;			// Posem el vector a zero
	}
	TRISA = 0b11011111;			// Tot el port A és d'entrada excepte, de moment, RA5
	PORTA = 0b00000000;			// RA5 a 0
	__delay_ms(2);				// Retard de 2 ms
	PORTA = 0b00100000;			// RA5 a 1
	__delay_us(15);				// Retard de 15 us
						// Un cop activat, esperem la resposta
	TRISA = 0b11111111;			// Tot el port A és d'entrada, inclosa RA5
						// Esperem a rebre el pols d'inici
						// Primer un L d'uns 80 us
						// Per començar, s'ha de desactivar l'entrada
						// i s'ha de reactivar al cap d'entre 70 i 90 us
	while (Sens)				// S'ha desactivat l'entrada?
		;				// No, doncs esperem
	TMR1H = 0;
	TMR1L = 0;				// Sí, doncs comencem a comptar el temps
	while ((!Sens) && (TMR1L < 45))		// Esperem que s'activi l'entrada
		;                               // O passin més de 90 us
	Temps = TMR1L;				// Agafa el valor de TMR1L
	TMR1H = 0;
	TMR1L = 0;				// Torna a començar a comptar el temps
	if (Temps > 45) {			// És més gran
		return 1;			// Error 1 - L inicial massa llarg
	}
	if (Temps < 35) {			// Mirem que no sigui menor que 70 us
		return 2;			// Error 2 - L inicial massa curt
	}
						// L inicial ja està
	while (Sens && (TMR1L < 45))		// Esperem a que es desactivi l'entrada
		;				// O passin més de 90 us
	Temps = TMR1L;				// Agafa el valor de TMR1L
	TMR1H = 0;
	TMR1L = 0;				// Torna a començar a comptar el temps
	if (Temps > 45) {			// És més gran
		return 3;			// Error 3 - H inicial massa llarg
	}
	if (Temps < 35) {			// Mirem que no sigui menor que 70 us
		return 4;			// Error 4 - H inicial massa curt
	}
						// H inicial ja està
						// Ara hem de rebre els bits
	TMR1H = 0;
	TMR1L = 0;				// Torna a començar a comptar el temps
	for (int j = 0; j < 5; j++){		// 5 bytes
		for (int k = 0; k < 8; k++){	// 8 bits a cada byte
			Bytes[j] = 2 * Bytes[j];	// Rodem a l'esquerra el bit anterior
						// per deixar lloc al nou
						// Si no n'hi havia cap no canvia res
						// ja que estava a zero
						// Esperem a rebre un bit
						// Primer un L d'uns 80 us
						// Ara l'entrada està a zero
						// S'ha d'activar al cap d'entre 10 i 90 us
			while ((!Sens) && (TMR1L < 45))	// Esperem que s'activi l'entrada
				;		// O passin més de 90 us
			Temps = TMR1L;		// Agafa el valor de TMR1L
			TMR1H = 0;
			TMR1L = 0;		// Torna a començar a comptar el temps
			if (Temps > 45) {	// És més gran
				return 5;	// Error 5 - Valor L del bit massa llarg
			}
			if (Temps < 5) {	// Mirem que no sigui menor que 10 us
				return 6;	// Error 6 - Valor L del bit massa curt
			}
						// Ja tenim el valor L del bit. Ara esperem un H
			while (Sens && (TMR1L < 40))	// Esperem a que es desactivi l'entrada
				;		// O passin més de 80 us
			Temps = TMR1L;		// Agafa el valor de TMR1L
			TMR1H = 0;
			TMR1L = 0;		// Torna a començar a comptar el temps
			if (Temps > 40) {	// És més gran
				return 7;	// Error 7 - Valor H del bit massa llarg
			}
			if (Temps < 6) {	// Mirem que no sigui menor que 12 us
				return 8;	// Error 8 - Valor H del bit massa curt
			}
						// Ja hem comprovat que no sigui massa curt ni massa llarg
						// Si és més petit que 38 us és un pols curt, o sigui un 0
						// Si és curt no cal fer res, el 0 ja hi és
						// Si és més gran que 60 us és un pols llarg, o sigui un 1
			if (Temps > 19) {	// És més gran que 38 us
						// Sí, doncs no és un pols curt
				if (Temps > 30) {	// És més gran que 60 us
						// És un pols llarg
					Bytes[j] = Bytes[j] + 1;	// Entrem un 1
				} else {
					return 9;	// Error 9 - Valor H del bit incorrecte
				}
			}
		}
	}
						// Ja tenim els 5 bytes. Fem la suma de comprovació
						// Cal sumar els quatre primers bytea
						// Però sense portar-ne
	Valor = 0;				// Primer la posem a zero
	for (int j = 0; j < 4; j++){		// 4 bytes
		Valor = Valor + Bytes[j];	// Sumem un dels quatre elements
		if (Valor > 255) {		// Mirem si és més gran del que cap a un byte
						// Si és més gran, només pot haver activat un bit del segon byte
						// el que correspon a 256
			Valor = Valor -256;	// Restem les que en portàvem
		}
	}
	if (Valor != Bytes[4]) {		// No coincideixen
		return 10;			// Error 10 - Falla la suma de comprovació
	}
	Lectura[0] = Bytes[4];			// Suma de comprovació
	Lectura[1] = 256 * Bytes[2] + Bytes[3];	// Temperatura
	Lectura[2] = 256 * Bytes[0] + Bytes[1];	// Humitat
	return 0;				// Recepció correcta
}
char Polsador(void) {
	char Pols = 0;
	ADCON0bits.GO = 1;			// Posa en marxa el conversor
	while (ADCON0bits.GO == 1)		// Mentre no acabi
		;				// ens esperem
	if (ADRESH < 220 && ADRESH > 200) {
		Pols = 1;			// Comprova polsador 1
	}
	if (ADRESH < 194 && ADRESH > 174) {
		Pols = 2;			// Comprova polsador 2
	}
	if (ADRESH < 163 && ADRESH > 143) {
		Pols = 3;			// Comprova polsador 3
	}
	if (ADRESH < 90 && ADRESH > 70) {
		Pols = 4;			// Comprova polsador 4
	}
	if (ADRESH < 55 && ADRESH > 35) {
		Pols = 5;			// Comprova polsador 5
	}
	return Pols;
}

void EnviaL(char Caracter) {
	INTCONbits.GIE = 0;
	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 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
}
void EnviaNum(char Nom) {
	EnviaL(Nom);				// Lletra
	EnviaL(':');				// dos punts
	for (int j = 4; j > 0; j--){		// 4 dígits (el 5è és el decimal)
		EnviaL(Digits[j]);		// Número
	}
	EnviaL(',');				// Coma
	EnviaL(Digits[0]);			// Número
	EnviaL(' ');				// Espai
    
}
void Transforma(void) {
	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
	}					// Això és la humitat multiplicada per 10
	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
			}			// Els dos darrers zeros els mostrarem sempre
		}
	}
}
void Esborra(void) {
	EnviaL(254);				// Caràcter de control
	EnviaL(1);				// Esborra la pantalla i posa el cursor a l'inici
}
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 TocaNota(char ValPR2, char ValCCPR1L, char ValDC1B) {
	TRISC = 0b00100000;			// Definim com volem les E/S del port C
						// RC5 (sortida del PWM), de moment, com a entrada
	PR2 = ValPR2;				// Carrega PR2
	CCP1CON = CCP1CON & 0b11001111;		// Posa a zero els bits que corresponen a DC1B
	ValDC1B = ValDC1B % 4;			// DC1B va de 0 a 3
	ValDC1B = ValDC1B * 16;			// Desplaça els bits a la posició que els correspon a CCP1CON
	CCP1CON = CCP1CON + ValDC1B;		// Coloca DC1B al seu lloc
	CCPR1L = ValCCPR1L;			// Carrega CCPR1L, registre que ens dona l'amplada de tON
	PIR1bits.TMR2IF = 0;			// Desactiva el bit d'interrupció del Timer 2
	T2CON = 0b00000111;			// Configura el Timer 2
						// bits T2KCPS (bits 1-0) a 11 prescalat de 16
						// bit 2 (TMR2ON) a 1, Timer activat
						// Postscaler TOUTPS (bits 6-3) no afecten al PWM
	while (PIR1bits.TMR2IF == 0)		// Espera l'activació del bit d'interrupció del Timer 2
		;				// Esperem
	TRISC = 0b00000000;			// Posem RC5 (sortida del PWM) com a sortida
	__delay_ms(300);			// Retard de 0,4 s
	TRISC = 0b00100000;			// Posem RC5 (sortida del PWM) com a entrada
						// O sigui, silenci
	__delay_ms(50);				// Retard de 0,05 s
}

 

 

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