Programació en C del PIC 16F690

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

Sonòmetre digital

Programa del grup 2

En aquest cas, el programa contempla tres modes de funcionament predefinits (bar, passadís i biblioteca) i un de personalitzat que es poden triar amb els polsadors. En el mode personalitzat es pot definir el rang esperat de so i en els altres es poden configurar els llindars. A més, el polsador 0 deixa l'aparell en mode repòs (sembla que l'aparell estigui apagat) i permet sortir-ne; aquest mode és el que està definit per al moment d'engegar.

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 <math.h>
#define _XTAL_FREQ  4000000  // La freqüència del rellotge és 4 MHz
#define FiTimer1 PIR1bits.TMR1IF  // Li assigna un nom al bit que indica el final del Timer 1
#define Inicia  RA3  // Li assigna un nom a l'adreça del polsador
unsigned int Lectura[32];  // Per guardar els valors llegits
char pos = 0;  // Punter del vector
char n;  // Elegir si sona brunzidor
int brun;  // Variable per l?escala del brunzidor
char p = 0;  // Elegir si s'encén i s?apaga
char esc[8] = {20,18,16,14,12,10,8,6};  // Constant escala de so
char mod = 0;  // Mode en el que ens trobem
char lind = 50;  // Valor llindar
char pas[3]= {1,5,10};  // Pas 
char r=1;  // Rang 
char k=0;  // Canvi estat entre elegir Pas o Rang
char j = 0;  // Index del pas
char m = 0;  // Elegir si registre o no so
unsigned long SO=0;  
unsigned int SOmitj=0;
float SOef=0;  // Valor de so enregistrat
unsigned int SOint;  // Valor en nombre enter del so enregistrat
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
char fig[6][8] = {  {0b00000000, 0b00100100, 0b00100100, 0b00000000,  // Figura 1
  0b01000010, 0b00100100, 0b00011000, 0b00000000},
  {0b00111100, 0b01111110, 0b11111111, 0b11111111, 
  0b10111101, 0b11111111, 0b01111110, 0b00111100},
  {0b00000000, 0b00100100, 0b00100100, 0b00000000, 
  0b00000000, 0b00100100, 0b00011000, 0b00000000},
  {0b00111100, 0b01111110, 0b11111111, 0b11111111,  // Figura 2
  0b11111111, 0b11111111, 0b01111110, 0b00111100},
  {0b00000000, 0b00100100, 0b00100100, 0b00000000,
  0b00000000, 0b00011000, 0b00100100, 0b00000000},
  {0b00000000, 0b00100100, 0b00100100, 0b00000000,
  0b00000000, 0b00011000, 0b00100100, 0b00000000}};
char Polsad;  // Polsador que s'ha premut
// Definició de les funcions que farem servir 
void Linia(void);  // Escriu una línia de resultats
void escriuValor(unsigned int Valor);  // Escriu un valor a la pantalla
void EnviaL(char Caracter);  // Envia un caràcter
void Esborra(void);  // Esborra la pantalla i posa el cursor a l'inici
void Envia3max(char Valor[]);  // Envia un joc de valors als tres MAX7221
                               // desactivant interrupcions
