En aquest projecte volem fer un joc del Mastermind. Per això disposarem de quatre LED tricolor per indicar les combinacions de color i quatre LED monocolor per indicar els encerts. Aquests LED els controlarem amb uns registres de desplaçament. També tindrem cinc polsadors connectats a una entrada analògica i un brunzidor piezoelèctric que ens permetrà, si ho desitgem, afegir una melodia al nostre joc. L'esquema de connexionat dels elements és el següent:

Els LED tricolor no només ens permeten obtenir els tres colors que incorporen (vermell, blau i verd) sinó alguns colors més. En teoria, combinant aquests tres colors (amb diferents intensitats) podem obtenir quasi infinits colors. Però nosaltres només podem tenir els colors activats o desactivats (sense variar-ne la intensitat) i, per tant, el nombre de possibles colors és reduït. En principi, disposem dels de la taula següent:
| Vermell (R) | Verd (G) | Blau (B) | Color |
| 1 | 0 | 0 | Vermell |
| 0 | 1 | 0 | Verd |
| 0 | 0 | 1 | Blau |
| 1 | 1 | 0 | Groc |
| 1 | 0 | 1 | Magenta |
| 0 | 1 | 1 | Cian |
| 1 | 1 | 1 | Blanc |
Alternant de forma ràpida dues o més combinacions podem fer alguns colors intermedis; per exemple:
| Vermell (R) | Verd (G) | Blau (B) | Color |
| 1 | 0 | 1 | Morat |
| 0 | 0 | 1 |
El programa de l'exemple NM permet provar el brunzidor. i el programa de l'exemple PA permet provar els polsadors.
En el programa que farem com a exemple, tindrem les variables Sortida i Sortida+1 que és on posarem els valors que volem enviar als registres i, per tant, als LED. La següent taula ens indica a quin LED correspon cada bit i alguns exemples, que són els que veurem al programa de mostra.
| Sortida2 | Sortida1 | Comentari | ||||||||||||||||
| B3 | G3 | R3 | B2 | G2 | R2 | B1 | G1 | R1 | B0 | G0 | R0 | M3 | M2 | M1 | M0 | |||
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | Monocrom encesos i tricolor apagats | ||
| 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | Monocrom apagats i tricolor vermells | ||
| 0 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | Monocrom apagats i tricolor verds | ||
| 1 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | Monocrom apagats i tricolor blaus | ||
El següent programa permet provar els registres de desplaçament:
#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
char Sortida1, Sortida2; // Valors a enviar al registre de desplaçament // Sortida2 correspon als bits del 8 al 15 i Sortida1 als bits del 0 al 7 // Sortida2 Sortida1 // B3 G3 V3 B2 G2 V2 B1 G1 R1 B0 G0 R0 M3 M2 M1 M0
// Definició de les funcions que farem servir void EnviaR16(char Valor1, char Valor2); // Envia 16 bits
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 = 0b00000001; // Configura AN0 com entrada analògica
ANSELH = 0; // Desactiva les altres entrades analògiques
PORTB = 0; // Inicialitza a 0 el port B
while (1) {
Sortida1 = 0b00001111; // Bits 0 a 3 a u (LED monocrom) i la resta a zero
Sortida2 = 0b00000000; // Bits 8 a 15 a zero
EnviaR16(Sortida1, Sortida2); // Ho envia al registre
_delay(1000000); // Retard per permetre la visualització
Sortida1 = 0b10010000; // LED multicolor a vermell
Sortida2 = 0b00100100; // La resta apagat
EnviaR16(Sortida1, Sortida2); // Ho envia al registre
_delay(1000000); // Retard per permetre la visualització
Sortida1 = 0b00100000; // LED multicolor a verd
Sortida2 = 0b01001001; // La resta apagat
EnviaR16(Sortida1, Sortida2); // Ho envia al registre
_delay(1000000); // Retard per permetre la visualització
Sortida1 = 0b01000000; // LED multicolor a blau
Sortida2 = 0b10010010; // La resta apagat
EnviaR16(Sortida1, Sortida2); // Ho envia al registre
_delay(1000000); // Retard per permetre la visualització
}
}
void EnviaR16(char Valor1, char Valor2) {
char Port = 0; // Variable on guardem l'estat del port B
char Temp; // Variable temporal
for (int k = 1; k < 9; k++){ // Primer enviem Valor2
Temp = Valor2 & 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)
}
Valor2 = Valor2 << 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
}
for (int k = 1; k < 9; k++){ // Després enviem Valor1
Temp = Valor1 & 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)
}
Valor1 = Valor1 << 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
}
A continuació posarem els programes realitzats pels grups. Estan tal com els han deixat i tenint present que no els va donar temps de simplificar-los o millorar-los. També pot ser que hi hagi errades ortogràfiques.

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