Programació en C del PIC 16F690

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

Joc d'enfonsar vaixells electrònic

Programa del grup 1

En aquest cas hi ha un jugador que intenta enfonsar els vaixells que ha situat la màquina. La posició dels vaixells es determina aleatòriament per a cada partida. Hi ha set vaixells:

Mida Nombre de vaixells
4 caselles 1
3 caselles 1
2 caselles 2
1 casella 3

Els colors dels LED de la matriu representen:

Color Significat
Apagat Casella sobre la que no s'ha disparat
Blau Aigua
Groc Tocat
Vermell Enfonsat
Verd Posició del cursor

Els polsadors de la part inferior serveixen per moure el cursor i per disparar sobre la casella actual, segons el següent ordre:

Polsador Funció
1 Esquerra
2 Dreta
3 Amunt
4 Avall
5 Disparar

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
#include <stdlib.h>
#define _XTAL_FREQ 4000000 // La freqüència del rellotge és 4 MHz
#define cic_int 5 // Nombre de cicles per a la intermitència
#define setbit(var, bit) ((var) |= (1 << (bit)))
#define testbit(var, bit) ((var) & (1 <<(bit)))
char d=0;   // 0 és Vaixell vertical
char Port; // Gestió del port a la funció Envia_max
char Compta; // Comptador de bits a la funció Envia_max
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 Polsad; // Polsador que s'ha premut
char x = 0; // Coordenada X del cursor (0 a 7)
            // X = 0 és la columna de la dreta
char y = 0; // Coordenada Y del cursor (0 a 7)
char mirar = 1; // Espera que es deixi anar el polsador
char compt_int = 0; // Comptador de cicles per a la intermitència
char cur_on = 1; // Controla l'estat del cursor
unsigned short adressa; // Variable de 16 bits per a l'adreça
char Vaixells[7][4] = {{0,0,0,1},{0,0,0,1},{0,0,0,1},{0,0,0,2},
                       {0,0,0,2},{0,0,0,3},{0,0,0,4}}; // Posició dels vaixells
char Barquitos[8][8]={0};  // Matriu 8x8 que representa el mapa dels vaixells
                           // Cada posició és 0b00000000,
                           // Bit [0]: 1 si el color ences es VERMELL
                           // Bit [1]: 1 si el color ences es GROC
                           // Bit [2]: 1 si el color ences es BLAU
                           // Bit [3]: 1 si hi ha algun color ENCÈS
                           //          0 si no hi ha cap encès (no s'ha disparat)
                           // Bit [4]: 1 si la posició és AIGUA
                           // Bit [5]: 1 si la posicio és VAIXELL
                           // Bit [6]: 1 si la posició és VOLTANT DE VAIXELL
