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
}

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