En aquest cas està previst que juguin dos jugadors i el sistema guarda la puntuació de cada un. En el moment de començar tenim quatre opcions segons el botó que es premi. El cinquè polsador activa i desactiva el so. El polsador de la part superior ens torna, en qualsevol moment, al menú principal.
| Polsador | Jugador | Correcció |
| 1 | 1 | Manual |
| 2 | 2 | Manual |
| 3 | 1 | Automàtica |
| 4 | 2 | Automàtica |
| 5 | Activar o desactivar so | |
| 0 | Torna al menú inicial | |
La matriu de LED es fa servir de manera que les quatre columnes de l'esquerra mostren les combinacions de colors i les quatre de la dreta mostren la correcció de la tirada corresponent. El jugador disposa de vuit intents per intentar encertar la combinació. Durant la partida, els polsadors tenen les següents finalitats:
| Activitat | Polsador | Funció |
| Tirada | 1 | Vermell |
| 2 | Groc | |
| 3 | Verd | |
| 4 | Cian | |
| 5 | Magenta | |
| Correcció | 1 | Apagat (el color no és a la sèrie) |
| 2 | Blanc (el color no és a la posició correcta) | |
| 3 | Blau (el color és a la posició correcta) |
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 #include <stdio.h> // Per als nombres aleatoris #include <stdlib.h> // Per a les variables binàries #include <math.h> #define _XTAL_FREQ 4000000 // La freqüència del rellotge és 4 MHz #define Pols0 RA3 // Li assigna un nom a l'adreça del polsador superior
char Sortida[6]; // Valors a enviar al MAX7221 (48 bits)
char Actiu; // Variable que diu quin color està actiu
// Actiu = 0 Apagat
// Actiu = 1 Vermell
// Actiu = 2 Verd
// Actiu = 3 Blau
char Polsad; // Polsador que s'ha premut
unsigned char tanca,col,fila,mode,tinicial,bi,gi,ri, music,xtra; // iniciem les variables generals
unsigned char blue, green, red, bc, rc, gc,d1,d2,u1,u2;
char nom1[14] = {'J', 'U', 'G','A','D','O','R',' ','1',' ',':',' ','0','0'};
char nom2[14] = {'J', 'U', 'G','A','D','O','R',' ','2',' ',':',' ','0','0'};
void Envia3max(char Val[6]); // Envia un joc de valors als tres MAX7221 desactivant interrupcions void Envia_max(char Valor[6]); // Envia un joc de valors als tres MAX7221 void Ini3max(void); // Inicialitza els tres MAX7221 void Apaga(void); // Apaga tots els LED 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 TocaNota(char ValPR2, char ValCCPR1L, char ValDC1B, char v); // Funció que serveix per produir un so amb el brunzidor char Polsador(void); // Funció de lectura dels polsadors char Mode(void); // Funció que conté el joc en sí void Final(void); // Funció que mostra el final de la partida char Decompose(char, char); // Funció que diu si la variable passada a binaria tindria un 1 // en la posició indicada void Auto(char extra); // Funció que corregeix la tirada char Compare(char v1[3], char v2[3]); // Funció que compara dos vectors de tres posicions
void main (void) {
OPTION_REG = 0b10000101; // Configuració de Timer0
// Com a temporitzador basat en rellotge
// 101 - Factor d'escala de 64
// I resistències de pull-up desactivades (valor per defecte)
TRISC = 0b00100000; // 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
ADCON1 = 0b00010000; // Posa el conversor a 1/8 de la freqüència
ADCON0 = 0b00001001; // Activa el conversor A/D connectat a AN2
Ini3max(); // Inicialitza els tres MAX7221
Actiu = 1; // Activa el color vermell
TMR0 = 139; // Presselecció de 139, que són 117 iteracions
// Correspon a una interrupció cada 7,5 ms
INTCON = 0b10100000; // Activem GIE i T0IE
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ó
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
__delay_ms(200);
Apaga(); // Apaga tots els LED
// Donem valors inicials a les variables generals
col=1; // Variable que representa les columnes de la matriu
fila=1; // Variable que representa les files de la matriu
red=0; // Variable que controla el color vermell
green=0; // Variable que controla el color verd
blue=0; // Variable que controla el color blau
tinicial=0; // Variable que diu si existeix una tirada inicial
bi=0; // Variable del color blau de la tirada inicial
gi=0; // Variable del color verd de la tirada inicial
ri=0; // Variable del color vermell de la tirada inicial
bc=0; // Variable que conté el blau de les primeres quatre columnes d'una fila
gc=0; // Variable que conté el verd de les primeres quatre columnes d'una fila
rc=0; // Variable que conté el vermell de les primeres quatre columnes d'una fila
tanca=0; // Variable que serveix per tancar bucles per acabar la partida
music=0; // Variable que controla la música
d1=0; // Variable que conté les desenes de la puntuació del jugador 1
d2=0; // Variable que conté les desenes de la puntuació del jugador 2
u1=0; // Variable que conté les unitats de la puntuació del jugador 1
u2=0; // Variable que conté les unitats de la puntuació del jugador 2
xtra=0; // Variable que emmagatzema la puntuació extra
TocaNota(189, 95, 0,0); // Valor que correspon aproximadament a mi3
TocaNota(158, 79, 2,0); // Valor que correspon aproximadament a sol3
TocaNota(94, 33, 1,0); // Valor que correspon aproximadament a mi4
TocaNota(118, 41, 3,0); // Valor que correspon aproximadament a do4
TocaNota(105, 37, 1,0); // Valor que correspon aproximadament a re4
TocaNota(78, 26, 1,0); // Valor que correspon aproximadament a sol4
Apaga();
TRISC = 0b11110111; // Posa el bit 3 del port C com a sortida
PORTC = 0b000001000; // Activa el bit 3 del port C i, per tant, encén el LED
TRISC = 0b00100000; // Tot el port C és de sortida
while (1) {
Apaga();
Polsad = Polsador();
Esborra(); // Esborra la pantalla i posa el cursor a l'inici
for (int k = 0; k < 14; k++){
EnviaL(nom1[k]);
}
Cursor(2, 1); // Posició
for (int k = 0; k < 14; k++){
EnviaL(nom2[k]);
}
if (Polsad == 1) { // Mode de joc de correcció manual on adivina el jugador 1
mode=0;
__delay_ms(100);
u1=u1+Mode();
tanca=0;
fila=1;
if (u1>=10){
d1=d1+1;
u1=u1-10;
}
}
if (Polsad == 2) { // Mode de joc de correcció manual on adivina el jugador 2
mode=0;
__delay_ms(100);
u2=u2+Mode();
tanca=0;
fila=1;
if (u2>=10){
d2=d2+1;
u2=u2-10;
}
}
if (Polsad == 3) { // Mode de joc de correcció automàtica on adivina el jugador 1
mode=1;
__delay_ms(100);
u1=u1+Mode();
tanca=0;
fila=1;
if (u1>=10){
d1=d1+1;
u1=u1-10;
}
}
if (Polsad == 4) { // Mode de joc de correcció automàtica on adivina el jugador 2
mode=1;
__delay_ms(100);
u2=u2+Mode();
tanca=0;
fila=1;
if (u2>=10){
d2=d2+1;
u2=u2-10;
}
}
if (Polsad==5) {
if (music==0){ // Desactiva el so i apaga el primer LED superior
music=-1;
TRISC = 0b11110111; // Posa els bits 0 i 2 del port C com a sortida
PORTC = 0b00000000; // Desctiva el bit 3 del port C i, per tant, encén el LED
TRISC = 0b00100000; // Tot el port C és de sortida
} else { // Activa el so i encen el primer LED superior
music=0;
TRISC = 0b11110111; // Posa els bits 0 i 2 del port C com a sortida
PORTC = 0b00001000; // Activa el bit 3 del port C i, per tant, encén el LED
TRISC = 0b00100000; // Tot el port C és de sortida
}
}
nom1[12]='0'+d1; // Actualitzem la variable de les desenes de la puntuació del jugador 1
nom1[13]='0'+u1; // Actualitzem la variable de les unitats de la puntuació del jugador 1
nom2[12]='0'+d2; // Actualitzem la variable de les desenes de la puntuació del jugador 2
nom2[13]='0'+u2; // Actualitzem la variable de les unitats de la puntuació del jugador 2
}
}
void __interrupt() temporit(void) {
INTCONbits.GIE = 0; // Desactiva les interrupcions momentàniament
if (INTCONbits.T0IF) { // Comprovem que hi ha interrupció per Timer 0
TMR0 = 139; // Preselecció de Timer0
INTCONbits.T0IF = 0; // Desactiva el bit que indica interrupció pel Timer0
if (Actiu != 0) { // Si la matriu no està apagada
Actiu--; // Passem a activar un altre color
if (Actiu == 0) { // Si hem arribat a zero
Actiu = 3; // Torna a posar el 3
}
}
// D'entrada els desactivem els tres
Sortida[0] = 0x00; // Vermell
Sortida[2] = 0x00; // Verd
Sortida[4] = 0x00; // Blau
if (Actiu == 1) { // Si és vermell
Sortida[0] = 0x01; // Vermell activat
}
if (Actiu == 2) { // Si és verd
Sortida[2] = 0x01; // Verd activat
}
if (Actiu == 3) { // Si és blau
Sortida[4] = 0x01; // Blau activat
}
Sortida[1] = 0x0C; // Shutdown mode
Sortida[3] = 0x0C; // Shutdown mode
Sortida[5] = 0x0C; // Shutdown mode
Envia_max(Sortida); // Ho envia al MAX7221
}
INTCONbits.GIE = 1; // Reactiva les interrupcions a l'acabar
}
void Auto(char extra) {
unsigned char ba=0;
unsigned char ga=0;
unsigned char ra=0;
// Descomposem la tirada inicial per posicions
char Ti1[3]={Decompose(bi,1)>>7, Decompose(gi,1)>>7, Decompose(ri,1)>>7};
char Ti2[3]={Decompose(bi,2)>>6, Decompose(gi,2)>>6,Decompose(ri,2)>>6};
char Ti3[3]={Decompose(bi,3)>>5,Decompose(gi,3)>>5,Decompose(ri,3)>>5};
char Ti4[3]={Decompose(bi,4)>>4,Decompose(gi,4)>>4,Decompose(ri,4)>>4};
// Descomposem la tirada actual per posicions
char T1[3]={Decompose(blue,1)>>7,Decompose(green,1)>>7,Decompose(red,1)>>7};
char T2[3]={Decompose(blue,2)>>6,Decompose(green,2)>>6,Decompose(red,2)>>6};
char T3[3]={Decompose(blue,3)>>5,Decompose(green,3)>>5,Decompose(red,3)>>5};
char T4[3]={Decompose(blue,4)>>4,Decompose(green,4)>>4,Decompose(red,4)>>4};
// Comparem les posicions i establim les correccions
if (Compare(T1,Ti1)){ // Posició 1 de la tirada inicial igual a la posició 1 de la tirada actual
ba=ba+8; // Blau en la correcció
} else {
if(Compare(T1,Ti2) || Compare(T1,Ti3) || Compare(T1,Ti4)){
// Posició actual 1 del mateix color que alguna de
// les posicions de la tirada incial exceptuant la posició 1
// Blanc en la correcció
ba=ba+8;
ga=ga+8;
ra=ra+8;
xtra=xtra+1; // Sumem 1 a la putuació extra
} else { // LED apagat en la correcció
xtra=xtra+2; // Sumem 2 a la puntuació extra
}
}
if (Compare(T2,Ti2)){
ba=ba+4;
} else {
if(Compare(T2,Ti3) || Compare(T2,Ti1) || Compare(T2,Ti4)){
ba=ba+4;
ga=ga+4;
ra=ra+4;
xtra=xtra+1;
} else {
xtra=xtra+2;
}
}
if (Compare(T3,Ti3)){
ba=ba+2;
} else {
if(Compare(T3,Ti2) || Compare(T3,Ti1) || Compare(T3,Ti4)){
ba=ba+2;
ga=ga+2;
ra=ra+2;
xtra=xtra+1;
} else {
xtra=xtra+2;
}
}
if (Compare(T4,Ti4)){
ba=ba+1;
} else {
if(Compare(T4,Ti2) || Compare(T4,Ti1) || Compare(T4,Ti3)){
ba=ba+1;
ga=ga+1;
ra=ra+1;
xtra=xtra+1;
} else {
xtra=xtra+2;
}
}
if (extra==0) { // Quan volem que surti la correcció i no ens importa l'extra
xtra=0;
blue=blue+ba;
red=red+ra;
green=green+ga;
Sortida[1] = fila;
Sortida[3] = fila;
Sortida[5] = fila;
Sortida[0] = red; // Vermells
Sortida[2] = green; // Verds
Sortida[4] = blue; // Blaus
Envia3max(Sortida); // Ho envia al MAX7221
}
}
char Decompose(char convert, char len){
unsigned char bin=0;
if (len ==1 && (convert & 128)==128){ // Mira si el vuitè bit de convert és 1
bin=128;
}
if (len ==2 && (convert & 64)==64){ // Mira si el setè bit de convert és 1
bin=64;
}
if (len ==3 && (convert & 32)==32){
bin=32;
}
if (len ==4 && (convert & 16)==16){
bin=16;
}
if (len ==5 && (convert & 8)==8){
bin=8;
}
if (len ==6 && (convert & 4)==4){
bin=4;
}
if (len ==7 && (convert & 2)==2){
bin=2;
}
if (len ==8 && (convert & 1)==1){
bin=1;
}
return bin;
}
char Compare(char v1[3], char v2[3]) {
return (v1[0]==v2[0] && v1[1]==v2[1] && v1[2]==v2[2]); // Comparem dos vectors de tres posicions
}
char Mode(void) { // Joc en sí
Apaga();
blue=0; // Retornem les variables generals als valors inicials
green=0;
red=0;
col=0;
tinicial=0;
bi=0;
ri=0;
gi=0;
bc=0;
rc=0;
gc=0;
while (tanca==0) {
unsigned char Compta = 0; // Variable local per comptar
unsigned char var=0; // Variable que porta el valor del bit relacionat
// a la posició de la fila
Polsad = Polsador(); // Llegim els polsadors
if (col==1) {
var=128;
}
if (col==2) {
var=64;
}
if (col==3) {
var=32;
}
if (col==4) {
var=16;
}
if (col==5) {
if (tinicial==0) { // Si no existeix tirada inicial agafa la tirada actual com a
// aquesta i torna als valors inicials les variables
bi=blue;
gi=green;
ri=red;
var=0;
col=0;
red=0;
green=0;
blue=0;
Apaga();
tinicial=1; // Tenim tirada inicial
} else {
var=8;
if (mode==1){ // Si estem en el mode d'autocorregir completa la fila
// amb la correcció
Auto(0);
col=9;
}
}
}
if (col==6) {
var=4;
}
if (col==7) {
var=2;
}
if (col==8) {
var=1;
}
if (col==9) { // Hem acabat la fila de la matriu
bc=Decompose(blue,5)+Decompose(blue,6)+Decompose(blue,7)+Decompose(blue,8);
// Ens quedem amb les últimes quatre columnes de la tirada actual
rc=Decompose(red,5)+Decompose(red,6)+Decompose(red,7)+Decompose(red,8);
gc=Decompose(green,5)+Decompose(green,6)+Decompose(green,7)+Decompose(green,8);
if ((bc==15 && rc==0 && gc==0) || fila==8) {
// En cas que la correcció indiqui que s'ha encertat la combinació
// o s'hagi arribat al límit de tirades s'envia al final de la partida
__delay_ms(400);
Apaga();
Final();
__delay_ms(100);
tanca=1;
} else { // Mentre no haguem arribat al límit de tirades ni haguem acertat
// la combinació
// Tornem algunes variables generals a 0 i sumem 1 a la fila
var=0;
col=0;
red=0;
green=0;
blue=0;
fila++;
}
}
if (Pols0 == 0) { // Si s'apreta el botó superior es torna al menú
// principal sense actualitzar el marcador
fila=0;
tanca=1;
}
if (Polsad == 1) { // Si s'ha premut el polsador 1
if(col>=5){ // Si s'està corregint deixa el LED apagat i passa a la següent posició
;
} else { // Si s'està endevinant marca el color vermell
red=var+red;
}
Sortida[1] = fila; // Filera
Sortida[3] = fila;
Sortida[5] = fila;
Sortida[0] = red; // Vermells
Sortida[2] = green; // Verds
Sortida[4] = blue; // Blaus
Envia3max(Sortida);
} // Ho envia al MAX7221
if (Polsad == 2) { // Si s'ha premut el polsador 2
if(col>=5){ // Si s'està corregint encén el LED de color blanc
red=red+var;
green=green+var;
blue=blue+var;
}else { // Si s'està endevinant encén el LED de color groc
red=var+red;
green=var+green;
}
Sortida[1] = fila; // Filera
Sortida[3] = fila;
Sortida[5] = fila;
Sortida[0] = red; // Vermells
Sortida[2] = green; // Verds
Sortida[4] = blue; // Blaus
Envia3max(Sortida);
}
if (Polsad == 3) { // Si s'ha premut el polsador 3
if(col>=5){ // Si s'està corregint encén el LED de color blau
blue=blue+var;
}else { // Si s'està endevinant encén el LED de color verd
green=var+green;
}
Sortida[1] = fila; // Filera
Sortida[3] = fila;
Sortida[5] = fila;
Sortida[0] = red; // Vermells
Sortida[2] = green; // Verds
Sortida[4] = blue; // Blaus
Envia3max(Sortida);
}
if (Polsad == 4) { // Si s'ha premut el polsador 4
if(col>=5){ // Si s'està corregint no fa res
col=col-1;
} else { // Si s'està endevinant encén el LED de color cian
Sortida[1] = fila; // Filera
Sortida[3] = fila;
Sortida[5] = fila;
Sortida[0] = red; // Vermells
Sortida[2] = var+green; // Verds
Sortida[4] = var+blue; // Blaus
Envia3max(Sortida); // Ho envia al MAX7221
green=var+green;
blue=var+blue;
}
}
if (Polsad == 5) { // Si s'ha premut el polsador 5
if(col>=5){ // Si s'està corregint no fa res
col=col-1;
} else { // Si s'està endevinant encén el LED de color magenta
Sortida[1] = fila; // Filera
Sortida[3] = fila;
Sortida[5] = fila;
Sortida[0] = var+red; // Vermells
Sortida[2] = green; // Verds
Sortida[4] = var+blue; // Blaus
Envia3max(Sortida); // Ho envia al MAX7221
red=var+red;
blue=var+blue;
}
}
if (Polsad != 0){
while (Polsad == 0) // Esperem a que el polsador es deixi anar
; // No fem res
do { // Bucle per comptar quants cops detectem el polsador premut
if (Polsad != 0) // Si el polsador està premut
Compta++; // Incrementa Compta
else // Si no està premut
Compta = 0; // Posa el comptador zero
__delay_ms(100); // Retard de 1000 cicles
} while (Compta < 5); // Es repeteix fins que hem comptat 5 cops
}
if(Polsad!=0){ // Si es prem qualsevol polsador passem a la següent columna
col=col+1;
}
} // S'acaba el bucle
return fila; // Enviem la variable fila per a actualitzar la puntuació
}
void Final (void) {
unsigned char b2=0; // Variable local que emmagatzema el blau de les
// primeres quatre posicions de l'última tirada realitzada
unsigned char g2=0; // Variable local que emmagatzema el verd de les
// primeres quatre posicions de l'última tirada realitzada
unsigned char r2=0; // Variable local que emmagatzema el vermell de les
// primeres quatre posicions de l'última tirada realitzada
b2=blue-bc;
g2=green-gc;
r2=red-rc;
while (tanca==0) {
Polsad = Polsador(); // Llegim els polsadors
Sortida[1] = 1; // Filera 1
Sortida[3] = 1;
Sortida[5] = 1;
Sortida[0] = ri; // Vermells de la tirada original
Sortida[2] = gi; // Verds de la tirada original
Sortida[4] = bi; // Blaus de la tirada original
Envia3max(Sortida); // Ho envia al MAX7221
__delay_ms(100);
Sortida[1] = 2; // Filera 2
Sortida[3] = 2;
Sortida[5] = 2;
Sortida[0] = r2; // Vermells de l'última tirada realitzada
Sortida[2] = g2; // Verds de l'última tirada realitzada
Sortida[4] = b2; // Blaus de l'última tirada realitzada
Envia3max(Sortida); // Ho envia al MAX7221
__delay_ms(100);
if (music >= 0){ // Si la música està activada
if (bi==b2 && ri==r2 && gi==g2){ // Si s'ha encertat la combinació sona la
// música de victòria
while (music<=1) { // Inici del bucle de programa
TocaNota(238,119,2,0); // Valor que correspon aproximadament a DO3
TocaNota(178,89,2,0); // Valor que correspon aproximadament a FA3
TocaNota(158,79,2,0); // Valor que correspon aproximadament a SOL3
TocaNota(141,71,0,0); // Valor que correspon aproximadament a LA3
TocaNota(158,79,2,0); // Valor que correspon aproximadament a SOL3
__delay_ms(200); // Retard de 0,2 s
TocaNota(189,95,0,0); // Valor que correspon aproximadament a MI3
__delay_ms(200); // Retard de 0,2 s
music++;
}
if (music==2) {
TocaNota(189,95,0,1); // Valor que correspon aproximadament a MI3
TocaNota(178,89,2,0); // Valor que correspon aproximadament a FA3
TocaNota(189,95,0,0); // Valor que correspon aproximadament a MI3
TocaNota(238,119,2,0); // Valor que correspon aproximadament a DO3
TocaNota(238,119,2,1); // Valor que correspon aproximadament a DO3
__delay_ms(400); // Retard de 0,4 s
music++;
}
} else { // Si no s'ha encertat la combinació
if (music==0) {
TocaNota(88, 31, 1,1); // Valor que correspon aproximadament a FA4
TocaNota(118, 41, 3,1); // Valor que correspon aproximadament a DO4
TocaNota(141, 70, 0,1); // Valor que correspon aproximadament a LA3
TocaNota(178, 89, 2,2); // Valor que correspon aproximadament a FA3
music++;
}
}
}
if (Polsad != 0){ // Activant qualsevol pulsador
Auto(1); // Calculem la puntuació extra
fila=fila+xtra; // Afegim la puntuació extra a la normal
if (music>= 0){ // Si la música estava activada torna la variable a 0
music==0;
}
__delay_ms(200);
Apaga();
tanca=1; // Tanca el bucle de la funció Final i de la funció Mode
}
}
}
void Envia3max(char Val[6]) { // Envia un joc de valors als tres MAX7221
INTCONbits.GIE = 0; // Desactiva les interrupcions momentàniament
Envia_max(Val);
INTCONbits.GIE = 1; // Reactiva les interrupcions a l'acabar
}
void Envia_max(char Valor[6]) { // Envia un joc de valors als tres MAX7221
char Port = 0; // Variable on guardem l'estat del port B
char Temp; // Variable temporal
for (int j = 5; j >= 0; j--){ // Hem d'enviar 6 bytes
for (int k = 1; k < 9; k++){ // De 8 bits
Temp = Valor[j] & 0b10000000; // Agafa el bit de més a l'esquerra
// Temp només podrà valer 0 o 128
if (Temp == 0) { // Si val 0
Port = Port & 0b11101111; // Desactiva Data (bit 4)
} else { // Si val 128
Port = Port | 0b00010000; // Activa Data (bit 4)
}
Valor[j] = Valor[j] << 1; // Rodem els bits per situar el següent
PORTB = Port; // Ho posa al port B
Port = Port | 0b00100000; // Activa Clock (bit 5) i força lectura
PORTB = Port; // Ho posa al port B
Port = Port & 0b11011111; // Desactiva Clock (bit 5)
PORTB = Port; // Ho posa al port B
}
}
Port = Port | 0b01000000; // Activa Latch (bit 6) per copiar a les sortides
PORTB = Port; // Ho posa al port B
}
void Ini3max(void) { // Inicialitza els tres MAX7221
char Bytes[6]; // Els sis bytes que cal enviar
Bytes[0] = 0x00; // Desactivat
Bytes[1] = 0x0C; // Shutdown mode
Bytes[2] = 0x00;
Bytes[3] = 0x0C;
Bytes[4] = 0x00;
Bytes[5] = 0x0C;
Envia_max(Bytes); // Els envia
Bytes[0] = 0x00; // No decode
Bytes[1] = 0x09; // Decode mode
Bytes[2] = 0x00;
Bytes[3] = 0x09;
Bytes[4] = 0x00;
Bytes[5] = 0x09;
Envia_max(Bytes); // Els envia
Bytes[0] = 0x07; // Vuit fileres
Bytes[1] = 0x0B; // Scan limit
Bytes[2] = 0x07;
Bytes[3] = 0x0B;
Bytes[4] = 0x07;
Bytes[5] = 0x0B;
Envia_max(Bytes); // Els envia
}
void Apaga(void) { // Apaga tots els LED
char Bytes[6]; // Els sis bytes que cal enviar
for (int j = 1; j <= 8; j++){ // Hem d'enviar 8 fileres
Bytes[1] = j; // Filera
Bytes[3] = j;
Bytes[5] = j;
Bytes[0] = 0x00; // Vermells
Bytes[2] = 0x00; // Verds
Bytes[4] = 0x00; // Blaus
Envia3max(Bytes); // Els envia
}
}
void 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
}
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 TocaNota(char ValPR2, char ValCCPR1L, char ValDC1B, char v) {
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
if (v==0){
__delay_ms(100); // Retard de 0,2 s
TRISC = 0b00100000; // Posem RC5 (sortida del PWM) com a entrada
// O sigui, silenci
__delay_ms(100); // Retard de 0,2 s
}
if (v==1){
__delay_ms(150); // 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
}
if (v==2){
__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
}
}

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