Aquest dispositiu mostra la data i l'hora. A més, es pot configurar una alarma que, a l'hora programada, fa sonar una melodia. També l'opció de mostrar l'hora a la matriu de leds, fent servir una porció de 3 ⨯ 4 leds per a cada dígit.
Per a la gestió del temps fan servir el temporitzador 0 i una interrupció, que també gestiona la matriu de leds.
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 <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 PolsadorS RA3 // Li assigna un nom a l'adreça del polsador #define FiTimer0 INTCONbits.T0IF // Li assigna un nom al bit que indica el final del Timer 0 #define flipbit(var, bit) ((var) ^= (1<<(bit)))
char Port; // Gestió del port a la funció Envia_max
char Compta; // Comptador de bits a la funció Envia_max
unsigned char ComptaB = 0;
char Sortida[6]; // Valors a enviar al MAX7221 (48 bits)
char Sorti[6]; // Valors a enviar al MAX7221 des de la interrupció
char Actiu; // Variable que diu quin color està actiu
// Actiu = 0 Apagat
// Actiu = 1 Vermell
// Actiu = 2 Verd
// Actiu = 3 Blau
char i;
char j;
char l;
char Menu=2;
char Comptar; // Comptador de bits a la funció Envia3max
char fig1[3][8];
char numLed[10][4] = {{0b01000000, 0b10100000, 0b10100000, 0b01000000}, // Zero
{0b00100000, 0b01100000, 0b00100000, 0b00100000}, // U
{0b01100000, 0b10100000, 0b01000000, 0b11100000}, // Dos
{0b11100000, 0b01000000, 0b00100000, 0b11100000}, // Tres
{0b01100000, 0b10100000, 0b11110000, 0b00100000}, // Quatre
{0b11100000, 0b11000000, 0b00100000, 0b11000000}, // Cinc
{0b11000000, 0b10000000, 0b11100000, 0b11100000}, // Sis
{0b11100000, 0b00100000, 0b01000000, 0b01000000}, // Set
{0b11100000, 0b10100000, 0b11100000, 0b11100000}, // Vuit
{0b11100000, 0b10100000, 0b01100000, 0b00100000}}; // Nou
unsigned char Valor; // Variable de 8 bits sense signe (0 a 255)
unsigned char ComptaT; // Variable de 8 bits sense signe (0 a 255)
char h=0;
char min=0;
char s=0;
char d[8]={0, 1, 0, 1, 2, 0, 2, 5};
char dIni[8]={0, 1, 0, 1, 2, 0, 2, 5};
char alarmaH=0;
char alarmaM=0;
char aSet=0;
char selec=1;
char diaSetmana=2;
char lletresDS[7][3] = {{'L', 'U', 'N'}, {'M', 'A', 'R'}, {'M', 'I', 'E'}, {'J', 'U', 'E'},
{'V', 'I', 'E'}, {'S', 'A', 'B'}, {'D', 'O', 'M'}};
unsigned char Analogica (void); // Funció de lectura del conversor
char Polsad; // Polsador que s'ha premut
char Polsador(void); // Funció de lectura dels polsadors
void EnviaL(char Caracter); // Envia un caràcter
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(void); // Envia un joc de valors als tres MAX7221
// desactivant interrupcions
void Envia_max(void); // Envia un joc de valors als tres MAX7221
void Ini3max(void); // Inicialitza els tres MAX7221
void Apaga(void); // Apaga tots els LED
void TocaNota(char ValPR2, char ValCCPR1L, char ValDC1B);
void OperacioT(void);
void OperacioCAL(void);
void Alarma(void);
void main(void) {
TRISC = 0; // Tot el port C és de sortida
TRISB = 0; // Tot el port B és de sortida
TRISA = 0xFF; // Tot el port A és d'entrada
ANSEL = 0b00000101; // Configura AN0 i AN2 com entrada analògica
ANSELH = 0; // Desactiva les altres entrades analògiques
PORTC = 0; // Inicialitza a 0 el port C
PORTB = 0; // Inicialitza a 0 el port B
Ini3max(); // Inicialitza els tres MAX7221
Actiu = 1; // Activa el color vermell
TMR0 = 100; // Presselecció de 100, que són 156 iteracions
// Correspon a una interrupció cada 7,5 ms
CCP1CON = 0b00001100; // Configura el PWM, bits P1M (bits 7-6) a 00 mode senzill
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
PIR1bits.TMR2IF = 0; // Desactiva el bit d'interrupció del Timer 2
T2CON = 0b00000011; // Configura el Timer 2
ADCON1 = 0b00010000; // Posa el conversor a 1/8 de la freqüència
ADCON0 = 0b00001001;
INTCON = 0b10100000; // Habilitem la interrupció per Timer0
// Configuració del Timer 0
FiTimer0 = 0; // Aquest bit es posarà a 1 quan el temporitzador acabi
// cal desactivar-lo des del programa
OPTION_REG = 0b10000100; // Configuració de Timer0
// Com a temporitzador basat en rellotge
// 111 - Factor d'escala de 256
// I resistències de pull-up desactivades (valor per defecte)
INTCONbits.GIE = 1; // Habilitem les interrupcions a nivell general
Apaga(); // Apaga tots els LED
while (1){
if (Menu==1) { // Menu 1
Apaga();
PORTC = 0b00000001; // Activem el LED 0 com a indicació visual del menu on estem
Esborra(); // Enviem a la pantalla l'hora actual
Cursor(2,1); // Enviem a la pantalla la data actual
EnviaL(d[0]+'0');
EnviaL(d[1]+'0');
EnviaL('/');
EnviaL(d[2]+'0');
EnviaL(d[3]+'0');
EnviaL('/');
EnviaL(d[4]+'0');
EnviaL(d[5]+'0');
EnviaL(d[6]+'0');
EnviaL(d[7]+'0');
Cursor(2,14); // Enviem a la pantalla el dia de la setmana actual
for (i=0;i<3;i++){
EnviaL(lletresDS[diaSetmana][i]);
}
do { // Bucle que s'executa mentre estem al menu 1
OperacioT();
Cursor(1,1);
EnviaL(h/10 + '0');
EnviaL(h%10 + '0');
EnviaL(':');
EnviaL(min/10 + '0');
EnviaL(min%10 + '0');
EnviaL(':');
EnviaL(s/10 + '0');
EnviaL(s%10 + '0');
Alarma();
if (PolsadorS==0) { // Comprova l'estat del polsador per veure si s'ha canviat de menu
__delay_ms(250); // Retard de 250 ms per evitar canvis de menu extres
Menu = 2; // Canvi de menu
}
} while (Menu==1);
}
if (Menu==2) {
PORTC = 0b00000010; // Activem el LED 1 com a indicació visual del menu on estem
Polsad = Polsador();
Esborra();
Cursor(1,6);
EnviaL(alarmaH/10+'0');
EnviaL(alarmaH%10+'0');
EnviaL(':');
EnviaL(alarmaM/10+'0');
EnviaL(alarmaM%10+'0');
Cursor(1,16);
EnviaL(aSet+'0');
selec=1;
Cursor(2,6);
EnviaL('^');
EnviaL('^');
EnviaL(' ');
EnviaL(' ');
EnviaL(' ');
do { // Bucle que s'executa mentre estem al menu 2
Polsad = Polsador(); // Llegim els polsadors
if (Polsad == 4) { // Si s'ha premut el polsador 4
aSet=2;
Cursor(1,16);
EnviaL(aSet+'0');
}
if (Polsad == 3) { // Si s'ha premut el polsador 3
aSet=1;
Cursor(1,16);
EnviaL(aSet+'0');
}
if (Polsad == 2) { // Si s'ha premut el polsador 2
aSet=0;
Cursor(1,16);
EnviaL(aSet+'0');
}
if (Polsad == 5) { // Si s'ha premut el polsador 5
ComptaB = 0;
if(selec==2){
selec=1;
Cursor(2,6);
EnviaL('^');
EnviaL('^');
EnviaL(' ');
EnviaL(' ');
EnviaL(' ');
} else {
selec=2;
Cursor(2,6);
EnviaL(' ');
EnviaL(' ');
EnviaL(' ');
EnviaL('^');
EnviaL('^');
}
while(Polsador() == 5) // Esperem a que el polsador es deixi anar
; // No fem res
do { // Bucle per comptar quants cops detectem el polsador premut
if (Polsad == 5) // Si el polsador està premut
ComptaB++; // Incrementa Compta
else // Si no està premut
ComptaB = 0; // Posa el comptador zero
_delay(1000); // Retard de 1000 cicles
} while (ComptaB < 5); // Es repeteix fins que hem comptat 5 cops
}
if (Polsad == 1) { // Si s'ha premut el polsador 1
ComptaB = 0;
if(selec==1){
alarmaH++;
if(alarmaH==24)
alarmaH=0;
}
if(selec==2){
alarmaM++;
if(alarmaM==60)
alarmaM=0;
}
Cursor(1,6);
EnviaL(alarmaH/10+'0');
EnviaL(alarmaH%10+'0');
EnviaL(':');
EnviaL(alarmaM/10+'0');
EnviaL(alarmaM%10+'0');
while(Polsador() == 1) // Esperem a que el polsador es deixi anar
; // No fem res
do { // Bucle per comptar quants cops detectem el polsador premut
if (Polsad == 1) // Si el polsador està premut
ComptaB++; // Incrementa Compta
else // Si no està premut
ComptaB = 0; // Posa el comptador zero
_delay(1000); // Retard de 1000 cicles
} while (ComptaB < 5); // Es repeteix fins que hem comptat 5 cops
}
OperacioT();
Alarma();
if (PolsadorS==0) { // Comprova l'estat del polsador per veure si s'ha canviat de menu
__delay_ms(250); // Retard de 250 ms per evitar canvis de menu extres
Menu = 3; // Canvi de menu
}
} while (Menu==2);
}
if (Menu==3) {
PORTC = 0b00000100; // Activem el LED 2 com a indicació visual del menu on estem
Esborra();
for (i=0;i<8;i++){ // Guardem la data inicial abans d'entrar al menu
dIni[i]=d[i];
}
do { // Bucle que s'executa mentre estem al menu 3
Polsad = Polsador(); // Llegim els polsadors
if (Polsad == 1) { // Si s'ha premut el polsador 1
ComptaB = 0;
h++;
s=0;
if(h==24){
h=0;
}
while(Polsador() == 1) // Esperem a que el polsador es deixi anar
; // No fem res
do { // Bucle per comptar quants cops detectem el polsador premut
if (Polsad == 1) // Si el polsador està premut
ComptaB++; // Incrementa Compta
else // Si no està premut
ComptaB = 0; // Posa el comptador zero
_delay(1000); // Retard de 1000 cicles
} while (ComptaB < 5); // Es repeteix fins que hem comptat 5 cops
}
if (Polsad == 2) { // Si s'ha premut el polsador 2
ComptaB = 0;
min++;
s=0;
if(min==60){
min=0;
}
while(Polsador() == 2) // Esperem a que el polsador es deixi anar
; // No fem res
do { // Bucle per comptar quants cops detectem el polsador premut
if (Polsad == 2) // Si el polsador està premut
ComptaB++; // Incrementa Compta
else // Si no està premut
ComptaB = 0; // Posa el comptador zero
_delay(1000); // Retard de 1000 cicles
} while (ComptaB < 5); // Es repeteix fins que hem comptat 5 cops
}
if (Polsad == 3) { // Si s'ha premut el polsador 3
ComptaB = 0;
d[1]++;
OperacioCAL();
diaSetmana = (diaSetmana + 1)%7;
while(Polsador() == 3) // Esperem a que el polsador es deixi anar
; // No fem res
do { // Bucle per comptar quants cops detectem el polsador premut
if (Polsad == 3) // Si el polsador està premut
ComptaB++; // Incrementa Compta
else // Si no està premut
ComptaB = 0; // Posa el comptador zero
_delay(1000); // Retard de 1000 cicles
} while (ComptaB < 5); // Es repeteix fins que hem comptat 5 cops
}
if (Polsad == 4) { // Si s'ha premut el polsador 4
for (i=0;i<8;i++){
d[i]=dIni[i];
}
}
if (Polsad == 5) { // Si s'ha premut el polsador 5
d[0]=0; // La data torna als valors de fábrica (01/01/2025)
d[1]=1;
d[2]=0;
d[3]=1;
d[4]=2;
d[5]=0;
d[6]=2;
d[7]=5;
}
Cursor(1,1);
EnviaL(h/10+'0'); // Enviem la hora i data actuals
EnviaL(h%10+'0');
EnviaL(':');
EnviaL(min/10+'0');
EnviaL(min%10+'0');
EnviaL(' ');
EnviaL(d[0]+'0');
EnviaL(d[1]+'0');
EnviaL('/');
EnviaL(d[2]+'0');
EnviaL(d[3]+'0');
EnviaL('/');
EnviaL(d[4]+'0');
EnviaL(d[5]+'0');
EnviaL(d[6]+'0');
EnviaL(d[7]+'0');
if (s==60)
s=0;
if (PolsadorS==0) { // Comprova l'estat del polsador per veure si s'ha canviat de menu
__delay_ms(250); // Retard de 250 ms per evitar canvis de menu extres
Menu = 4; // Canvi de menu
}
} while (Menu==3);
}
if (Menu==4) {
PORTC = 0b00001000; // Activem el LED 3 com a indicació visual del menu on estem
Esborra(); // Esborra la pantalla i posa el cursor a l'inici
do { // Bucle que s'executa mentre estem al menu 4
Cursor(1,1);
EnviaL(h/10+'0');
EnviaL(h%10+'0');
EnviaL(' ');
EnviaL('H');
Cursor(2,1);
EnviaL(min/10+'0');
EnviaL(min%10+'0');
EnviaL(' ');
EnviaL('M');
EnviaL('i');
EnviaL('n');
for (j=0; j<8; j++) {
if (j<4)
fig1[0][j] = numLed[h/10][j];
else
fig1[0][j] = (numLed[min%10][j-4])>>4;
}
for (j=0; j<8; j++) {
if (j<4)
fig1[1][j] = (numLed[h%10][j])>>4;
else
fig1[1][j] = (numLed[min%10][j-4])>>4;
}
for (j=4; j<8; j++) {
fig1[2][j] = numLed[min/10][j-4];
}
for (unsigned char k = 0; k < 8; k++){
Sortida[1] = k+1; // Filera
Sortida[3] = k+1;
Sortida[5] = k+1;
Sortida[0] = fig1[0][k]; // Vermells
Sortida[2] = fig1[1][k]; // Verds
Sortida[4] = fig1[2][k]; // Blaus
Envia3max(); // Ho envia al MAX7221
__delay_ms(1);
}
OperacioT();
Alarma();
if (PolsadorS==0) { // Comprova l'estat del polsador per veure si s'ha canviat de menu
__delay_ms(250); // Retard de 250 ms per evitar canvis de menu extres
Menu = 1; // Canvi de menu
}
} while (Menu==4);
}
}
}
void __interrupt() temporit(void){
if (INTCONbits.T0IF) { // Comprovem que hi ha interrupció per Timer 0
TMR0 = 100; // Preselecció de Timer0
if (FiTimer0){ // Comprovem que hi ha interrupció per Timer 0
ComptaT++; // Incrementa Compta
if (ComptaT == 120) { // Si ha acabat vint vegades
ComptaT = 0; // Reinicialitza Compta
s++;
}
FiTimer0 = 0; // Tornem a posar el bit a zero
TMR0 = Analogica(); // Cridem a la funció de lectura del conversor i
// copiem el resultat llegit com a precàrrega del Timer
}
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
Sorti[0] = 0x00; // Vermell
Sorti[2] = 0x00; // Verd
Sorti[4] = 0x00; // Blau
if (Actiu == 1) { // Si és vermell
Sorti[0] = 0x01; // Vermell activat
}
if (Actiu == 2) { // Si és verd
Sorti[2] = 0x01; // Verd activat
}
if (Actiu == 3) { // Si és blau
Sorti[4] = 0x01; // Blau activat
}
Sorti[1] = 0x0C; // Shutdown mode
Sorti[3] = 0x0C; // Shutdown mode
Sorti[5] = 0x0C; // Shutdown mode
Envia_max(); // Ho envia al MAX7221
}
}
unsigned char Analogica (void){ // Funció de lectura del conversor
ADCON0bits.GO_DONE = 1; // Posa en marxa el conversor
while (ADCON0bits.GO_DONE == 1) // Mentre no acabi
; // ens esperem
return ADRESH; // Retornem el resultat llegit
}
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; // Desactiva les interrupcions momentàniament
RCSTAbits.SPEN = 1; // Activa comunicació sèrie
TXSTAbits.TXEN = 1; // Activa comunicació
TXREG = Caracter; // Agafa el caràcter i l'envia
__delay_ms(1); // Donem temps
while (PIR1bits.TXIF == 0) // Esperem 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 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 Envia3max(void) { // Envia un joc de valors als tres MAX7221
asm("bcf INTCON,5"); // Desactiva les interrupcions momentàniament
asm("banksel _Port");
asm("bcf (_Port&7fh),5"); // S'assegura que Clock està desactivat
asm("bcf (_Port&7fh),6"); // S'assegura que Latch està desactivat
asm("movf (_Port&7fh),w"); // Agafa el valor de Port
asm("banksel PORTB");
asm("movwf PORTB"); // I el posa al port B
asm("banksel _Comptar");
asm("movlw 48"); // Número de bits a enviar
asm("movwf (_Comptar&7fh)"); // Variable per comptar els bits
asm("Bucles:");
asm("banksel _Port");
asm("bcf (_Port&7fh),4"); // Desactiva Data. Si toca activar-ho, ja ho farem
asm("banksel _Sorti");
asm("rlf (_Sortida&7fh),f"); // Fa sortir el bit de més a l'esquerra cap a C
asm("rlf ((_Sortida+1)&7fh),f"); // i roda els altres a l'esquerra
asm("rlf ((_Sortida+2)&7fh),f");
asm("rlf ((_Sortida+3)&7fh),f");
asm("rlf ((_Sortida+4)&7fh),f");
asm("rlf ((_Sortida+5)&7fh),f");
asm("banksel _Port");
asm("btfsc STATUS,0"); // Mira si el bit de l'esquerra era un 1
asm("bsf (_Port&7fh),4"); // Si era 1, activa Data
asm("movf (_Port&7fh),w"); // Agafa el valor de Port. El valor que ha canviat és Data
asm("banksel PORTB");
asm("movwf PORTB"); // I el posa al port B
asm("banksel _Port");
asm("bsf (_Port&7fh),5"); // Activa Clock, forçant a llegir el bit
asm("movf (_Port&7fh),w"); // Agafa el valor de Port. El valor que ha canviat és Clock
asm("banksel PORTB");
asm("movwf PORTB"); // I el posa al port B
asm("banksel _Port");
asm("bcf (_Port&7fh),5"); // Desactiva Clock
asm("movf (_Port&7fh),w"); // Agafa el valor de Port. El valor que ha canviat és Clock
asm("banksel PORTB");
asm("movwf PORTB"); // I el posa al port B
asm("banksel _Comptar");
asm("decfsz (_Comptar&7fh),f"); // Decrementa Compta
asm("goto (Bucles&7ffh)"); // Si Compta no és zero, repeteix el bucle
asm("banksel _Port");
asm("bsf (_Port&7fh),6"); // Torna a activar Latch
// Els valors es copiaran a la sortida del registre
asm("movf (_Port&7fh),w"); // Agafa el valor de Port. El valor que ha canviat és Latch
asm("banksel PORTB");
asm("movwf PORTB"); // I el posa al port B
asm("bsf INTCON,5"); // Reactiva les interrupcions a l'acabar
}
void Envia_max(void) { // Envia un joc de valors als tres MAX7221
asm("banksel _Port");
asm("bcf (_Port&7fh),5"); // S'assegura que Clock està desactivat
asm("bcf (_Port&7fh),6"); // S'assegura que Latch està desactivat
asm("movf (_Port&7fh),w"); // Agafa el valor de Port
asm("banksel PORTB");
asm("movwf PORTB"); // I el posa al port B
asm("banksel _Compta");
asm("movlw 48"); // Número de bits a enviar
asm("movwf (_Compta&7fh)"); // Variable per comptar els bits
asm("Bucle:");
asm("banksel _Port");
asm("bcf (_Port&7fh),4"); // Desactiva Data. Si toca activar-ho, ja ho farem
asm("banksel _Sorti");
asm("rlf (_Sorti&7fh),f"); // Fa sortir el bit de més a l'esquerra cap a C
asm("rlf ((_Sorti+1)&7fh),f"); // i roda els altres a l'esquerra
asm("rlf ((_Sorti+2)&7fh),f");
asm("rlf ((_Sorti+3)&7fh),f");
asm("rlf ((_Sorti+4)&7fh),f");
asm("rlf ((_Sorti+5)&7fh),f");
asm("banksel _Port");
asm("btfsc STATUS,0"); // Mira si el bit de l'esquerra era un 1
asm("bsf (_Port&7fh),4"); // Si era 1, activa Data
asm("movf (_Port&7fh),w"); // Agafa el valor de Port. El valor que ha canviat és Data
asm("banksel PORTB");
asm("movwf PORTB"); // I el posa al port B
asm("banksel _Port");
asm("bsf (_Port&7fh),5"); // Activa Clock, forçant a llegir el bit
asm("movf (_Port&7fh),w"); // Agafa el valor de Port. El valor que ha canviat és Clock
asm("banksel PORTB");
asm("movwf PORTB"); // I el posa al port B
asm("banksel _Port");
asm("bcf (_Port&7fh),5"); // Desactiva Clock
asm("movf (_Port&7fh),w"); // Agafa el valor de Port. El valor que ha canviat és Clock
asm("banksel PORTB");
asm("movwf PORTB"); // I el posa al port B
asm("banksel _Compta");
asm("decfsz (_Compta&7fh),f"); // Decrementa Compta
asm("goto (Bucle&7ffh)"); // Si Compta no és zero, repeteix el bucle
asm("banksel _Port");
asm("bsf (_Port&7fh),6"); // Torna a activar Latch
// Els valors es copiaran a la sortida del registre
asm("movf (_Port&7fh),w"); // Agafa el valor de Port. El valor que ha canviat és Latch
asm("banksel PORTB");
asm("movwf PORTB"); // I el posa al port B
}
void Ini3max(void) { // Inicialitza els tres MAX7221
Sortida[0] = 0x00; // Desactivat
Sortida[1] = 0x0C; // Shutdown mode
Sortida[2] = 0x00;
Sortida[3] = 0x0C;
Sortida[4] = 0x00;
Sortida[5] = 0x0C;
Envia3max(); // Els envia
Sortida[0] = 0x00; // No decode
Sortida[1] = 0x09; // Decode mode
Sortida[2] = 0x00;
Sortida[3] = 0x09;
Sortida[4] = 0x00;
Sortida[5] = 0x09;
Envia3max(); // Els envia
Sortida[0] = 0x07; // Vuit fileres
Sortida[1] = 0x0B; // Scan limit
Sortida[2] = 0x07;
Sortida[3] = 0x0B;
Sortida[4] = 0x07;
Sortida[5] = 0x0B;
Envia3max(); // Els envia
}
void Apaga(void) { // Apaga tots els LED
for (unsigned char j = 1; j <= 8; j++){ // Hem d'enviar 8 fileres
Sortida[1] = j; // Filera
Sortida[3] = j;
Sortida[5] = j;
Sortida[0] = 0x00; // Vermells
Sortida[2] = 0x00; // Verds
Sortida[4] = 0x00; // Blaus
Envia3max(); // Els envia
}
}
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 OperacioT(void) {
if(s==60) {
s=0;
min++;
}
if(min==60) {
min=0;
h++;
}
if(h==24) {
diaSetmana = (diaSetmana + 1)%7;
d[1]++; // incrementem el dia
OperacioCAL();
h=0;
}
}
void OperacioCAL(void) {
if (d[1]==10) { // Canvi decenes dia
d[1]=0;
d[0]++;
}
if (d[2]==0) { // mesos 1-9
if (d[3]==1) { // Gener
if (d[0]==3 && d[1]==2) { // Canvi a Febrer
d[0]=0;
d[1]=1;
d[3]=2;
}
}
if (d[3]==2) { // Febrer
if (d[0]==2 && d[1]==9) { // Canvi a Març
d[0]=0;
d[1]=1;
d[3]=3;
}
}
if (d[3]==3) { // Març
if (d[0]==3 && d[1]==2) { // Canvi a Abril
d[0]=0;
d[1]=1;
d[3]=4;
}
}
if (d[3]==4) { // Abril
if (d[0]==3 && d[1]==1) { // Canvi a Maig
d[0]=0;
d[1]=1;
d[3]=5;
}
}
if (d[3]==5) { // Maig
if (d[0]==3 && d[1]==2) { // Canvi a Juny
d[0]=0;
d[1]=1;
d[3]=6;
}
}
if (d[3]==6) { // Juny
if (d[0]==3 && d[1]==1) { // Canvi a Juliol
d[0]=0;
d[1]=1;
d[3]=7;
}
}
if (d[3]==7) { // Juliol
if (d[0]==3 && d[1]==2) { // Canvi a Agost
d[0]=0;
d[1]=1;
d[3]=8;
}
}
if (d[3]==8) { // Agost
if (d[0]==3 && d[1]==2) { // Canvi a Setembre
d[0]=0;
d[1]=1;
d[3]=9;
}
}
if (d[3]==9) { // Setembre
if (d[0]==3 && d[1]==1) { // Canvi a Octubre
d[0]=0;
d[1]=1;
d[2]=1;
d[3]=0;
}
}
} else { // mesos 10-12
if (d[3]==0) { // Octubre
if (d[0]==3 && d[1]==2) { // Canvi a Novembre
d[0]=0;
d[1]=1;
d[3]=1;
}
}
if (d[3]==1) { // Novembre
if (d[0]==3 && d[1]==1) { // Canvi a Desembre
d[0]=0;
d[1]=1;
d[3]=2;
}
}
if (d[3]==2) { // Desembre
if (d[0]==3 && d[1]==2) { // Canvi a Gener
d[0]=0;
d[1]=1;
d[2]=0;
d[3]=1;
d[7]++;
if (d[7]==10) { // Canvi decenes any
d[7]=0;
d[6]++;
}
if (d[6]==10) { // Canvi centenes any
d[6]=0;
d[5]++;
}
if (d[5]==10) { // Canvi milers any
d[5]=0;
d[4]++;
}
}
}
}
}
void Alarma(void) {
if(alarmaH==h && alarmaM==min && s==0){
if(aSet==1){
for (l=1; l<8; l++) {
TocaNota(238, 119, 2);
}
}
if(aSet==2){
for (l=1; l<8; l++) {
TocaNota(189, 95, 0);
}
}
}
}

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