Programació en C del PIC 16F690

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

Rellotge digital

Programa del grup 2

En aquest cas es tracta d'un rellotge despertador en el que l'usuari, a més de poder ajustar l'hora, disposa de tres melodies diferents per a l'alarma.

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
char MissatgeAlarma[13]={'J','A',' ','H','A',' ','A','R','R','I','B','A','T'};
char Alarma1[45]={
	126, 63, 2,126, 63, 2,118, 59, 2,212, 106, 2,
	212, 106, 2,118, 59, 2,126, 63, 2,141, 71, 0,
	158, 79, 2,158, 79, 2,141, 71, 0,126, 63, 2,
	126, 63, 2,141, 71, 0,141, 71, 0};	// El himno de la alegria
char Alarma2[48]={
	158, 79, 2,158, 79, 2,189, 95, 0,178, 89, 2,238, 119, 2,
	189, 95, 0,178, 89, 2,238, 119, 2,212, 106, 2,212, 106, 2,
	126, 63, 2,238, 119, 2,158, 79, 2,126, 63, 2,238, 119, 2,
	158, 79, 2};				// I follow rivers
char Alarma3[36]={
	189, 95, 0,158, 79, 2,141, 71, 0,189, 95, 0,158, 79, 2,
	126, 63, 2, 141, 71, 0,189, 95, 0,158, 79, 2,141, 71, 0,
	158, 79, 2,189, 95, 0};			// Smoke on the water
unsigned char Compta = 0;			// Comptador inicialitzat a 0
char Polsad;					// Polsador que s'ha premut
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 D;						// Desenes de la hora, minuts...
char E;						// Unitats de la hora, minuts...
char Decimal;					// Valor decimal de Lectura
unsigned char horaAlarm = 0x00;			// Hora alarma per 

unsigned char minAlarm = 0x00;			// Minuts alarma per defecte
unsigned char alarma = 0;			// Alarma desactivada per defecte (alarma=1 activada)
unsigned char melodia = 1;			// Melodia predeterminada
						// Definició de les funcions que farem servir 
char Polsador(void);				// Funció de lectura dels polsadors
void Cursor(char Filera, char Columna);		// Posiciona el cursor (filera 1 a 2
						// i columna 1 a 32, segons pantalla)
