Programació en C del PIC 16F690

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

Rellotge

Programa del grup 3

Aquest grup va fer un rellotge amb alarma que també avisa a les hores en punt. Amb els polsadors es pot posar el rellotge en hora i activar i desactivar l'alarma i els avisos. Uns caràcters especials serveixen per indicar si l'alarma i els avisos estan activats o desactivats.

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
#define FiTimer1 PIR1bits.TMR1IF  // Li assigna un nom al bit que indica el final del Timer 1
#define _XTAL_FREQ  4000000  // La freqüència del rellotge és 4 MHz
#include <stdio.h>
unsigned char Compta;// Variable de 8 bits sense signe (0 a 255)
char Valor=0;
char h1 = '1', h2 = '3', min1 = '0', min2 = '0', sec1 = '0', sec2 = '0', dia1 = '1', dia2 = '9';
char mes1 = '1', mes2 = '2', any1 = '2', any2 = '0', any3 = '2', any4 = '3'; // Variables temps
int i = 1, mes = 12, any = 2023; 
char dia[7][3]={ {'L', 'U', 'N'}, 
                 {'M', 'A', 'R'},
                 {'M', 'I', 'E'},
                 {'J', 'U', 'E'},
                 {'V', 'I', 'E'},
                 {'S', 'A', 'B'},
                 {'D', 'O', 'M'} };
char Polsad = 0;  // Polsador que s'ha premut
char Edicio = 0, Edicioalarm = 0, alarma = 0;
char dhms = 1, mute = 0, alarmah1 = '1', alarmah2 = '2', alarmamin1 = '5', alarmamin2 = '6', alarmon = 0;
char campana[8] = {0b00000000, 0b00000100, 0b00001110, 0b00010001,
                   0b00010001, 0b00011111, 0b00000100, 0b00000000};
char nocampana[8] = {0b00000000, 0b00000100, 0b00001110, 0b00010001,
                     0b00010001, 0b00011111, 0b00000000, 0b00000000};
char nota[8] = {0b00000000, 0b00000110, 0b00000100, 0b00000100,
                0b00001100, 0b00001100, 0b00000000, 0b00000000};
char nonota[8] = {0b00000000, 0b00010110, 0b00001100, 0b00000100,
                  0b00001110, 0b00001101, 0b00000000, 0b00000000};
