Programació en C del PIC 16F690

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

Rellotge digital

Programa del grup 1

En aquest cas és un rellotge despertador que, a més de poder ajustar la data i l'hora, incorpora una funció especial. En el moment que sona l'alarma es pot, prement alguns dels polsadors, canviar a una altra melodia.

El programa é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 Stop   RA3			// Li assigna un nom a l'adreça del polsador
unsigned char Valor;
char Polsad;
char z=0;					// Fer que alarma acabi
char A;						// Nombre decimal
char E;						// Dígit esquerre decimal
char D;						// Dígit dret decimal
char L;						// Lectura
char X;						// Dígit a introduir
char HR;					// Hora rellotge
char MR;					// Minuts rellotge
char i=0;					// Comptador de canvi d'hora
char a=0;					// Entrar modo alarma
char interruptor=0;				// Interruptor de poder canviar l'hora
char h=00;					// Hora alarma
char m=00;					// Minut alarma
char w=0;					// Activador d'alarma1
char q=0;					// Activador d'alarma2
char c=0;					// Activador cucaracha
char r=0;					// Activador música relax
char cumple=0;
char AdreI2C = 0b11010000;			// Adreça del dispositiu I2C (1101000)
						// Rodada cap a l'esquerra (preparada per afegir el bit RW)
char Posicio = 0;				// Posició a la pantalla
char Lectura;					// Aquí guardarem el resultat de la lectura
char Port = 0;					// Valor a escriure al port C
						// RC7 és SDA
						// RC6 és SCL
char Polsador(void);
char LlegirI2C(char AdreMem);			// Llegeix un byte I2C
void EscriuI2C(char AdreMem, char Dades);	// Escriu un byte I2C
void SDAentrada(void);				// Posa SDA com a entrada
void SDAsortida(void);				// Posa SDA com a sortida
void StartI2C(void);				// Envia el bit d'inici I2C
void StopI2C(void);				// Envia el bit d'aturada I2C
void ACK_S(void);				// Reb un ACK des de l'esclau
void NACK_M(void);				// Envia un NACK a l'esclau
void EnvByteI2C(char Buffer);			// Funció interna que envia un byte a I2C
char RebByteI2C(void);				// Funció interna que rep un byte a I2C
void EnviaL(char Caracter);			// Envia un caràcter
void EnviaBCD2(char Caracter);			// Mostrem a la pantalla un valor BCD
						// a partir de dues xifres hexadecimals
void EnviaBCD1(char Caracter);			// Mostrem a la pantalla un valor BCD
						// a partir d'una xifra hexadecimal