void led(void);  // Envia figures a la matriu LED
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
void Cursor(char Filera, char Columna);  // Posiciona el cursor
void TocaNota(char ValPR2, char ValCCPR1L, char ValDC1B);  // Sona el brunzidor
int Sqrt(unsigned long x) ;  // Funció per calcular l?arrel
void llindar(char Pols);  // Funció canviar de llindar
void main (void) {
  TRISA = 0xFF;  // Tot el port A és d'entrada
  TRISB = 0;  // Tot el port B és de sortida
  TRISC = 0b01000000;  // Posa RC6 (AN8) com a entrada
  // La resta del port C és de sortida
  ADCON1 = 0b00010000;  // Posa el conversor a 1/8 de la freqüència
  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
  ANSEL = 0b00000001;  // Configura AN0 com entrada analògica
  ANSELH = 0b00000001;  // Configura AN8 com entrada analògica
  PORTB = 0;  // Inicialitza a 0 el port B
  PORTC = 0;  // Inicialitza a 0 el port C
  FiTimer1 = 0;  // Aquest bit es posarà a 1 quan el temporitzador acabi
  TMR1H = 248;  // Inicialitza el Timer1
  TMR1L = 94;
  T1CON = 0b00110001;  // Configuració de Timer1
  OPTION_REG = 0b10000101;  // Configuració de Timer0
  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
  Apaga();  // Apaga tots els LED
  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
  while (1) {  // Bucle infinit
    if (Inicia == 0){
      Esborra();
      p = p+1;
      p=p%2;
      if (p==1){  // Apagat
        EnviaL('E');  // Lletra
        EnviaL('n');  // Lletra
        EnviaL('c');  // Lletra
        EnviaL('e');  // Lletra
        EnviaL('n');  // Lletra
      }
      if (p==0){  // Encés
        EnviaL('A');  // Lletra
        EnviaL('p');  // Lletra
        EnviaL('a');  // Lletra
        EnviaL('g');  // Lletra
        EnviaL('a');  // Lletra
        PORTC = 0b00000000;  // Inicialització variables
        m=0;
        mod=0;
        j=0;
        lind = 50;
        k = 0;
      }
      __delay_ms(500);  // Retard de 0,5 s
      Esborra();  // Esborra LCD
    }
    if (p == 1) {
      SOmitj=0;  // Inicialització variables
      SO=0;
      SOef=0;
      Polsad = Polsador();  // Llegim els polsadors
      if (Polsad == 2){  // Si s'ha premut el pulsador 2
        m = m+1;
        m = m%2;
        Esborra();  // Esborra LCD
        Apaga();  // Apaga LED
        __delay_ms(300);  // Retard 0,3 s
      }
      FiTimer1 = 0;  // Desactivem el bit de final de temporització
      // Per assegurar la desconnexió del programador
      if (m==0){  // Enregistre So
        if (Polsad == 1){  // Si s'ha premut el pulsador 1
          mod = mod + 1;
          mod = mod%4;
        }
        if (mod == 0) {  // Mode 1
          Esborra();  // Esborra LCD
          Cursor(1,1);  // Posa el cursor 
          EnviaL('B');  // Lletra
          EnviaL('a');  // Lletra
          EnviaL('r');  // Lletra
          r = 5;  // Rang
          Cursor(1,11);  // Posa cursor
          escriuValor(r);  // Escriu una línia de resultats
          Cursor(2,11);  // Posa el cursor
          escriuValor(lind);  // Escriu una línia de resultats
        }
        if (mod == 1) {  // Mode 2
          Esborra();  // Esborra LCD
          Cursor(1,1);  // Posa el cursor
          EnviaL('P');  // Lletra
          EnviaL('a');  // Lletra
          EnviaL('s');  // Lletra
          EnviaL('s');  // Lletra
          EnviaL('a');  // Lletra
          EnviaL('d');  // Lletra
          EnviaL('i');  // Lletra
          EnviaL('s');  // Lletra
          r=3;  // Rang
          Cursor(1,11);  // Posa el cursor
          escriuValor(r);  // Escriu una línia de resultats
          Cursor(2,11);  // Posa el cursor
          escriuValor(lind);  // Escriu una línia de resultats
        }  
        if (mod == 2) {  // Mode 3
          Esborra();  // Esborra LCD
          Cursor(1,1);  // Posa el cursor
          EnviaL('B');  // Lletra
          EnviaL('i');  // Lletra
          EnviaL('b');  // Lletra
          EnviaL('l');  // Lletra
          EnviaL('i');  // Lletra
          EnviaL('o');  // Incrementa y però la manté entre 0 i 7
          r=2;  // Rang
          Cursor(1,11);  // Posa el cursor
          escriuValor(r);  // Escriu una línia de resultats
          Cursor(2,11);  // Posar cursor
          escriuValor(lind);  // Escriu una línia de resultats
        }
        if (mod == 3) {  // Mode 4
          Esborra();  // Esborra LCD
          Cursor(1,1);  // Posa el cursor
          EnviaL('P');  // Lletra
          EnviaL('e');  // Lletra
          EnviaL('r');  // Lletra
          EnviaL('s');  // Lletra
          EnviaL('o');  // Lletra
          EnviaL('n');  // Lletra
          Cursor(1,11);  // Posa el cursor
          escriuValor(r);  // Escriu una línia de resultats
          Cursor(2,11);  // Posa el cursor
          escriuValor(lind);  // Escriu una línia de resultats
        }
        for (char k = 0; k < 32; k++){  // Llegim 32 valors
          while (FiTimer1 == 0)  // Mira si Timer1 ha arribat a zero
            ;  // Si no hi ha arribat, espera
          T1CONbits.TMR1ON = 0;  // Atura momentàniament el Timer1
          TMR1H = 248;  // Inicialitza el Timer1
          TMR1L = 94;
          ADCON0 = 0b10100001;  // Activa el conversor connectat a AN8
          T1CONbits.TMR1ON = 1;  // Torna a engegar el Timer1
          FiTimer1 = 0;  // Tornem a posar el bit a zero
          ADCON0bits.GO = 1;
          while (ADCON0bits.GO == 1)  // Mentre no acabi
            ;  // ens esperem
          Lectura[k] = ADRESH * 256 + ADRESL;  // Guardem el resultat
          SOmitj+=(Lectura[k]);  // Suma dels resultats per fer la mitjana
        }
        SOmitj=SOmitj/32;  // Mitjana de So
        for (int k=0; k<32; k++){  // Per fer la mitjana
          SO+=((Lectura[k]-SOmitj)*(Lectura[k]-SOmitj));
        }
        SOef=Sqrt((SO)/32)*esc[r-1];  // so eficaç
        SOint=SOef;  // El so en format unsigned int
        SOint = SOint/10;
        __delay_ms(10);  // Retard 0,1 s
        Cursor(2,1);  // Posa el cursor
        if (SOint > 100){
          SOint = 100;  
          PORTC = 0b00001111;  // Activem els LED
        } else {
          PORTC = 0b00000000;  // Desectivem els LED
        }
        escriuValor(SOint);  // Escriu una valor  
        led();  // Enviem figures a la matriu LED
        if (n==1){
          brun = 10*(SOint-lind)/(100-lind);
          TocaNota(238-12*brun, 119-6*brun, 2);  // Funció brunzidor
          __delay_ms(200);  // Retard 0,2 s
        }
        __delay_ms(500);  // Retard 0,5 s
      }
      if (m==1 && mod!=3){
        Esborra();  // Esborra LCD
        llindar(Polsad);  // Funció llindar
        __delay_ms(100);  // Retard 0,1 s
      }
      if (m==1 && mod==3){
        Esborra();  // Esborra LCD
        Apaga();  // Apaga matriu LED
        if (Polsad == 1){  // Si s'ha premut pulsador 1
          k +=1;
          k = k%2;
          __delay_ms(10);  // Retard 0,01 s
        }
        if (k == 0) {
          Esborra();  // Esborra LCD
          Cursor(1,1);  // Posa el cursor
          EnviaL('R');  // Lletra
          EnviaL('a');  // Lletra
          EnviaL('n');  // Lletra
          EnviaL('g');  // Lletra
          EnviaL(':');  // Lletra
          escriuValor(r);  // Escriu un valor
          Cursor(2,1);  // Lletra
          EnviaL('P');  // Lletra
          EnviaL('a');  // Lletra
          EnviaL('s');  // Lletra
          EnviaL(':');  // Lletra
          escriuValor(1);  // Escriu un valor
          __delay_ms(100);  // Retard 0,1 s 
          if (Polsad == 3){  // Si s'ha premut pulsador 3
            j +=1;
            j = j%3;
            __delay_ms(10);  // Retard 0,01 s
          }
          if (Polsad == 4){  // Si s'ha premut pulsador 4
            if (r>1){
              r -=1;  
              __delay_ms(10);  // Retard 0,01 s
            }
          }
          if (Polsad == 5){  // Si s'ha premut pulsador 5
            if (r<8){
              r +=1;  
              __delay_ms(10);  // Retard 0,01 s
            }
          }
        }
        if (k == 1){
          Esborra();  // Esborra LCD
          llindar(Polsad);  // Funció elegir llindar
          __delay_ms(100);  // Retard 0,1 s
        }
      }
    } else {
      Apaga();  // Apaga matriu LED
      Esborra();  // Esborra LCD
    }
  }
}
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
  }
}
void escriuValor(unsigned int Valor){
  char Digits[5];  // Variable amb el número dígit a dígit
  // Digits[0] són les unitats
  // Convertim a BCD
  Digits[0] = Valor % 10;  // Unitats
  Valor = Valor / 10;
  Digits[1] = Valor % 10;  // Desenes
  Valor = Valor / 10;
  Digits[2] = Valor % 10;  // Centenes
  Valor = Valor / 10;
  Digits[3] = Valor % 10;  // Milers
  Digits[4] = Valor / 10;  // Desenes de milers
  // Passem els dígits a ASCII
  for (char j = 0; j < 5; j++){  // 5 dígits
    Digits[j] = Digits[j] + '0';  // Li sumem el codi ASCII de 0
  }
  // Suprimim zeros innecessaris
  if (Digits[4] == '0') {  // Mirem si el primer dígit és 0
    Digits[4] = ' ';  // Si ho és, hi posem un espai
    if (Digits[3] == '0') {  // I mirem si ho és el segon
      Digits[3] = ' ';  // Si ho és, hi posem un espai
      if (Digits[2] == '0') {  // I mirem si ho és el tercer
        Digits[2] = ' ';  // Si ho és, hi posem un espai
        if (Digits[1] == '0') {  // I mirem si ho és el quart
          Digits[1] = ' ';  // Si ho és, hi posem un espai
        }  // El 0 de les unitats el mostrarem sempre
      }
    }
  }
  for (signed char k = 3; k >= 0; k--){  // Només escrivim quatre valors
    EnviaL(Digits[k]);  // Escriu un dígit a la pantalla
  }
}
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 led(void){
  Apaga();
  for (char k = 0; k < 8; k++){
    Sortida[1] = k+1;  // Filera
    Sortida[3] = k+1;
    Sortida[5] = k+1;
    if (SOint < lind){
      n=0;
      Sortida[0] = fig[0][k];  // Vermells
      Sortida[2] = fig[1][k];  // Verds
      Sortida[4] = fig[2][k];  // Blaus
      Envia3max(Sortida);  // Ho envia al MAX7221
      __delay_ms(1);  // Retard 1 ms
    }
    if (SOint >= lind){
      n=1;
      Sortida[0] = fig[3][k];  // Vermells
      Sortida[2] = fig[4][k];  // Verds
      Sortida[4] = fig[5][k];  // Blaus
      Envia3max(Sortida);  // Ho envia al MAX7221
      __delay_ms(1);  // Retard 1 ms
    }
  }
}
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 (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
}
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 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 Apaga(void) {  // Apaga tots els LED
  char Bytes[6];  // Els sis bytes que cal enviar
  for (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
  }
}
char Polsador(void) {
  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
  ANSEL = 0b00000101;  // Configura AN0 i AN2 com entrada analògica
  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) {
  TRISC = 0b01100000;  // 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 = 0b01000000;  // Posem RC5 (sortida del PWM) com a sortida
  __delay_ms(200);  // Retard de 0,2 s
  TRISC = 0b01100000;  // Posem RC5 (sortida del PWM) com a entrada
  // O sigui, silenci
  __delay_ms(200);  // Retard de 0,2 s
}
int Sqrt(unsigned long x){  // Funció calcular sqrt  
  if (x == 0 || x == 1)  // Cas base
    return x;
  int start = 1,  ans;  // Do Binary Search for floor(sqrt(x))
  unsigned long end = x;
  while (start <= end){  
    unsigned long mid = (start + end) / 2;
    if (mid*mid == x)  // If x is a perfect square
      return mid;  
    if (mid*mid < x){  // Since we need floor, we update answer when mid*mid is
                          // smaller than x, and move closer to sqrt(x)
      start = mid + 1;
      ans = mid;
    } else  // If mid*mid is greater than x
      end = mid-1;  
  }
  return ans;
}
void llindar(char Pols){  // Funció canviar llindar
  if (Pols == 3){  
    j = j+1;
    j = j%3;
    __delay_ms(50);
  }
  if (Pols == 4){
    lind-=pas[j];
    __delay_ms(50);
  }
  if (Pols == 5){
    lind+=pas[j];
    __delay_ms(50);
  }
  Cursor(1,1);  // Posa cursor
  EnviaL('L');  // Lletra
  EnviaL('i');  // Lletra
  EnviaL('n');  // Lletra
  EnviaL('d');  // Lletra
  EnviaL('a');  // Lletra
  EnviaL('r');  // Lletra
  EnviaL(':');  // Lletra
  escriuValor(lind);  // Escriu linia de resultats
  Cursor(2,1);  // Posa cursor
  EnviaL('P');  // Lletra
  EnviaL('a');  // Lletra
  EnviaL('s');  // Lletra
  EnviaL(':');  // Lletra
  escriuValor(pas[j]);  // Escriu linia de resultats
}

 

 

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