// Definició de les funcions que farem servir 
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
void DisplayTime(void);
void DisplayAlarm(void);
void TocaNota(char ValPR2, char ValCCPR1L, char ValDC1B);
void Calculardata(void);
void DefCarac(char Numero, char Fileres[8]);  // Crea un caràcter definit per l'usuari
void main (void) {
  __delay_ms(3000);  // Esperem que arrenqui la pantalla
  Compta = 0;  // Compta el nombre de cops que ha acabat el Timer
  // Configuració d'entrades i sortides
  TRISC = 0b11111110;  // Posa el bit 0 del port C com a sortida
  PORTC = 0;  // Desactiva les sortides del port C
  CCP1CON = 0b00001100;  // Configura el PWM, bits P1M (bits 7-6) a 00 mode senzill
  FiTimer1 = 0;  // Aquest bit es posarà a 1 quan el temporitzador acabi
                 // cal desactivar-lo des del programa
  ANSELH = 0;  // Desactiva les altres entrades analògiques
  TRISB = 0;  // Tot el port B és de sortida
  TRISA = 0xFF;  // Tot el port A és d'entrada
  TMR1H = 231;  // Inicialitza el Timer1
  TMR1L = 150;
  T1CON = 0b00110001; // Configuració de Timer1
                      // 11 - Factor d'escala de 8
                      // I el posem en marxa
  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;  // Activa el conversor A/D connectat a AN2 
  PIE1bits.TMR1IE = 1;
  INTCONbits.PEIE = 1;
  INTCONbits.GIE = 1;  // Habilitem les interrupcions a nivell general
  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ó
  Esborra();  // Esborra la pantalla i posa el cursor a l'inici
  DefCarac(0, campana);  // Defineix caràcter
  DefCarac(1, nota);  // Defineix caràcter
  DefCarac(2, nonota);  // Defineix caràcter
  DefCarac(3, nocampana);  // Defineix caràcter
  while (1){  // Inici del bucle de programa
    EnviaL(254);
    EnviaL(12);
    while(Polsad !=0){
      Polsad = Polsador();
    }  // Mentre el contingut del parèntesi sigui 1
    Polsad = Polsador();
    if (Polsad == 2){
      Edicio = 1;
      dhms=1;
    }
    while (Edicio == 1){
      while(Polsad !=0){
        Polsad = Polsador();
      }
      EnviaL(254);
      EnviaL(13);
      Polsad = Polsador();
      if (Polsad == 2){
        Edicio = 0;
      }
      if (Polsad == 3 && dhms != 4){
        dhms++;
      }
      if (Polsad == 3 && dhms == 4){
        dhms=1;
      }
      if (Polsad == 5 && dhms == 1){
        h2++;
        if (h2 == ':' && h1!='2'){
          h2='0';
          h1++;
        }
        if (h2 == '4' && h1 == '2'){
          h2='0';
          h1='0';
        }
      }
      if (Polsad == 5 && dhms == 2){
        min2++;
        if (min2 == ':' && min1 != '5'){
          min1++;
          min2='0';
        }
        if (min2 == ':' && min1 == '5'){
          min2='0';
          min1='0';
        }
      }
      if (Polsad == 5 && dhms == 3){
        i++;
        if (i > 6) {
          i=0;
        }
        if (dia2 != '9' && dia1 != '3' && mes != 2){
          dia2++;
        } else if (dia2 != '8' && dia1 == '2' && mes == 2){
          dia2++;
        } else if ((dia2 == '8' && dia1 == '2' && mes == 2 && (any%4 != 0 || (any%4 == 0 && any%100 == 0 && any%400 != 0))) || (dia2 == '9' && dia1 == '2' && mes == 2)){
          dia1 = '0';
          dia2 = '1';
        } else if (dia2 == '8' && dia1 == '2' && mes == 2 && any%4 == 0 && ((any%100 == 0 && any%400 == 0) || any%100 != 0)){
          dia2++;
        } else if (dia2 == '9' && dia1 != '3'){
          dia2='0';
          dia1++;
        } else if (dia1 == '3' && dia2 == '0' && (mes==4 || mes==6 || mes==9 || mes==11)){
          dia2='1';
          dia1='0';
        } else if (dia1 == '3' && dia2 == '0' && (mes==1 || mes==3 || mes==5 || mes==7 || mes==8 || mes==10 || mes==12)){
          dia2++;
        } else if (dia1 == '3' && dia2 == '1' && (mes==1 || mes==3 || mes==5 || mes==7 || mes==8 || mes==10 || mes==12)){
          dia2='1';
          dia1='0';
        }
      }
      if (Polsad == 4 && dhms == 1){
        h2--;
        if (h2 == '/' && h1!='0'){
          h2='9';
          h1--;
        }
        if (h2 == '/' && h1 == '0'){
          h2='3';
          h1='2';
        }
      }
      if (Polsad == 4 && dhms == 2){
        min2--;
        if (min2 == '/' && min1 != '0'){
          min1--;
          min2='9';
        }
        if (min2 == '/' && min1 == '0'){
          min2='9';
          min1='5';
        }
      }
      if (Polsad == 4 && dhms == 3){
        if (i != 0){
          i--;
        } else {
          i=6;
        }
        dia2--;
        if (dia2 == '/' && dia1!='0'){
          dia2='9';
          dia1--;
        }
        if (dia2 == '/' && dia1 == '0'){
          if (mes==4 || mes==6 || mes==9 || mes==11){
            dia1 = '3';
            dia2 = '0';
          } else if (mes==1 || mes==3 || mes==5 || mes==7 || mes==8 || mes==10 || mes==12){
            dia1 = '3';
            dia2 = '1';
          } else if (mes==2 && any%4 == 0 && ((any%100 == 0 && any%400 == 0) || any%100 != 0)){
            dia1 = '2';
            dia2 = '9';
          } else if ((mes == 2 && (any%4 != 0 || (any%4 == 0 && any%100 == 0 && any%400 != 0))) || (dia2 == '9' && dia1 == '2' && mes == 2)){
            dia1 = '2';
            dia2 = '8';
          }
        }
      }
      DisplayTime();
      if (dhms == 1){
        Cursor(1,1);
      }
      if (dhms == 2){
        Cursor(1,4);
      }
      if (dhms == 3){
        Cursor(2,1);
      }
    }
    if (Polsad == 1){
      Edicioalarm = 1;
      dhms=1;
      Esborra();
    }
    while (Edicioalarm == 1){
      while(Polsad !=0){
        Polsad = Polsador();
      }
      EnviaL(254);
      EnviaL(13);
      Polsad = Polsador();
      if (Polsad == 3 && dhms != 3){
        dhms++;
      }
      if (Polsad == 3 && dhms == 3){
        dhms=1;
      }
      if (Polsad == 5 && dhms == 1){
        alarmah2++;
        if (alarmah2 == ':' && alarmah1!='2'){
          alarmah2='0';
          alarmah1++;
        }
        if (alarmah2 == '4' && alarmah1 == '2'){
          alarmah2='0';
          alarmah1='0';
        }
      }
      if (Polsad == 5 && dhms == 2){
        alarmamin2++;
        if (alarmamin2 == ':' && alarmamin1 != '5'){
          alarmamin1++;
          alarmamin2='0';
        }
        if (alarmamin2 == ':' && alarmamin1 == '5'){
          alarmamin2='0';
          alarmamin1='0';
        }
      }
      if (Polsad == 4 && dhms == 1){
        alarmah2--;
        if (alarmah2 == '/' && alarmah1!='0'){
          alarmah2='9';
          alarmah1--;
        }
        if (alarmah2 == '/' && alarmah1 == '0'){
          alarmah2='3';
          alarmah1='2';
        }
      }
      if (Polsad == 4 && dhms == 2){
        alarmamin2--;
        if (alarmamin2 == '/' && alarmamin1 != '0'){
          alarmamin1--;
          alarmamin2='9';
        }
        if (alarmamin2 == '/' && alarmamin1 == '0'){
          alarmamin2='9';
          alarmamin1='5';
        }
      }
      DisplayAlarm();
      if (dhms == 1){
        Cursor(1,6);
      }
      if (dhms == 2){
        Cursor(1,9);
      }
      if (Polsad == 1){
        Edicioalarm = 0;
        Esborra();
      }
    }
    if (mute == 0){    
      Cursor(1, 15);
      EnviaL(1);
    } else if (mute == 1){    
      Cursor(1, 15);
      EnviaL(2);
    }
    if (alarmon == 0){    
      Cursor(1, 16);
      EnviaL(3);
    } else if (alarmon == 1){    
      Cursor(1, 16);
      EnviaL(0);
    }
    DisplayTime();
    Cursor(1,1);
    if (alarmon == 1 && min1 == alarmamin1 && min2 == alarmamin2 && h1 == alarmah1 && h2 == alarmah2 && sec1 == '0' && sec2 == '0'){
      alarma = 1;
      Esborra();
    }
    while(alarma == 1){
      Polsad = Polsador();
      DisplayAlarm();
      if (Polsad == 1){
        alarma = 0;
        Esborra();
      }
      TocaNota(189, 95, 0);    
    }
    if (Polsad == 4 && mute == 0){
      mute=1;
    } else if (Polsad == 4 && mute == 1){
      mute=0;
    }
    if (mute == 0 && min1 == '0' && min2 == '0' && sec1 == '0' && sec2 == '0'){
      TocaNota(189, 95, 0);  // Valor que correspon aproximadament a mi3
      __delay_ms(600);
    }
    if (Polsad == 5 && alarmon == 0){
      alarmon=1;
    } else if (Polsad == 5 && alarmon == 1){
      alarmon=0;
    }
  }
}
void __interrupt() temporit(void){  // Línia alternativa
  if  (FiTimer1){  // Comprovem que hi ha interrupció per Timer 1
    T1CONbits.TMR1ON = 0;  // Atura momentàniament el Timer1
    TMR1H = 231;  // Inicialitza el Timer1
    TMR1L = 150;
    T1CONbits.TMR1ON = 1;  // Torna a engegar el Timer1
    Compta++;  // Incrementa Compta
    FiTimer1 = 0;  // Tornem a posar el bit a zero
    if (Compta == 20) {  // Si ha acabat vint vegades
      if (sec2 != '9'){
        sec2++;
        Compta = 0;  // Reinicialitza Compta
      } else if (sec1 != '5'){
        sec1++;
        sec2 = '0';
        Compta = 0;  // Reinicialitza Compta
      } else if (min2 != '9'){
        sec1 = '0';
        sec2 = '0';
        min2++;
        Compta = 0;
      } else if (min1 != '5'){
        sec1 = '0';
        sec2 = '0';
        min2 = '0';
        min1++;
        Compta = 0;
      } else if (h2 != '9' && h1 != '2'){
        sec1 = '0';
        sec2 = '0';
        min1 = '0';
        min2 = '0';
        h2++;
        Compta = 0;
      } else if (h2 == '9' && h1 != '2') {
        sec1 = '0';
        sec2 = '0';
        min1 = '0';
        min2 = '0';
        h2 = '0';
        h1++;
        Compta = 0;
      } else {
        sec1 = '0';
        sec2 = '0';
        min1 = '0';
        min2 = '0';
        h2 = '0';
        h1 = '0';
        i++;
        if (i > 6) {
          i=0;
        }
        Compta = 0;
        Calculardata();
      }
    }
  }
}
void DisplayTime(void){
  Cursor(1, 1);  // Posició
  EnviaL(h1);
  EnviaL(h2);
  EnviaL('.');
  EnviaL(min1);
  EnviaL(min2);
  EnviaL('.');
  EnviaL(sec1);
  EnviaL(sec2);
  Cursor(2, 1);
  EnviaL(dia[i][0]);
  EnviaL(dia[i][1]);
  EnviaL(dia[i][2]);
  Cursor(2, 7);
  EnviaL(dia1);
  EnviaL(dia2);
  EnviaL('/');
  EnviaL(mes1);
  EnviaL(mes2);
  EnviaL('/');
  EnviaL(any1);
  EnviaL(any2);
  EnviaL(any3);
  EnviaL(any4);
}
void DisplayAlarm(void){
  Cursor(1, 6);  // Posició
  EnviaL(alarmah1);
  EnviaL(alarmah2);
  EnviaL(':');
  EnviaL(alarmamin1);
  EnviaL(alarmamin2);
}
void EnviaL(char Caracter) {
  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
}
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
  }
  PORTC = Pols;
  __delay_ms(10);
  return Pols;
}
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 DefCarac(char Numero, char Fileres[8]) {
  char Posicio = 0;  // Variable per a calcular la posició
  if (Numero  < 8) {  // Comprovem que sigui un valor raonable
    Posicio = Numero * 8;  // Calculem l'adreça de memòria
  }
  Posicio = Posicio + 64;  // Posa el bit de caràcter especial a 1
  EnviaL(254);  // Control de la posició del cursor
  EnviaL(Posicio);  // Canvia el cursor de lloc
  for (signed char k = 0; k < 8; k++){
    EnviaL(Fileres[k]);  // Canvia el cursor de lloc
  }
}
void Calculardata(void){
  if (dia2 != '9' && dia1 != '3' && mes != 2){
    dia2++;
  } else if (dia2 != '9' && dia1 != '2' && mes == 2){
    dia2++;
  } else if (dia2 != '8' && dia1 == '2' && mes == 2){
    dia2++;
  } else if ((dia2 == '8' && dia1 == '2' && mes == 2 && (any%4 != 0 || (any%4 == 0 && any%100 == 0 && any%400 != 0))) || (dia2 == '9' && dia1 == '2' && mes == 2)){
    mes++;
    mes2++;
    dia1 = '0';
    dia2 = '1';
  } else if (dia2 == '8' && dia1 == '2' && mes == 2 && any%4 == 0 && ((any%100 == 0 && any%400 == 0) || any%100 != 0)){
    dia2++;
  } else if (dia2 == '9' && dia1 != '3'){
    dia2='0';
    dia1++;
  } else if (dia1 == '3' && dia2 == '0' && (mes==4 || mes==6 || mes==9 || mes==11)){
    dia2='0';
    dia1='0';
    mes++;
    if(mes==10){
      mes1++;
      mes2='0';
    } else {
      mes2++;
    }
  } else if (dia1 == '3' && dia2 == '0' && (mes==1 || mes==3 || mes==5 || mes==7 || mes==8 || mes==10 || mes==12)){
    dia2++;
  } else if (dia1 == '3' && dia2 == '1' && (mes==1 || mes==3 || mes==5 || mes==7 || mes==8 || mes==10 || mes==12)){
    mes++;
    dia1='0';
    if(mes==13){
      mes=1; 
      mes1='0'; 
      mes2='1';
      any++;
      if(any4 != '9'){
        any4++;
      } else {
        any4='0';
        if (any3!='9'){
          any3++;
        } else {
          any3='0';
          if (any2 != '9'){
            any2++;
          } else {
            any2='0';
            if (any1 != '9'){
              any1++;
            } else {
              any1='2';
            }
          }
        }
      }
    } else {
      mes2++;
    }
  }
}

 

 

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