void Alarma(void);				// Funció per l'alarma
void Hora(void);				// Funció canvi hora
void Minuts(void);				// Funció canvi minuts
void TocaNota(char ValPR2, char ValCCPR1L, char ValDC1B);				// Fes sonar notes
void Esborra(void);				// Esborra la pantalla
void Bit1(void);				// Fila inferior
void Bit2(void);				// Fila superior
void Cucaracha(void);
void Relax(void);
void DO(void);
void RE(void);
void MI(void);
void FA(void);
void SOL(void);
void LA(void);
void SI(void);
void DOO(void);
void Cumple(void);
void main (void) {
	ANSEL = 0b00000101;			// Configura AN0 i AN2 com entrada analògica
	ANSELH = 0;				// Desactiva les altres entrades analògiques
	TRISA = 0xFF;				// Tot el port A és d'entrada
	TRISB = 0;				// Tot el port B és de sortida
	TRISC = 0;				// Tot el port C és de sortida
	ADCON1 = 0b00010000;			// Posa el conversor a 1/8 de la freqüència
	ADCON0 = 0b00001001;
	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ó
	PORTB = 0;				// Inicialitza a 0 el port B
	PORTC = 0;				// Inicialitza a 0 el port C
						// Com a mostra, es posen les 23.58.34
						// del dijous 31-3-2016
						// per poder veure un canvi de dia i de mes
	EscriuI2C(0, 0x45);			// Segons
	EscriuI2C(1, 0x01);			// Minuts
	EscriuI2C(2, 0x00);			// Hores
	EscriuI2C(3, 0x02);			// Dia setmana (dijous)
	EscriuI2C(4, 0x11);			// Dia mes
	EscriuI2C(5, 0x01);			// Mes (març)
	EscriuI2C(6, 0x18);			// Any (2016)
	EscriuI2C(7, 0x00);			// Polsos desactivats
	while (1) {
		__delay_ms(100);		// 
		Bit1();				// Posiciona't a la fila d'avall
		Lectura = LlegirI2C(2);		// Hores
		EnviaBCD2(Lectura);		// Mostrem a la pantalla el valor
		EnviaL('.');			// Separador
		Lectura = LlegirI2C(1);		// Minuts
		EnviaBCD2(Lectura);		// Mostrem a la pantalla el valor
		EnviaL('.');			// Separador
		Lectura = LlegirI2C(0);		// Segons
		EnviaBCD2(Lectura);		// Mostrem a la pantalla el valor
		Bit2();
		Lectura = LlegirI2C(4);		// Dia
		EnviaBCD2(Lectura);		// Mostrem a la pantalla el valor
		EnviaL('-');			// Separador
		Lectura = LlegirI2C(5);		// Mes
		EnviaBCD2(Lectura);		// Mostrem a la pantalla el valor
		EnviaL('-');			// Separador
		EnviaL('2');			// Any primer dígit
		EnviaL('0');			// Any segon dígit
		Lectura = LlegirI2C(6);		// Any segona part
		EnviaBCD2(Lectura);		// Mostrem a la pantalla el valor
		EnviaL(' ');			// Espai
		EnviaL(' ');			// Espai
		Lectura = LlegirI2C(3);		// Dia
		EnviaBCD1(Lectura);		// Mostrem a la pantalla el valor
		Polsad = Polsador();		// Llegim els polsadors
		Port = Port & 0b11110000;	// Abans de començar, SDA ha d'estar activat
		if (interruptor==1){		// Si interruptor activat, entrem a poder canviar l'hora
			if (Polsad == 2) {	// Si s'ha premut el polsador 2, serveix per disminuir
				if(i==0){			//Canviem hora
					Bit1();
					L=LlegirI2C(2);		// Hores
					E=L/16;			// Dígit esquerre hora
					D=L%16;			// Dígit dreta hora
					A=E*10+D;		// Decimal hora
					if (D==0){ 
						if (E==0){	// Si l'hora és 00 passarem a 23
							EnviaBCD2(23);
							EscriuI2C(2, 0x23);  
						} else{		// Sinó disminuim 1 al dígit esquerre i el dret passa a ser 9
							E=E-1;
							D=9;
							X=E*16+D;
							EnviaBCD2(X);
							EscriuI2C(2, X);
						}
					} else{			// Disminució normal de l'hora
						D=A%10-1;
						X=E*16+D;
						EnviaBCD2(X);
						EscriuI2C(2, X);
					}
				}
				if(i==1){			// Disminució dels minuts
					Bit1();
					L=LlegirI2C(1);		// Minuts
					E=L/16;
					D=L%16;
					A=E*10+D;
					if (D==0){ 
						if(E==0){
							EnviaBCD2(59);
							EscriuI2C(1, 0x59);
						} else{
							E=E-1;
							D=9;
							X=E*16+D;
							EnviaBCD2(X);
							EscriuI2C(1, X);
						}
					} else{
						D=A%10-1;
						X=E*16+D;
						EnviaBCD2(X);
						EscriuI2C(1, X);
					}
				}
				if(i==2){			// Disminució del dia
					Bit2();
					L = LlegirI2C(4);	// Dia
					E=L/16;
					D=L%16;
					if (D==1){
						if(E==0){
							EnviaBCD2(31);
							EscriuI2C(4, 0x31);
						} else{
							D=0;
							X=E*16+D;
							EnviaBCD2(X);
							EscriuI2C(4, X);
						}
					} else if (D==0){
						E=E-1;
						D=9;
						X=E*16+D;
						EnviaBCD2(X);
						EscriuI2C(4, X);
					} else{
						D=D-1;
						X=E*16+D;
						EnviaBCD2(X);
						EscriuI2C(4, X);
					}
				}
				if (i==3){			// Disminuir dia del mes
					Bit2();
					L = LlegirI2C(5);	// Mes
					E=L/16;
					D=L%16;
					if (D==1){
						if(E==0){
							EnviaBCD2(12);
							EscriuI2C(5, 0x12);
						} else{
							EnviaBCD2(10);
							EscriuI2C(5, 0x10);
						}
					} else if (D==0){
						if (E==1){
							EnviaBCD2(9);
							EscriuI2C(5, 0x9);
						}
					} else{
						D=D-1;
						X=E*16+D;
						EnviaBCD2(X);
						EscriuI2C(5, X);
					}
				}
				if (i==4){			// Disminuim any
					Bit2();
					L=LlegirI2C(6);
					E=L/16;
					D=L%16;
					if(D==0){
						if(E==0){
							EnviaBCD2(99);
							EscriuI2C(6, 0x99);
						} else{
							E=E-1;
							D=9;
							X=E*16+D;
							EnviaBCD2(X);
							EscriuI2C(6, X);
						}    
					} else{
						D=D-1;
						X=E*16+D;
						EnviaBCD2(X);
						EscriuI2C(6, X);
					}
				}
				if(i==5){			// Disminuir dia setmana
					Bit2();
					L=LlegirI2C(3);
					E=L/16;
					D=L%16;
					A=E*10+D;
					if(A==1){
						EnviaBCD2(07);
						EscriuI2C(3, 0x07);
					} else{
						A=A-1; 
						D=A%16;
						E=A/16;
						X=E*16+D;
						EnviaBCD2(X);
						EscriuI2C(3, X);
					}
				}
			}    
			if (Polsad == 1) {			// Si s'ha premut el polsador 1, serveix per augmentar
				if (i==0){			// Augmentem hores
					Hora();
				}
				if(i==1){			// Augmentem minuts
					Minuts();
				}
				if(i==2){			// Augmentem dies
					Bit2();
					L = LlegirI2C(4);	// Dia
					E=L/16;
					D=L%16;
					A=E*10+D;
					if (D==1){
						if(E==3){
							EnviaBCD2(01);
							EscriuI2C(4, 0x01);
						} else{
							D=D+1;
							X=E*16+D;
							EnviaBCD2(X);
							EscriuI2C(4, X);
						}
					} else if (D==9){
						E=E+1;
						D=0;
						X=E*16+D;
						EnviaBCD2(X);
						EscriuI2C(4, X);
					} else{
						D=A%10+1;
						X=E*16+D;
						EnviaBCD2(X);
						EscriuI2C(4, X);
					}
				}
				if (i==3){			// Augmentar dia del mes
					Bit2();
					L = LlegirI2C(5);	// Mes
					E=L/16;
					D=L%16;
					A=E*10+D;
					if (D==9){
						EnviaBCD2(10);
						EscriuI2C(5, 0x10);
					} else if (D==2){
						if (E==1){
							EnviaBCD2(01);
							EscriuI2C(5, 0x01);
						} else{
							D=D+1;
							X=E*16+D;
							EnviaBCD2(X);
							EscriuI2C(5, X);
						}
					} else{
						D=D+1;
						X=E*16+D;
						EnviaBCD2(X);
						EscriuI2C(5, X);
					}
				}
				if(i==4){			// Augmentem any
					Bit2();
					L=LlegirI2C(6);
					E=L/16;
					D=L%16;
					A=E*10+D;
					if(D==9){
						if(E==9){
							EnviaBCD2(00);
							EscriuI2C(6, 0x00); 
						} else{
							D=0;
							E=E+1;
							X=E*16+D;
							EnviaBCD2(X);
							EscriuI2C(6, X);
						}
					} else{
						D=D+1;
						X=E*16+D;
						EnviaBCD2(X);
						EscriuI2C(6, X);
					}
				}
				if(i==5){
					Bit2();
					L=LlegirI2C(3);
					E=L/16;
					D=L%16;
					A=E*10+D;
					if(A==7){
						EnviaBCD2(01);
						EscriuI2C(3, 0x01);
					} else{
						A=A+1; 
						D=A%16;
						E=A/16;
						X=E*16+D;
						EnviaBCD2(X);
						EscriuI2C(3, X);
					}
				}
			}      
		}
		if (Polsad == 3) {				// Serveix per anar passant en el rellotge
								// depenent del que volem canviar
			if (interruptor==1){			// Si l'interruptor està 'activat'
				__delay_ms(1000);
				i=i+1;				// Augmentem la i, avançant així en el rellotge
				RC0 = 1;		// Per cada lloc que s'avanci, encén el LED de la dreta
								// per així controlar quants llocs ens hem mogut  
				if (i==6){			// Si ja hem recorregut tot el rellotge, tornem a les hores
					i=0;
				}  
			} 
		}
		if (Polsad == 5){   	 	   // 'Activa' l'interruptor
			__delay_ms(300);
			interruptor=1;
		}          
		if (Polsad==4){      		   // 'Apaga' l'interruptor
			__delay_ms(300);
			interruptor=0;
			i=0;
		}
		if (interruptor==0){
			HR=LlegirI2C(2);
			MR=LlegirI2C(1);
			if (Polsad==4){
				a=1;
				Alarma();
			}
			while (HR==h && MR==m && z==0 && w==1){
				Esborra();
				Bit1();
				TRISC = 0b11110000;		// Posa els bits 0 i 2 del port C com a sortida
				PORTC = 0b00001111;		// Activa els bits 0 i 2 del port C i,
								// per tant, encén els LED de manera intermitent
				EnviaL('A');			
				EnviaL('L');			
				EnviaL('A');			
				EnviaL('R');			
				EnviaL('M');			
				EnviaL('A');			
				EnviaL(' ');			
				EnviaL(' ');			
				EnviaL(' ');			
				EnviaL(' ');			
				EnviaL(' ');			
				EnviaL('O');			
				EnviaL('N');			
				TRISC = 0b00100000;
				PORTC = 0;
				CCP1CON = 0b00001100;
				CCPR1L = 49;
				PIR1bits.TMR2IF = 0;
				T2CON = 0b00000011;
				TocaNota(141,71,0);
				if (RA3==0){		// Que s'apagui l'alarma
					z=1;
				}
				Polsad=Polsador();
				if (Polsad==1){			// Activar c perquè s'entri en el while
					c=1;
				}
				while (c==1){			// Que soni la cucaracha
					Cucaracha();
				}
				if(Polsad==2){
					r=1;
				}
				while (r==1){			// Que soni cançó més relaxant
					Relax();
				}
				if(Polsad==5){
					cumple=1;
				}
				while (cumple==1){		// Que soni cumpleaños feliz
					Cumple();
				}
			}      
		}
	}    
}
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;
}
char LlegirI2C(char AdreMem) {
	char Rebut;				// Valor rebut
	SDAsortida();				// Posa SDA com a sortida
	StartI2C();				// Envia el bit d'inici I2C
	EnvByteI2C(AdreI2C);			// Enviem l'adreça del dispositiu
						// Amb un zero al final per indicar escriptura
	SDAentrada();				// Posa SDA com a entrada
	ACK_S();				// Reb un ACK des de l'esclau
	SDAsortida();				// Posa SDA com a sortida
	EnvByteI2C(AdreMem);			// Adreça a enviar
	SDAentrada();				// Posa SDA com a entrada
	ACK_S();				// Reb un ACK des de l'esclau
	SDAsortida();				// Posa SDA com a sortida
	StartI2C();				// Envia el bit d'inici I2C
	EnvByteI2C(AdreI2C+1);			// Enviem l'adreça del dispositiu
						// Amb un 1 al final per indicar lectura
	SDAentrada();				// Posa SDA com a entrada
	ACK_S();				// Reb un ACK des de l'esclau
	Rebut = RebByteI2C();			// Rep el byte
	SDAsortida();				// Posa SDA com a sortida
	NACK_M();				// Envia un NACK a l'esclau
	StopI2C();				// Envia el bit d'aturada I2C
	return Rebut;				// Retorna el valor
}
void EscriuI2C(char AdreMem, char Dades) {
	SDAsortida();				// Posa SDA com a sortida
	StartI2C();				// Envia el bit d'inici I2C
	EnvByteI2C(AdreI2C);			// Enviem l'adreça del dispositiu
						// Amb un zero al final per indicar escriptura
	SDAentrada();				// Posa SDA com a entrada
	ACK_S();				// Reb un ACK des de l'esclau
	SDAsortida();				// Posa SDA com a sortida
	EnvByteI2C(AdreMem);			// Adreça a enviar
	SDAentrada();				// Posa SDA com a entrada
	ACK_S();				// Reb un ACK des de l'esclau
	SDAsortida();				// Posa SDA com a sortida
	EnvByteI2C(Dades);			// Dades a enviar
	SDAentrada();				// Posa SDA com a entrada
	ACK_S();				// Reb un ACK des de l'esclau
	SDAsortida();				// Posa SDA com a sortida
	StopI2C();				// Envia el bit d'aturada I2C
}
void SDAentrada() {
	TRISCbits.TRISC7 = 1;			// Posem SDA com a entrada
}
void SDAsortida() {
	TRISCbits.TRISC7 = 0;			// Posem SDA com a sortida
}
void StartI2C() {
	Port = Port | 0b11000000;		// Abans de començar, SDA ha d'estar activat
						// i SCL també
	PORTC = Port;
	__delay_us(2);				// Allarguem el pols
	Port = Port & 0b01111111;		// Bit d'inici, posem SDA a zero
	PORTC = Port;
	__delay_us(2);				// Allarguem el pols
	Port = Port & 0b10111111;		// Fi del bit d'inici, posem SCL a zero
	PORTC = Port;
}
void StopI2C() {
	Port = Port & 0b01111111;		// Desactivem SDA
	Port = Port | 0b01000000;		// i activem SCL
	PORTC = Port;
	__delay_us(2);				// Allarguem el pols
	Port = Port | 0b10000000;		// Posem SDA a 1
	PORTC = Port;
}
void ACK_S() {
	Port = Port | 0b01000000;		// Posem SCL a 1
	PORTC = Port;
	__delay_us(2);				// Allarguem el pols
	Port = Port & 0b10111111;		// Posem SCL a zero
	PORTC = Port;
	Port = Port | 0b10000000;		// Posem SDA a 1
	PORTC = Port;
}
void NACK_M() {
	Port = Port | 0b10000000;		// Posem SDA a 1
	PORTC = Port;
	Port = Port | 0b01000000;		// Posem SCL a 1
	PORTC = Port;
	__delay_us(2);				// Allarguem el pols
	Port = Port & 0b10111111;		// Posem SCL a zero
	PORTC = Port;
}
void EnvByteI2C(char Buffer) {
	char Temp;				// Variable temporal
	for (int k = 1; k < 9; k++){
		Port = Port & 0b10111111;	// Posem SCL a zero per modificar SDA
		PORTC = Port;
		Temp = Buffer & 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 & 0b01111111;		// Desactivem SDA
		} else {			// Si val 128
			Port = Port | 0b10000000;		// Posem SDA a 1
		}
		Buffer = Buffer << 1;		// Rodem els bits per situar el següent
		PORTC = Port;
		Port = Port | 0b01000000;	// Activem SCL perquè el receptor llegeixi el bit
		PORTC = Port;
	}
	Port = Port & 0b10111111;		// Posem SCL a zero per modificar SDA
	PORTC = Port;
}
char RebByteI2C() {
	char Buffer;				// Valor rebut
	Port = Port & 0b10111111;		// Posem SCL a zero
	PORTC = Port;
	for (int k = 1; k < 9; k++){
		Port = Port | 0b01000000;	// Posem SCL a 1
		PORTC = Port;
		Buffer = Buffer << 1;		// Rodem els bits per situar el següent
						// a la dreta hi quedarà un zero
		if (RC7 == 1) {
			Buffer = Buffer | 0b00000001;		// Si SDA està activat, posem un 1
		}
		Port = Port & 0b10111111;	// Posem SCL a zero
		PORTC = Port;
	}
	return Buffer;				// Retorna el valor
}
void EnviaL(char Caracter) {
	TXREG = Caracter;			//  Agafa el caràcter i l'envia
	_delay(5);				// Donem temps
	while (PIR1bits.TXIF == 0);		// Esperem a que s'acabi d'enviar
		;				// No fem res
}
void EnviaBCD2(char Caracter) {
	char Temp;				// Variable temporal
	Temp = Caracter & 0b11110000;		// Agafem el primer dígit
	Temp = Temp >> 4;			// Rodem els bits per situar-los a la dreta
	Temp = Temp + '0';			// Ho convertim a ASCII
	EnviaL(Temp);				// Envia el primer dígit
	Temp = Caracter & 0b00001111;		// Agafem el segon dígit
	Temp = Temp + '0';			// Ho convertim a ASCII
	EnviaL(Temp);				// Envia el segon dígit
}
void EnviaBCD1(char Caracter) {
	char Temp;				// Variable temporal
	Temp = Caracter & 0b00001111;		// Agafem el segon dígit
	Temp = Temp + '0';			// Ho convertim a ASCII
	EnviaL(Temp);				// Envia el segon dígit
}
void Alarma(void){
	EscriuI2C(9, m);			// Minuts
	EscriuI2C(8, h);			// Hores
	z=0;					// Activador1 encès
	while(a==1){
		__delay_ms(200);
		Polsad=Polsador();
		Esborra();
		Bit1();
		Lectura = LlegirI2C(8);		// Hores
		EnviaBCD2(Lectura);		// Mostrem a la pantalla el valor
		EnviaL('.');			// Separador
		Lectura = LlegirI2C(9);		// Minuts
		EnviaBCD2(Lectura);		// Mostrem a la pantalla el valor
		EnviaL(' ');			// Espai
		EnviaL(' ');			// Espai
		EnviaL(' ');			// Espai
		EnviaL(' ');
		EnviaL(' ');			// Espai
		EnviaL(' ');
		EnviaL('O');			// Espai
		if (RA3==0 && q==0){ 
			__delay_ms(200);
			q=1;   
		} else if (RA3==0 && q==1){
			__delay_ms(200);
			q=0;
		}    
		if (q==1){
			EnviaL('N');		// escriu 'ON'
			w=1;                    // Alarma activada
		} else if (q==0){     
			EnviaL('F');
			EnviaL('F');            // escriu off
			w=0;                    // Alarma apagada
		}
		if(Polsad==5){
			h=LlegirI2C(8);
			m=LlegirI2C(9);
			a=0;
		}
		if (Polsad==1){			// Augmentem hores
			Bit1();
			L=LlegirI2C(8);
			E=L/16;
			D=L%16;
			A=E*10+D;
			if (A==9){ 
				EnviaBCD2(10);
				EscriuI2C(8, 0x10);   
			} else if (A==19){ 
				EnviaBCD2(20);
				EscriuI2C(8, 0x20);   
			} else if (A==23){ 
				EnviaBCD2(00);
				EscriuI2C(8, 0x00);  
			} else{
				E=A/10;
				D=A%10+1;
				X=E*16+D;
				EnviaBCD2(X);
				EscriuI2C(8, X);
			}         
		}
		if (Polsad==2){
			Bit1();
			L=LlegirI2C(9);		// Augmentem Minuts 
			E=L/16;
			D=L%16;
			A=E*10+D;      
			if (D==9){ 
				if(E==5){
					EnviaBCD2(00);
					EscriuI2C(9, 0x00);
				} else{
					E=E+1;
					D=0;
					X=E*16+D;
					EnviaBCD2(X);
					EscriuI2C(9, X);
				}
			} else{
				D=A%10+1;
				X=E*16+D;
				EnviaBCD2(X);
				EscriuI2C(9, X);
			}    
		}
	}
}    
void Esborra(void) {
	EnviaL(254);				// Caràcter de control
	EnviaL(1);				// Esborra la pantalla i posa el cursor a l'inici
}
void Hora(void){
	Bit1();
	L=LlegirI2C(2);
	E=L/16;
	D=L%16;
	A=E*10+D;
	if (A==9){ 
		EnviaBCD2(10);
		EscriuI2C(2, 0x10);   
	} else if (A==19){ 
		EnviaBCD2(20);
		EscriuI2C(2, 0x20);   
	} else if (A==23){ 
		EnviaBCD2(00);
		EscriuI2C(2, 0x00);  
	} else{
		E=A/10;
		D=A%10+1;
		X=E*16+D;
		EnviaBCD2(X);
		EscriuI2C(2, X);
	}
}
void Minuts(void){
	Bit1();
	L=LlegirI2C(1);				// Minuts 
	E=L/16;
	D=L%16;
	A=E*10+D;      
	if (D==9){ 
		if(E==5){
			EnviaBCD2(00);
			EscriuI2C(1, 0x00);
		} else{
			E=E+1;
			D=0;
			X=E*16+D;
			EnviaBCD2(X);
			EscriuI2C(1, X);
		}
	} else{
		D=A%10+1;
		X=E*16+D;
		EnviaBCD2(X);
		EscriuI2C(1, X);
	}    
}
void Bit1(void){
	Posicio = 64;				// La primera columna de la segona fila és 64
	Posicio = Posicio + 128;		// Posa el bit de posicionat a 1
	EnviaL(254);
	EnviaL(Posicio);
}
void Bit2(void){
	Posicio = 0;				// La primera columna de la primera fila és 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(200);	   	 	// Retard de 0,2 s
	TRISC = 0b00100000;			// Posem RC5 (sortida del PWM) com a entrada
						// O sigui, silenci
	__delay_ms(200);	   	 	// Retard de 0,2 s
}
void Cucaracha(void){
	DO();
	DO();
	DO();
	FA();
	LA();
	DO();
	DO();
	DO();
	FA();
	LA();
	FA();
	FA();
	MI();
	MI();
	RE();
	RE();
	DO();
	DO();
	DO();
	DO();
	MI();
	SOL();
	DO();
	DO();
	DO();
	MI();
	SOL();
	DO();
	RE();
	DO();
	SI();
	LA();
	SOL();
	FA();
	c=0;
	z=1;
}
void Relax(){
	MI();
	MI();
	SOL();
	MI();
	MI();
	SOL();
	MI();
	SOL();
	DO();
	SI();
	LA();
	LA();
	SOL();
	RE();
	MI();
	FA();
	RE();
	RE();
	MI();
	FA();
	RE();
	FA();
	SI();
	LA();
	SOL();
	SI();
	DOO();
	DO();
	DO();
	r=0;
	z=1;
}
void Cumple(void){
	DO();
	DO();
	RE();
	DO();
	FA();
	MI();
	DO();
	DO();
	RE();
	DO();
	SOL();
	FA();
	DO();
	DO();
	DOO();
	LA();
	FA();
	FA();
	MI();
	RE();
	SI();
	SI();
	LA();
	FA();
	SOL();
	FA();
	cumple=0;
	z=1;
}
void DO(void){
	TocaNota(238,119,2);
	__delay_ms(100);
}
void RE(void){
	TocaNota(212,106,2);
	__delay_ms(100);
}
void MI(void){
	TocaNota(189,95,0);
	__delay_ms(100);
}
void FA(void){
	TocaNota(178,89,2);
	__delay_ms(100);
}
void SOL(void){
	TocaNota(158,79,2); 
	__delay_ms(100);
}
void LA(void){
	TocaNota(141,71,0); 
	__delay_ms(100);
}
void SI(void){
	TocaNota(126,63,2); 
	__delay_ms(100);
}
void DOO(void){
	TocaNota(118,59,2);
	__delay_ms(100);
}

 

 

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