En aquest cas es tracta d'un rellotge despertador en el que l'usuari, a més de poder ajustar l'hora, pot seleccionar la durada del so d'alarma.
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 #define _XTAL_FREQ 4000000 // La freqüència del rellotge és 4 MHz #define PolsadoR RA3
char AdreI2C = 0b11010000; // Adreça del dispositiu I2C (1101000) // Rodada cap a l'esquerra (preparada per afegir el bit RW) char Posicio = 0; // Posició a la pantalla char Lectura; // Aquí guardarem el resultat de la lectura char Polsad; // Polsador que s'ha premut char Port = 0; // Valor a escriure al port C // RC7 és SDA // RC6 és SCL // Definició de les funcions que farem servir char Adressa = 11; char Adresa = 8; char Temps = 0;
char LlegirI2C(char AdreMem); // Llegeix un byte I2C char Polsador(void); // Funció de lectura dels polsadors void Esborra(void); // Esborra la pantalla i posa el cursor a l'inici void Alarma(void); void Mod(char AdreMem); void Increment(char AdreMem, char Dades); // Funció d'increment void Decrement(char AdreMem, char Dades); // Funció de decrement void EscriuI2C(char AdreMem, char Dades); // Escriu un byte I2C void SDAentrada(void); // Posa SDA com a entrada void SDAsortida(void); // Posa SDA com a sortida void StartI2C(void); // Envia el bit d'inici I2C void StopI2C(void); // Envia el bit d'aturada I2C void ACK_S(void); // Reb un ACK des de l'esclau void NACK_M(void); // Envia un NACK a l'esclau void EnvByteI2C(char Buffer); // Funció interna que envia un byte a I2C char RebByteI2C(void); // Funció interna que rep un byte a I2C void EnviaL(char Caracter); // Envia un caràcter void EnviaBCD2(char Caracter); // Mostrem a la pantalla un valor BCD // a partir de dues xifres hexadecimals void EnviaBCD1(char Caracter); // Mostrem a la pantalla un valor BCD // a partir d'una xifra hexadecimal void TocaNota(char ValPR2, char ValCCPR1L, char ValDC1B);
void main (void) {
ANSEL = 0b00000101; // Configura AN0 i AN2 com entrada analògica
ANSELH = 0; // Desactiva les altres entrades analògiques
TRISA = 0xFF; // Tot el port A és d'entrada
TRISB = 0; // Tot el port B és de sortida
TRISC = 0; // Tot el port C és de sortida
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ó
PORTB = 0; // Inicialitza a 0 el port B
PORTC = 0; // Inicialitza a 0 el port C
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
// Com a mostra, es posen les 23.58.34
// del dijous 31-3-2016
// per poder veure un canvi de dia i de mes
EscriuI2C(0, 0x40); // Segons
EscriuI2C(1, 0x50); // Minuts
EscriuI2C(2, 0x22); // Hores
EscriuI2C(3, 0x05); // Dia setmana
EscriuI2C(4, 0x25); // Dia mes
EscriuI2C(5, 0x02); // Mes (març)
EscriuI2C(6, 0x97); // Any (2016)
EscriuI2C(7, 0x00); // Polsos desactivats
EscriuI2C(8, 0x00); // Hores Alarma
EscriuI2C(9, 0x00); // Minuts Alarma
EscriuI2C(10,0x10); // Duració Alarma
EscriuI2C(12,0x00); // Activat/Desactivat Alarma
while (1) {
Polsad = Polsador(); // Llegim els polsadors
__delay_ms(200); // Retard d'2 ms
Temps = ++Temps;
if (Polsad == 1) { // Si s'ha premut el polsador 1
if (Adressa == 11){
Adressa = 1;
} else if (Adressa < 6){
Adressa = ++Adressa;
} else {
Adressa = 11;
}
}
if (Polsad == 2){ // Si s'ha premut el polsador 2
char Lektura;
Lektura = LlegirI2C(Adressa);
Decrement(Adressa, Lektura);
}
if (Polsad == 3){ // Si s'ha premut el polsador 3
char Lektura;
Lektura = LlegirI2C(Adressa);
Increment(Adressa,Lektura);
}
if (Polsad == 4){ // Si s'ha premut el polsador 4
EscriuI2C(12,0x01);
Alarma();
}
if (PolsadoR == 0 && LlegirI2C(12)==0){ // Si s'ha premut el polsador independent (RA3)
EscriuI2C(12,0x01);
} else if (PolsadoR == 0 && LlegirI2C(12)==1){
EscriuI2C(12,0x00);
} else{
if (Temps > 4){
Temps = 0;
Posicio = 64; // La primera columna de la segona fila és 64
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
Lectura = LlegirI2C(2); // Hores
EnviaBCD2(Lectura); // Mostrem a la pantalla el valor
EnviaL('.'); // Separador
Lectura = LlegirI2C(1); // Minuts
EnviaBCD2(Lectura); // Mostrem a la pantalla el valor
EnviaL('.'); // Separador
Lectura = LlegirI2C(0); // Segons
EnviaBCD2(Lectura); // Mostrem a la pantalla el valor
Mod(Adressa);
Posicio = 0; // La primera columna de la primera fila és 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
Lectura = LlegirI2C(4); // Dia
EnviaBCD2(Lectura); // Mostrem a la pantalla el valor
EnviaL('-'); // Separador
Lectura = LlegirI2C(5); // Mes
EnviaBCD2(Lectura); // Mostrem a la pantalla el valor
EnviaL('-'); // Separador
EnviaL('2'); // Any primer dígit
EnviaL('0'); // Any segon dígit
Lectura = LlegirI2C(6); // Any
EnviaBCD2(Lectura); // Mostrem a la pantalla el valor
EnviaL(' '); // Espai
EnviaL(' '); // Espai
Lectura = LlegirI2C(3); // Dia Setmana
EnviaBCD1(Lectura); // Mostrem a la pantalla el valor
if (LlegirI2C(12)==1){
EnviaL(' ');
EnviaL('A');
} else {
EnviaL(' ');
EnviaL(' ');
}
}
}
if (LlegirI2C(2)==LlegirI2C(8) && LlegirI2C(1)==LlegirI2C(9) && LlegirI2C(12)==1){
char lekktura;
char top;
top = LlegirI2C(10);
lekktura = LlegirI2C(0);
while(lekktura < top){
TRISC = 0b00100000; // Definim com volem les E/S del port C
// RC5 (sortida del PWM), de moment, com a entrada
PORTC = 0; // Desactiva les sortides del port C
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
TocaNota(141,71,0);
Esborra();
EnviaBCD2(LlegirI2C(8));
EnviaL('.');
EnviaBCD2(LlegirI2C(9));
lekktura = LlegirI2C(0);
}
}
}
}
char LlegirI2C(char AdreMem) {
char Rebut; // Valor rebut
SDAsortida(); // Posa SDA com a sortida
StartI2C(); // Envia el bit d'inici I2C
EnvByteI2C(AdreI2C); // Enviem l'adreça del dispositiu
// Amb un zero al final per indicar escriptura
SDAentrada(); // Posa SDA com a entrada
ACK_S(); // Reb un ACK des de l'esclau
SDAsortida(); // Posa SDA com a sortida
EnvByteI2C(AdreMem); // Adreça a enviar
SDAentrada(); // Posa SDA com a entrada
ACK_S(); // Reb un ACK des de l'esclau
SDAsortida(); // Posa SDA com a sortida
StartI2C(); // Envia el bit d'inici I2C
EnvByteI2C(AdreI2C+1); // Enviem l'adreça del dispositiu
// Amb un 1 al final per indicar lectura
SDAentrada(); // Posa SDA com a entrada
ACK_S(); // Reb un ACK des de l'esclau
Rebut = RebByteI2C(); // Rep el byte
SDAsortida(); // Posa SDA com a sortida
NACK_M(); // Envia un NACK a l'esclau
StopI2C(); // Envia el bit d'aturada I2C
return Rebut; // Retorna el valor
}
void EscriuI2C(char AdreMem, char Dades) {
SDAsortida(); // Posa SDA com a sortida
StartI2C(); // Envia el bit d'inici I2C
EnvByteI2C(AdreI2C); // Enviem l'adreça del dispositiu
// Amb un zero al final per indicar escriptura
SDAentrada(); // Posa SDA com a entrada
ACK_S(); // Reb un ACK des de l'esclau
SDAsortida(); // Posa SDA com a sortida
EnvByteI2C(AdreMem); // Adreça a enviar
SDAentrada(); // Posa SDA com a entrada
ACK_S(); // Reb un ACK des de l'esclau
SDAsortida(); // Posa SDA com a sortida
EnvByteI2C(Dades); // Dades a enviar
SDAentrada(); // Posa SDA com a entrada
ACK_S(); // Reb un ACK des de l'esclau
SDAsortida(); // Posa SDA com a sortida
StopI2C(); // Envia el bit d'aturada I2C
}
void SDAentrada() {
TRISCbits.TRISC7 = 1; // Posem SDA com a entrada
}
void SDAsortida() {
TRISCbits.TRISC7 = 0; // Posem SDA com a sortida
}
void StartI2C() {
Port = Port | 0b11000000; // Abans de començar, SDA ha d'estar activat
// i SCL també
PORTC = Port;
__delay_us(2); // Allarguem el pols
Port = Port & 0b01111111; // Bit d'inici, posem SDA a zero
PORTC = Port;
__delay_us(2); // Allarguem el pols
Port = Port & 0b10111111; // Fi del bit d'inici, posem SCL a zero
PORTC = Port;
}
void StopI2C() {
Port = Port & 0b01111111; // Desactivem SDA
Port = Port | 0b01000000; // i activem SCL
PORTC = Port;
__delay_us(2); // Allarguem el pols
Port = Port | 0b10000000; // Posem SDA a 1
PORTC = Port;
}
void ACK_S() {
Port = Port | 0b01000000; // Posem SCL a 1
PORTC = Port;
__delay_us(2); // Allarguem el pols
Port = Port & 0b10111111; // Posem SCL a zero
PORTC = Port;
Port = Port | 0b10000000; // Posem SDA a 1
PORTC = Port;
}
void NACK_M() {
Port = Port | 0b10000000; // Posem SDA a 1
PORTC = Port;
Port = Port | 0b01000000; // Posem SCL a 1
PORTC = Port;
__delay_us(2); // Allarguem el pols
Port = Port & 0b10111111; // Posem SCL a zero
PORTC = Port;
}
void EnvByteI2C(char Buffer) {
char Temp; // Variable Local
for (int k = 1; k < 9; k++){
Port = Port & 0b10111111; // Posem SCL a zero per modificar SDA
PORTC = Port;
Temp = Buffer & 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 & 0b01111111; // Desactivem SDA
} else { // Si val 128
Port = Port | 0b10000000; // Posem SDA a 1
}
Buffer = Buffer << 1; // Rodem els bits per situar el següent
PORTC = Port;
Port = Port | 0b01000000; // Activem SCL perquè el receptor llegeixi el bit
PORTC = Port;
}
Port = Port & 0b10111111; // Posem SCL a zero per modificar SDA
PORTC = Port;
}
char RebByteI2C() {
char Buffer; // Valor rebut
Port = Port & 0b10111111; // Posem SCL a zero
PORTC = Port;
for (int k = 1; k < 9; k++){
Port = Port | 0b01000000; // Posem SCL a 1
PORTC = Port;
Buffer = Buffer << 1; // Rodem els bits per situar el següent
// a la dreta hi quedarà un zero
if (RC7 == 1) {
Buffer = Buffer | 0b00000001; // Si SDA està activat, posem un 1
}
Port = Port & 0b10111111; // Posem SCL a zero
PORTC = Port;
}
return Buffer; // Retorna el valor
}
void EnviaL(char Caracter) {
TXREG = Caracter; // Agafa el caràcter i l'envia
_delay(5); // Donem temps
while (PIR1bits.TXIF == 0); // Esperem a que s'acabi d'enviar
; // No fem res
}
void EnviaBCD2(char Caracter) {
char Temp; // Variable Local
Temp = Caracter & 0b11110000; // Agafem el primer dígit
Temp = Temp >> 4; // Rodem els bits per situar-los a la dreta
Temp = Temp + '0'; // Ho convertim a ASCII
EnviaL(Temp); // Envia el primer dígit
Temp = Caracter & 0b00001111; // Agafem el segon dígit
Temp = Temp + '0'; // Ho convertim a ASCII
EnviaL(Temp); // Envia el segon dígit
}
void EnviaBCD1(char Caracter) {
char Temp; // Variable Local
Temp = Caracter & 0b00001111; // Agafem el segon dígit
Temp = Temp + '0'; // Ho convertim a ASCII
EnviaL(Temp); // Envia el segon dígit
}
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 Increment(char AdreMem, char Dades){
char Dreta; // Variable Local
char Esquerra; // variable Local
char Decimal; // Variable Local
Dades = ++Dades;
// Conversió a decimal
Esquerra = Dades/16; // Xifra esquerra
Dreta=Dades%16; // Xifra Dreta
Decimal = Esquerra*10 + Dreta;
if (Dreta > 9){
Esquerra = ++Esquerra;
Dreta = 0;
}
if (AdreMem == 1){
if (Decimal > 59){
Dreta = 0;
Esquerra = 0;
}
}
if (AdreMem == 2){
if (Decimal > 23){
Dreta = 0;
Esquerra = 0;
}
}
if (AdreMem == 3){
if (Decimal > 7){
Dreta = 1;
Esquerra = 0;
}
}
if (AdreMem == 4){
char Mes; // Variable Local
char DecimalM; // Variable Local
char EsquerraM;
char DretaM;
Mes = LlegirI2C(5);
EsquerraM = Mes/16;
DretaM = Mes%16;
DecimalM = EsquerraM*10 + DretaM;
if (DecimalM%2==0 & DecimalM < 7){
if (Decimal > 30){
Dreta = 1;
Esquerra = 0;
}
} else if (DecimalM%2!=0 & DecimalM < 7){
if (Decimal > 31){
Dreta = 1;
Esquerra = 0;
}
} else if (DecimalM%2==0 & DecimalM > 7){
if (Decimal > 31){
Dreta = 1;
Esquerra = 0;
}
} else if (DecimalM%2!=0 & DecimalM > 7){
if (Decimal > 30){
Dreta = 1;
Esquerra = 0;
}
}
}
if (AdreMem == 5){
if (Decimal > 12){
Dreta = 1;
Esquerra = 0;
}
}
if (AdreMem == 6){
if (Decimal > 99){
Dreta = 0;
Esquerra = 0;
}
}
// Alarma
if (AdreMem == 9){
if (Decimal > 59){
Dreta = 0;
Esquerra = 0;
}
}
if (AdreMem == 8){
if (Decimal > 23){
Dreta = 0;
Esquerra = 0;
}
}
if (AdreMem == 10){
if (Decimal > 59){
Dreta = 0;
Esquerra = 0;
}
}
// Conversió a hexadecimal
Dades = Esquerra*16 + Dreta;
EscriuI2C(AdreMem, Dades);
}
void Decrement(char AdreMem, char Dades){
char Dreta; // Variable Local
char Esquerra; // variable Local
char Decimal; // Variable Local
// Conversió a decimal
Esquerra = Dades/16; // Xifra esquerra
Dreta=Dades%16; // Xifra Dreta
if (Dreta == 0){
Dreta = 9;
--Esquerra;
} else {
--Dreta;
}
Decimal = Esquerra*10 + Dreta;
if (AdreMem == 1){
if (Decimal > 59){
Dreta = 9;
Esquerra = 5;
}
}
if (AdreMem == 2){
if (Decimal > 23){
Dreta = 3;
Esquerra = 2;
}
}
if (AdreMem == 3){
if (Decimal == 0){
Dreta = 7;
Esquerra = 0;
}
}
if (AdreMem == 4){
char Mes; // Variable Local
char DecimalM; // Variable Local
char EsquerraM;
char DretaM;
Mes = LlegirI2C(5);
EsquerraM = Mes/16;
DretaM = Mes%16;
DecimalM = EsquerraM*10 + DretaM;
if (DecimalM%2==0 & DecimalM < 7){
if (Decimal == 0){
Dreta = 0;
Esquerra = 3;
}
} else if (DecimalM%2!=0 & DecimalM < 7){
if (Decimal == 0){
Dreta = 1;
Esquerra = 3;
}
} else if (DecimalM%2==0 & DecimalM > 7){
if (Decimal == 0){
Dreta = 1;
Esquerra = 3;
}
} else if (DecimalM%2!=0 & DecimalM > 7){
if (Decimal == 0){
Dreta = 0;
Esquerra = 3;
}
}
}
if (AdreMem == 5){
if (Decimal == 0){
Dreta = 2;
Esquerra = 1;
}
}
if (AdreMem == 6){
if (Decimal > 99){
Dreta = 9;
Esquerra = 9;
}
}
// Alarma
if (AdreMem == 9){
if (Decimal > 59){
Dreta = 9;
Esquerra = 5;
}
}
if (AdreMem == 8){
if (Decimal > 23){
Dreta = 3;
Esquerra = 2;
}
}
if (AdreMem == 10){
if (Decimal > 59){
Dreta = 9;
Esquerra = 5;
}
}
// Conversió a hexadecimal
Dades = Esquerra*16 + Dreta;
EscriuI2C(AdreMem, Dades);
}
void Esborra(void) {
EnviaL(254); // Caràcter de control
EnviaL(1); // Esborra la pantalla i posa el cursor a l'inici
}
// 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(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 Mod(char AdreMem){
EnviaL(' ');
EnviaL(' ');
EnviaL(' ');
EnviaL(' ');
if (AdreMem == 1){
EnviaL('m');
EnviaL('i');
EnviaL('n');
}
if (AdreMem == 2){
EnviaL('h');
EnviaL('o');
EnviaL('r');
}
if (AdreMem == 3){
EnviaL('d');
EnviaL('i');
EnviaL('a');
}
if (AdreMem == 4){
EnviaL('D');
EnviaL('I');
EnviaL('A');
}
if (AdreMem == 5){
EnviaL('M');
EnviaL('E');
EnviaL('S');
}
if (AdreMem == 6){
EnviaL('A');
EnviaL('N');
EnviaL('Y');
}
if (AdreMem == 8){
EnviaL(' ');
EnviaL(' ');
EnviaL(' ');
EnviaL('h');
EnviaL('o');
EnviaL('r');
}
if (AdreMem == 9){
EnviaL(' ');
EnviaL(' ');
EnviaL(' ');
EnviaL('m');
EnviaL('i');
EnviaL('n');
}
if (AdreMem == 10){
EnviaL(' ');
EnviaL(' ');
EnviaL(' ');
EnviaL('d');
EnviaL('u');
EnviaL('r');
}
if (AdreMem == 11){
EnviaL(' ');
EnviaL(' ');
EnviaL(' ');
}
}
void Alarma(void){
char Polsad2;
char sortir=1;
char Lektura;
Esborra();
while(sortir==1){
__delay_ms(200);
Polsad2=Polsador();
Posicio = 0; // La primera columna de la primera fila 1
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
Lektura = LlegirI2C(8); // Hores
EnviaBCD2(Lektura); // Mostrem a la pantalla el valor
EnviaL('.'); // Separador
Lektura = LlegirI2C(9); // Minuts
EnviaBCD2(Lektura); // Mostrem a la pantalla el valor
Mod(Adresa);
Posicio = 64;
Posicio = Posicio + 128 ;
EnviaL(254);
EnviaL(Posicio);
EnviaL('D');
EnviaL('u');
EnviaL('r');
EnviaL(':');
Lektura = LlegirI2C(10);
EnviaBCD2(Lektura);
if (Polsad2 == 1) { // Si s'ha premut el polsador 1
if (Adresa < 10){
Adresa = ++Adresa;
} else {
Adresa = 8;
}
}
if (Polsad2==2){ // Si s'ha premut el polsador 2
char Lektura;
Lektura = LlegirI2C(Adresa);
Decrement(Adresa,Lektura);
}
if (Polsad2==3){ // Si s'ha premut el polsador 3
char Lektura;
Lektura = LlegirI2C(Adresa);
Increment(Adresa,Lektura);
}
if (Polsad2==5){ // Si s'ha premut el polsador 5
sortir=0;
}
}
}

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