void Esborra(void);				// Esborra la pantalla i posa el cursor a l'inici
void MostrarHora(void);				// Mostra la hora en pantalla
void Incrementa(void);				// Incrementa una unitat
void Decrementa(void);				// Decrementa una unitat
void Modifica(void);				// Permet que l'usuari pugui modificar l'hora i la data
void ConfiguraAlarma(void);			// Configuració de l'hora i dels minuts de l'alarma
void ActivaAlarma(void);			// Permet activar i desactivar l'alarma
void LletresAlarma(void);			// JA HA ARRIBAT L'HORA
void SonaAlarma1(void);				// Fa sonar l'alarma1
void SonaAlarma2(void);				// Fa sonar l'alarma2
void SonaAlarma3(void);				// Fa sonar l'alarma3
void SonaAlarma4(void);				// Fa sonar l'alarma4
void TocaNota(char ValPR2, char ValCCPR1L, char ValDC1B);
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 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 = 0b00100000;			// Tot el port C és de sortida
	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
	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
	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
						// Com a mostra, es posen les 12.00.00
						// del dimarts 20-3-2018
	EscriuI2C(0, 0x00);			// Segons
	EscriuI2C(1, 0x00);			// Minuts
	EscriuI2C(2, 0x12);			// Hores
	EscriuI2C(3, 0x02);			// Dia setmana (dijous)
	EscriuI2C(4, 0x20);			// Dia mes
	EscriuI2C(5, 0x03);			// Mes (març)
	EscriuI2C(6, 0x18);			// Any (2016)
	EscriuI2C(7, 0x00);			// Polsos desactivats
	while (1) {
		Polsad = Polsador();		// Llegim els polsadors
		__delay_ms(100);		// Retard de 0,1 s
		Compta++;
		if (Compta==10){
			MostrarHora();
			Compta=0;
		}
		if (Polsad==5) {
			while (Polsad==5) {
				Polsad=Polsador();
			}
			ActivaAlarma();
		}
		if (alarma==1) {
			if (melodia==1) {
				SonaAlarma1();
			}
			if (melodia==2) {
				SonaAlarma2();
			}
			if (melodia==3) {
				SonaAlarma3();
			}
		}
		if (Polsad==1) {
			ConfiguraAlarma();
			alarma=1;
			Cursor(2,16);
			EnviaL('A');		// Lletra
		}
		if (Polsad==2) {
			Modifica();
		} else {
			Port = Port | 0b00001111;  
		} 
	}
}
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 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 Esborra(void) {
	EnviaL(254);				// Caràcter de control
	EnviaL(1);				// Esborra la pantalla i posa el cursor a l'inici
}
void MostrarHora() {
	Posicio = 64;				// La primera columna de la segona fila és 64
	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
	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
	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
	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);			// Dia
	EnviaBCD2(Lectura);			// Mostrem a la pantalla el valor
	EnviaL(' ');				// Espai
	EnviaL(' ');				// Espai
	Lectura = LlegirI2C(3);			// Dia
	EnviaBCD1(Lectura);			// Mostrem a la pantalla el valor
}
void Incrementa() {
	E=Lectura/16;
	D=Lectura%16;
	Decimal=10*E+D;
	Decimal++;
	Lectura=(Decimal/10)*16+Decimal%10;    
}
void Decrementa() {
	E=Lectura/16;
	D=Lectura%16;
	Decimal=10*E+D;
	Decimal--;
	Lectura=(Decimal/10)*16+Decimal%10;    
}
void Modifica() {
	while (Polsad==2) {
		Polsad = Polsador();		// Llegim els polsadors   
		Lectura = LlegirI2C(2);		// Hores
	} 
	while (Polsad!=2) {
		Polsad=Polsador();
		Esborra();
		EnviaL('H');			// Lletra
		EnviaL('O');			// Lletra
		EnviaL('R');			// Lletra
		EnviaL('A');			// Lletra
		Cursor(2, 1);			// Posició
		EnviaBCD2(Lectura);		// Mostrem a la pantalla el valor
		__delay_ms(75);			// Retard de 0,075 s
		if (Polsad==3) {
			if (Lectura==0x23) {
				Lectura=0x00;                                                   
			} else {
				Incrementa();
			}        
			__delay_ms(75);		// Retard de 0,075 s
			EnviaBCD2(Lectura);	// Mostrem a la pantalla el valor
		}
		if (Polsad==4) {
			if (Lectura==0x00) {
				Lectura=0x23;                                                   
			} else {
				Decrementa();
			}        
			__delay_ms(75);		// Retard de 0,075 s
			EnviaBCD2(Lectura);	// Mostrem a la pantalla el valor
		}
		EscriuI2C(2, Lectura);		// Hores
	}
	while (Polsad==2) {
		Polsad=Polsador();
		Lectura = LlegirI2C(1);		// Minuts
	}
	while (Polsad!=2) {
		Polsad=Polsador();
		Esborra();
		EnviaL('M');			// Lletra
		EnviaL('I');			// Lletra
		EnviaL('N');			// Lletra
		EnviaL('U');			// Lletra
		EnviaL('T');			// Lletra
		EnviaL('S');			// Lletra
		Cursor(2, 1);			// Posició
		EnviaBCD2(Lectura);		// Mostrem a la pantalla el valor
		__delay_ms(75);			// Retard de 0,075 s
		if (Polsad==3) {
			if (Lectura==0x59) {
				Lectura=0x00;                           
			} else {
				Incrementa();
			}
			__delay_ms(75);		// Retard de 0,075 s
			EnviaBCD2(Lectura);	// Mostrem a la pantalla el valor
		}
		if (Polsad==4) {
			if (Lectura==0x00) {
				Lectura=0x59;                                                   
			} else {
				Decrementa();
			}        
			__delay_ms(75);		// Retard de 0,075 s
			EnviaBCD2(Lectura);	// Mostrem a la pantalla el valor
		}
		EscriuI2C(1, Lectura);		// Minuts
	}
	while (Polsad==2) {
		Polsad=Polsador();
		Lectura = LlegirI2C(3);		// Dia setmana
	}
	while (Polsad!=2) {
		Polsad=Polsador();
		Esborra();
		EnviaL('D');			// Lletra
		EnviaL('I');			// Lletra
		EnviaL('A');			// Lletra
		Cursor(1,5);
		EnviaL('S');			// Lletra
		EnviaL('E');			// Lletra
		EnviaL('T');			// Lletra
		EnviaL('M');			// Lletra
		EnviaL('A');			// Lletra
		EnviaL('N');			// Lletra
		EnviaL('A');			// Lletra
		Cursor(2,1);
		EnviaBCD2(Lectura);		// Mostrem a la pantalla el valor
		__delay_ms(75);			// Retard de 0,05 s
		if (Polsad==3) {
			if (Lectura==0x7) {
				Lectura=0x01;                           
			} else {
				Incrementa();
			}
			__delay_ms(75);		// Retard de 0,075 s
			EnviaBCD2(Lectura);	// Mostrem a la pantalla el valor
		}
		if (Polsad==4) {
			if (Lectura==0x01) {
				Lectura=0x07;                                                   
			} else {
				Decrementa();
			}        
			__delay_ms(75);		// Retard de 0,075 s
			EnviaBCD2(Lectura);	// Mostrem a la pantalla el valor
		}
		EscriuI2C(3, Lectura);		// Dia setmana
	}
	while (Polsad==2) {
		Polsad=Polsador();
		Lectura = LlegirI2C(4);		// Dia mes
		}
	while (Polsad!=2) {
		Polsad=Polsador();
		Esborra();
		EnviaL('D');			// Lletra
		EnviaL('I');			// Lletra
		EnviaL('A');			// Lletra
		Cursor(1,5);
		EnviaL('M');			// Lletra
		EnviaL('E');			// Lletra
		EnviaL('S');			// Lletra
		Cursor(2,1);
		EnviaBCD2(Lectura);		// Mostrem a la pantalla el valor
		__delay_ms(75);			// Retard de 0,075 s
		if (Polsad==3) {
			if (Lectura==0x31) {
				Lectura=0x01;                           
			} else {
				Incrementa();
			}
			__delay_ms(75);		// Retard de 0,075 s
			EnviaBCD2(Lectura);	// Mostrem a la pantalla el valor
		}
		if (Polsad==4) {
			if (Lectura==0x01) {
				Lectura=0x31;                                                   
			} else {
				Decrementa();
			}
			__delay_ms(75);		// Retard de 0,075 s
			EnviaBCD2(Lectura);	// Mostrem a la pantalla el valor
		}
		EscriuI2C(4, Lectura);		// Dia mes
	}
	while (Polsad==2) {
		Polsad=Polsador();
		Lectura = LlegirI2C(5);		// Mes
	}
	while (Polsad!=2) {
		Polsad=Polsador();
		Esborra();
		EnviaL('M');			// Lletra
		EnviaL('E');			// Lletra
		EnviaL('S');			// Lletra
		Cursor(2,1);
		EnviaBCD2(Lectura);		// Mostrem a la pantalla el valor
		__delay_ms(75);			// Retard de 0,075 s
		if (Polsad==3) {
			if (Lectura==0x12) {
				Lectura=0x01;                           
			} else {
				Incrementa();
			}
			__delay_ms(75);		// Retard de 0,075 s
			EnviaBCD2(Lectura);	// Mostrem a la pantalla el valor
		}
		if (Polsad==4) {
			if (Lectura==0x01) {
				Lectura=0x12;                                                   
			} else {
				Decrementa();
			}        
			__delay_ms(75);		// Retard de 0,075 s
			EnviaBCD2(Lectura);	// Mostrem a la pantalla el valor
		}
		EscriuI2C(5, Lectura);		// Mes
	}
	while (Polsad==2) {
		Polsad=Polsador();
		Lectura = LlegirI2C(6);		// Any
	}
	while (Polsad!=2) {
		Polsad=Polsador();
		Esborra();
		EnviaL('A');			// Lletra
		EnviaL('N');			// Lletra
		EnviaL('Y');			// Lletra
		Cursor(2,1);
		EnviaBCD2(Lectura);		// Mostrem a la pantalla el valor
		__delay_ms(75);			// Retard de 0,075 s
		if (Polsad==3) {
			if (Lectura==0x99) {
				Lectura=0x00;                           
			} else {
				Incrementa();
			}
			__delay_ms(75);		// Retard de 0,075 s
			EnviaBCD2(Lectura);	// Mostrem a la pantalla el valor
		}
		if (Polsad==4) {
			if (Lectura==0x00) {
				Lectura=0x23;                                                   
			} else {
				Decrementa();
			}        
			__delay_ms(75);		// Retard de 0,075 s
			EnviaBCD2(Lectura);	// Mostrem a la pantalla el valor
		}
		EscriuI2C(6, Lectura);		// Any
	}
	while (Polsad==2) {
		Polsad=Polsador();
	}
	EscriuI2C(0, 0x00);			// Segons a zero
}
void ConfiguraAlarma() {
	while (Polsad==1) {
		Polsad = Polsador();		// Llegim els polsadors   
	}
	while (Polsad!=1) {
		Polsad=Polsador();
		Esborra();
		EnviaL('A');			// Lletra
		EnviaL('.');			// Lletra
		EnviaL('H');			// Lletra
		EnviaL('O');			// Lletra
		EnviaL('R');			// Lletra
		EnviaL('A');			// Lletra
		Cursor(2, 1);			// Posició
		EnviaBCD2(horaAlarm);		// Mostrem a la pantalla el valor
		__delay_ms(75);			// Retard de 0,075 s
		if (Polsad==3) {
			if (horaAlarm==0x23) {
				horaAlarm=0x00;                                                   
			} else {
				Lectura=horaAlarm;
				Incrementa();
				horaAlarm=Lectura;
			}        
			__delay_ms(75);		// Retard de 0,075 s
			EnviaBCD2(horaAlarm);	// Mostrem a la pantalla el valor
		}
		if (Polsad==4) {
			if (horaAlarm==0x00) {
				horaAlarm=0x23;                                                   
			} else {
				Lectura=horaAlarm;
				Decrementa();
				horaAlarm=Lectura;
			}        
			__delay_ms(75);		// Retard de 0,075 s
			EnviaBCD2(horaAlarm);	// Mostrem a la pantalla el valor
		}     
	}
	while (Polsad==1) {
		Polsad = Polsador();		// Llegim els polsadors   
	}
	while (Polsad!=1) {
		Polsad=Polsador();
		Esborra();
		EnviaL('A');			// Lletra
		EnviaL('.');			// Lletra
		EnviaL('M');			// Lletra
		EnviaL('I');			// Lletra
		EnviaL('N');			// Lletra
		EnviaL('U');			// Lletra
		EnviaL('T');			// Lletra
		EnviaL('S');			// Lletra
		Cursor(2, 1);			// Posició
		EnviaBCD2(minAlarm);		// Mostrem a la pantalla el valor
		__delay_ms(75);			// Retard de 0,075 s
		if (Polsad==3) {
			if (minAlarm==0x59) {
				minAlarm=0x00;                                                   
			} else {
				Lectura=minAlarm;
				Incrementa();
				minAlarm=Lectura;
			}        
			__delay_ms(75);		// Retard de 0,075 s
			EnviaBCD2(minAlarm);	// Mostrem a la pantalla el valor
		}
		if (Polsad==4) {
			if (minAlarm==0x00) {
				minAlarm=0x59;                                                   
			} else {
				Lectura=minAlarm;
				Decrementa();
				minAlarm=Lectura;
			}        
			__delay_ms(75);		// Retard de 0,075 s
			EnviaBCD2(minAlarm);	// Mostrem a la pantalla el valor
		}     
	}
	while (Polsad==1) {
		Polsad=Polsador();
	}
	while (Polsad!=1) {
		Polsad=Polsador();
		Esborra();
		EnviaL('M');			// Lletra
		EnviaL('E');			// Lletra
		EnviaL('L');			// Lletra
		EnviaL('O');			// Lletra
		EnviaL('D');			// Lletra
		EnviaL('I');			// Lletra
		EnviaL('A');			// Lletra
		Cursor(2, 1);			// Posició
		EnviaBCD2(melodia);		// Mostrem a la pantalla el valor
		__delay_ms(75);			// Retard de 0,075 s
		if (Polsad==3) {
			if (melodia==3) {
				melodia=1;
			} else {
				melodia++;
			}
			__delay_ms(75);		// Retard de 0,075 s
			EnviaBCD2(melodia);	// Mostrem a la pantalla el valor
		}
		if (Polsad==4) {
			if (melodia==1) {
				melodia=3;
			} else {
				melodia--;
			}
			__delay_ms(75);		// Retard de 0,075 s
			EnviaBCD2(melodia);	// Mostrem a la pantalla el valor
		}
	}
	while (Polsad==1) {
		Polsad=Polsador();
	}
}
void ActivaAlarma(void) {
	if (alarma==0) {
		alarma=1;
		Cursor(2,16);
		EnviaL('A');			// Lletra 
	} else {
		alarma=0;
		Cursor(2,16);
		EnviaL(' ');			// Lletra
	}
}
void LletresAlarma(void){
	Esborra();
	for (int k = 0; k < 13; k=k+1){
		EnviaL(MissatgeAlarma[k]);	// Lletra 
	}
	Cursor(2,1);
	EnviaL('L');				// Lletra
	EnviaL(0x27);				// Lletra
	EnviaL('H');				// Lletra
	EnviaL('O');				// Lletra
	EnviaL('R');				// Lletra
	EnviaL('A');				// Lletra
}
void SonaAlarma1(void) {			// El himno de la alegria
	while (horaAlarm==LlegirI2C(2) && minAlarm==LlegirI2C(1)) {
		LletresAlarma();
		for (int k = 0; k < 43; k=k+3){
			TocaNota(Alarma1[k],Alarma1[k+1],Alarma1[k+2]);
			Polsad = Polsador();	// Llegim els polsadors
			if (Polsad==4) {
				alarma=0;
				break;
			}
		}
		break;
	}
}
void SonaAlarma2(void) {			// I follow rivers
	while (horaAlarm==LlegirI2C(2) && minAlarm==LlegirI2C(1)) {
		LletresAlarma();        
		for (int k = 0; k < 46; k=k+3){
			TocaNota(Alarma2[k],Alarma2[k+1],Alarma2[k+2]);
			Polsad = Polsador();	// Llegim els polsadors
			if (Polsad==4) {
				alarma=0;
				break;
			}
		}
		break;
	}
}
void SonaAlarma3(void) {			// Smoke on the water
	while (horaAlarm==LlegirI2C(2) && minAlarm==LlegirI2C(1)) {
		LletresAlarma();        
		for (int k = 0; k < 34; k=k+3){
			TocaNota(Alarma3[k],Alarma3[k+1],Alarma3[k+2]);
			Polsad = Polsador();	// Llegim els polsadors
			if (Polsad==4) {
				alarma=0;
				break;
			}
		}
		break;
	}
}
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
}
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 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
}

 

 

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