void Envia3max(char Valor[]);  // Envia un joc de valors als tres MAX7221
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
char Polsador(void);  // Funció de lectura dels polsadors
int figura2(int x, int y);  // Traducció als codis de colors
void TocaNota(char ValPR2, char ValCCPR1L, char ValDC1B);  // Funció per fer sonar el brunzidor
void EnviaL(char Caracter);  // Envia un caràcter a la pantall de text
void Esborra(void);  // Esborra la pantalla i posa el cursor a l'inici
void Creabarcos(void);
void Cursor(char Filera, char Columna);  // Posiciona el cursor de la pantalla de text
                                         // Filera d'1 a 2
                                         // Columna d'1 a 32
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 = 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
  ADCON1 = 0b00010000;  // Posa el conversor a 1/8 de la freqüència
  ADCON0 = 0b00001001;  // Activa el conversor A/D connectat a AN2
  CCP1CON = 0b00001100;  // Configura el PWM, bits P1M (bits 7-6) a 00 mode senzill
  PIR1bits.TMR2IF = 0;  // Desactiva el bit d'interrupció del Timer 2
  T2CON = 0b00000011;  // Configura el Timer 2
  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
  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
  while (1){ // Bucle infinit pel joc
    //----------- MENÚ PRINCIPAL -----------
    for (signed char j=7;j>=0;j--){ // Posem matriu tota de aigua
      for (signed char i=7;i>=0;i--){
        Barquitos[i][j]=16;
      }
    }    
    char fin=0;  // Cambiara a 1 quan s'acabi la partida
    char Tirs=40;  // Núm. de tirs permesos
    char contavaixells=0;  // Núm. de vaixelles enfonsats
    char a=0;
    Esborra();  // Esborra la pantalla i posa el cursor a l'inici
    Apaga();  // Apaga tots els LED
    EnviaL('T');
    EnviaL('R');
    EnviaL('I');
    EnviaL('A');
    Cursor(1,6);
    EnviaL('U');
    EnviaL('N');
    Cursor(1,9);
    EnviaL('N');
    EnviaL('I');
    EnviaL('V');
    EnviaL('E');
    EnviaL('L');
    EnviaL('L');
    while (a==0){ // Ens quedem esperant i llegint els polsadors fins que es prem algun
      Polsad=Polsador();
      if (Polsad==1){  // Si es prem algun...
        a=1;  // ... surt del bucle...
        Tirs=45;
      } else if (Polsad==2){
        a=1;
        Tirs=40;
      } else if (Polsad==3){
        a=1;
        Tirs=35;
      }
    }
    srand(TMR0);  // ... i crea la llavor de nombres aleatoris
    Esborra();  // Esborra la pantalla i posa el cursor a l'inici
    //----------- VAIXELLS ALEATORIS -----------
    char index=6;  // Per les posicions en Vaixells[][]
    for (unsigned char k = 4; k > 0; k--){ // k = llargaria del vaixell
      char f=0;
      char w=1;
      while (f<=4){
        char z=0;  // Bucle
        w++;
        f=k+w;
        while (z==0){ // Fins que el vaixell no es col.loqui correctament
          char p=0;  // Contador a 0
          char d=rand()%2;  // 0 Vertical, 1 horizontall (aleatori)
          char m=1-d;
          char xo=rand()%(9-k*d-1*(1-d));  // Columna aleatoria
          char yo=rand()%(9-k*(1-d)-1*d);  // Fila aleatoria
                                           // (xo,yo)
          for (signed char j = (k-1); j >= 0; j--){ // Per cada posició del vaixell
            if (Barquitos[yo+j*m][xo+j*d] != 16) // Si posicio vaixell incorrecta...
              p++;  // ...p deixa de ser 0
          }
          if (p==0){ // Si la posicio (xo, yo) escollida es corecte
            char arriba=1;     // -> Sera 0 quan estigui adalt
            char abajo=1;      // -> Sera 0 quan estigui abaix
            char izquierda=1;  // -> Sera 0 quan estigui a l'esquerra
            char derecha=1;    // -> Sera 0 quan estigui a la dreta
            if (xo==0)
              izquierda=0;
            if (xo==(8-k)*d+7*m)
              derecha=0;  // A l'hora de determinar els voltants del vaixell, necessitem diferenciar
            if (yo==0)  // els casos de les cantonades de la matriu de LED
              arriba=0;
            if (yo==(8-k)*m+7*d)
              abajo=0;
            char ad=arriba*derecha;
            char ai=arriba*izquierda;
            char abd=abajo*derecha;
            char abiz=abajo*izquierda;
            for (signed char j = (k-1); j >= 0; j--){
              // Canvien valor a 64 (Voltant de vaixell)...
              Barquitos[yo-1*arriba*d+j*derecha*m][xo+j*arriba*d+1*derecha*m]=64;
              // ...la part de dalt i...
              Barquitos[yo+1*abajo*d+j*izquierda*m][xo+j*abajo*d-1*izquierda*m]=64;
              // ... la part de baix. (Sempre ques es pugui)
            }
            // Ara hem de posar a 64 els casos de les cantonades i els laterals (sempre que sigui posible):
            Barquitos[yo-1*ad*d+k*abd*m][xo+k*ad*d+1*abd*m]=64;  // A dalt a la dreta
            Barquitos[yo-1*ai*d+k*abiz*m][xo-1*ai*d-1*abiz*m]=64;  // A dalt a l'esquerra
            Barquitos[yo+1*abiz*d-1*ad*m][xo-1*abiz*d+1*ad*m]=64;  // A baix a l'esquerra
            Barquitos[yo+1*abd*d-1*ai*m][xo+k*abd*d-1*ai*m]=64;  // A baix a la dreta
            Barquitos[yo-1*arriba*m][xo+k*derecha*d]=64;  // Dreta
            Barquitos[yo+k*abajo*m][xo-1*izquierda*d]=64;  // Esquerra
            for (signed char j = (k-1); j >= 0; j--){  // Cambiem el valor a 32 en les caselles
                                                       // que ocupa el vaixell
              Barquitos[yo+j*m][xo+j*d]=32;
            }
            z=1;  // Surtim del bucle perque la posicio (xo, yo) es correcte
            Vaixells[index][0]=xo;  // Apuntem la xo del vaixell
            Vaixells[index][1]=yo;  // Apuntem la yo del vaixell
            Vaixells[index][2]=d;  // Apuntem si es vertical o horitzontal
            index--;
          }
        }
      }
    }
    //----------- POLSADORS -----------
    while (fin==0) { // Mentre la partida no s'acabi
      // Mirem els polsadors
      // Un cop s'ha fet l'acció del polsador, no es tornarà
      // a fer fins que es detecti que s'han deixat anar
      Polsad = Polsador();  // Llegim els polsadors
      if (mirar == 1){
        if (Polsad == 1) { // Si s'ha premut el polsador 1 // ESQUERRA
          x = (x + 1) % 8;  // Incrementa x però la manté entre 0 i 7
          mirar = 0;
        }
        if (Polsad == 2) { // Si s'ha premut el polsador 2 // DRETA
          x = (x - 1) % 8;  // Disminuiex x però la manté entre 0 i 7 Dreta
          mirar = 0;
        }
        if (Polsad == 3) { // Si s'ha premut el polsador 3 // AMUNT
          y = (y - 1) % 8;  // Disminuiex x però la manté entre 0 i 7 Dreta
          mirar = 0;
        }
        if (Polsad == 4) { // Si s'ha premut el polsador 4 // AVALL
          y = (y + 1) % 8;  // Disminuiex x però la manté entre 0 i 7 Dreta
          mirar = 0;
        }
        if ((Polsad == 5) && (testbit(Barquitos[y][x], 3)==0)){ // Si s'ha premut el polsador 5 y LED apagat
                                                                // DISPARAR
          Tirs--;
          if ((testbit(Barquitos[y][x], 4)!=0) || (testbit(Barquitos[y][x], 6)!=0)){ // Si es AIGUA
            setbit(Barquitos[y][x],2);  // Pintem de BLAU ------> AIGUA
            setbit(Barquitos[y][x],3);  // Marca LED com a ences
            TocaNota(212, 106, 2);  // Valor que correspon aproximadament a re3
            TocaNota(238, 119, 2);  // Valor que correspon aproximadament a do3
          } else if (testbit(Barquitos[y][x],5)){ // Si es VAIXELL
            setbit(Barquitos[y][x], 1);  // Pinta de GROC ------> TOCAT (Després comprovem si es ENFONSAT)
            setbit(Barquitos[y][x],3);  // Marca LED com a ences
            TocaNota(238, 119, 2);  // Valor que correspon aproximadament a do3
          }
          for (signed char i = 0; i < 7; i++){ // Per cada vaixell (n'hi ha 7) Comprovem si esta enfonsat
            char longitud=Vaixells[i][3];
            char t=0;  // Contador de posicions tocades per vaixell
            d=Vaixells[i][2];  // d=0 Vertical, d=1 Horizontal
            a=1-d;
            for (signed char j = 0; j < longitud; j++){ // Per cada casella del vaixell
              if (testbit(Barquitos[Vaixells[i][1]+j*a][Vaixells[i][0]+j*d],1)!=0){
                t++;  // Suma un si posicio del vaixell tocada
              }
            }
            if (t==longitud){ // Si tot el vaixell tocat --> ENFONSAT
              for (signed char j = 0; j < longitud; j++){
                // Pintem de vermell totes les seves caselles
                setbit(Barquitos[Vaixells[i][1]+j*a][Vaixells[i][0]+j*d],0);
                // Posa a 0 el bit 1
                ((Barquitos[Vaixells[i][1]+j*a][Vaixells[i][0]+j*d]) &= ~(1 << (1)));
              }
              TocaNota(212, 106, 2);  // Valor que correspon aproximadament a re3
              TocaNota(189, 95, 0);  // Valor que correspon aproximadament a mi3
              contavaixells++;  // Hem enfonsat un vaixell més
            }
          }  
          mirar = 0;
        } // Final Polsador == 5 (Disparar)
        Esborra();  // Esborrem la pantalla de text (per tornar a escriure)
        EnviaL('T');  // i escrivim els Trets que queden per acabar
        EnviaL('R');
        EnviaL('E');
        EnviaL('T');
        EnviaL('S');
        Cursor(1,8);
        EnviaL((Tirs/10)+'0');  // Les decenes de Tirs
        EnviaL((Tirs%10)+'0');  // Les unitats de Tirs
      } else { // Mirar = 0
        if (Polsad == 0) // Si no s'ha premut cap polsador (o dos a la vegada)
        mirar = 1;
      }
      //----------- MOSTRAR FIGURA A LA MATRIU DE LED -----------
      for (signed char j = 0; j < 8; j++){ // Fileres
        char mascara;
        char col;
        char color=2;  // Color verd
        Sortida[0] = 0;  // Vermells
        Sortida[2] = 0;  // Verds
        Sortida[4] = 0;  // Blaus
        for (signed char k = 0; k < 8; k++){ // Caselles de la filera
          if ((y == j) && (x == k)){ // Si estem a la casella del cursor
            // El cursor es mostra en el color actual però si coincideix
            // amb el color de la casella el mostrem blanc
            // figura2[y][x]=0b00000001 --> vermell (R)
            // figura2[y][x]=0b00000010 --> verd    (G)
            // figura2[y][x]=0b00000110 --> blau    (B)
            // figura2[y][x]=0b00000011 --> groc    (RG)
            if (cur_on == 1){ // Si toca el cursor encès
              col = color;  // Color actual
            } else {
              col = figura2(x,y);  // Color de la posició actual
            }
          } else { // Si no hi estem, és una casella normal
            col = figura2(k,j);  // Color de la posició actual
          }
          // Posem els bits a la columna corresponent
          mascara = (col & 0b0000001);  // Serà 1 si hi ha vermell
          Sortida[0] = Sortida[0] | (mascara << k);
          mascara = (col & 0b0000010) >> 1;  // Serà 1 si hi ha verd
          Sortida[2] = Sortida[2] | (mascara << k);
          mascara = (col & 0b0000100) >> 2;  // Serà 1 si hi ha blau
          Sortida[4] = Sortida[4] | (mascara << k);
        }
        Sortida[1] = j+1;  // Filera
        Sortida[3] = j+1;
        Sortida[5] = j+1;
        Envia3max(Sortida);  // Ho envia al MAX7221
      }
      __delay_ms(1);
      compt_int++;
      if (compt_int == cic_int){ // Si toca intermitència
        compt_int = 0;
        cur_on = (cur_on + 1) % 2;  // Canvia el cursor
      }
      //----------- COMPROVAR FINAL DE PARTIDA -----------
      if (contavaixells==7){ // Has enfonsat tots els vaixells
        Cursor(2,1);  //
        EnviaL(':');  // VICTORIA
        EnviaL(')');
        __delay_ms(5000);
        fin=1;  // Torna a començar
      } else if (Tirs==0){ // T'has quedat sense tirs
        Cursor(2,1);  //
        EnviaL(':');  // DERROTA
        EnviaL('(');
        __delay_ms(5000);
        fin=1;  // Torna a començar
      }
    }
  }
}
void __interrupt() temporit(void){
  if (INTCONbits.T0IF) { // Comprovem que hi ha interrupció per Timer 0
    TMR0 = 100;  // 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
    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
  }
}
// 1. PANTALLA DE TEXT
void EnviaL(char Caracter) { // Escriure un caràcter
  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) { // Esborra text
  EnviaL(254);  // Caràcter de control
  EnviaL(1);  // Esborra la pantalla i posa el cursor a l'inici
}
void Cursor(char Filera, char Columna) { // Cursor del text
  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
}
// 2. BRUNZIDOR
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(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
}
// 3. MATRIU DE LED
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;
  Envia3max(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;
  Envia3max(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;
  Envia3max(Bytes);  // Els envia
}
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("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("movwf PORTB");  // I el posa al port B
  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("movwf PORTB");  // I el posa al port B
  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("movwf PORTB");  // I el posa al port B
  asm("banksel _Compta");
  asm("decfsz (_Compta&7fh),f");  // Decrementa Compta
  asm("goto Bucle");  // Si Compta no és zero, repeteix el bucle
  asm("banksel (_Port&7fh)");
  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("movwf PORTB");  // I el posa al port B
}
void Apaga(void) { // Apaga tots els LED
  char Bytes[6];  // Els sis bytes que cal enviar
  for (unsigned char 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 Envia3max(char Valor[]) { // Envia un joc de valors als tres MAX7221
  INTCONbits.T0IE = 0;  // Desactiva les interrupcions momentàniament
  char Port = 0;  // Variable on guardem l'estat del port B
  char Temp;  // Variable temporal
  for (signed char j = 5; j >= 0; j--){ // Hem d'enviar 6 bytes
    for (signed char 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
  INTCONbits.T0IE = 1;  // Reactiva les interrupcions a l'acabar
}
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;
}
// 4. PINTAR VAIXELLS  
int figura2(int x, int y){
  if (testbit(Barquitos[y][x],0)!=0){
    return 0b00000001;  // Retorna color VERMELL
  } else if (testbit(Barquitos[y][x],1)!=0){
    return 0b00000011;  // Retorna color GROC
  } else if (testbit(Barquitos[y][x],2)!=0){
    return 0b00000110;  // Retorna color BLAU
  } else
    return 0b00000000;  // Retorn apagat
}

 

 

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