El programa del grup 5 a més de mostrar la temperatura i la humitat, permet programar uns llindars d'alarma. També té un mode d'espera que deixa el microcontrolador en repòs.
El programa d'aquest grup é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 <string.h> // LA NECESSITEM A LA FUNCIO EnviaSTR()) #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 Sens RA5 // Li assigna un nom a l'adreça del sensor
unsigned char Visualit; // Variable on guardem el que mostrara la pantalla char Bloqueig; // variables per modo espera // Variable que farà el bloqueig del programa // Si no val 0 es bloqueja unsigned int Valor; // Variable de treball unsigned int Valormodi; unsigned int Valormodi2; unsigned int Error; // Error de lectura unsigned int Lectura[3]; // Valor llegit // Lectura[0] és la suma de comprovació // Lectura[1] és la temperatura // Lectura[2] és la humitat int p; char Digits[5]; // Vector amb el número dígit a dígit // Digits[0] és el decimal char Fahrenheit; char Negatiu; // Guarda si el valor de la temperatura és negatiu o positiu char Modi; char Modi2; char eshumitat; char alarma;
// Definició de les funcions que farem servir char Sensor(void); // Lectura del sensor. dona 0 si la suma de control és correcta void EnviaL(char Caracter); // Envia un caràcter void EnviaSTR(char cadena[]); void Esborra(void); // Esborra la pantalla i posa el cursor a l'inici void Cursor(char Filera, char Columna); // Posiciona el cursor (filera 1 a 2 i columna 1 a 32, segons pantalla) char Polsador(void); // Funció de lectura dels polsadors char Polsad; void TocaNota(char ValPR2, char ValCCPR1L, char ValDC1B); void enviavalor(int Valor); void corretextalarma(void);
void main(void) {
Bloqueig = 1; // inicialment esta en repos
TRISC = 0b00100000; // Definim com volem les E/S del port C
TRISB = 0; // tot el port b es de sortida
ANSELH = 0; // Desactiva les altres entrades analògiques
ANSEL = 0b00000101; // Configura AN0 i AN2 com entrada analògica
TRISA = 0xFF; // Tot el port A és d'entrada
ADCON1 = 0b00010000; // Posa el conversor a 1/8 de la freqüència
ADCON0 = 0b00001001; // Activa el conversor A/D connectat a AN2
Fahrenheit = 0; // celsius*1.8+32
Modi = 0;
Modi2 = 0;
Valormodi = 300;
Valormodi2 = 100;
alarma = 0;
p = 0;
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
PORTA = 0b00100000; // RA5 a 1
T1CON = 0b00100001; // Configuració de Timer1
// Com a temporitzador basat en rellotge
// 10 - Factor d'escala de 4
// TMR1L s'incrementarà cada 2 us
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ó
OPTION_REG = 0b11000000; // interrupcio a l'activacio
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) { // Inici del bucle de programa
Polsad = Polsador();
if (Modi == 1) {
p = 0;
PORTC = 0b00000110;
if (RA3 == 0) {
TocaNota(212, 106, 2);
Modi2 = ~Modi2;
}
Esborra();
if (Modi2 == 0) {
EnviaSTR("Tmax-> ");
Cursor(2, 0);
EnviaSTR("Tmin : ");
if (Polsad == 5) { // Sumar
Valormodi++;
}
if (Polsad == 4) { // Restar
Valormodi--;
}
if (Polsad == 3) {
Valormodi = Valormodi + 10;
}
if (Polsad == 2) { //Restar
Valormodi = Valormodi - 10;
}
}
if (Modi2 == 1) {
EnviaSTR("Tmax : ");
Cursor(2, 0);
EnviaSTR("Tmin-> ");
if (Polsad == 5) { // Sumar
Valormodi2++;
}
if (Polsad == 4) { // Restar
Valormodi2--;
}
if (Polsad == 3) {
Valormodi2 = Valormodi2 + 10;
}
if (Polsad == 2) { // Restar
Valormodi2 = Valormodi2 - 10;
}
}
eshumitat = 0;
Valor = Valormodi;
Cursor(0, 7); // Posició
enviavalor(Valor);
Valor = Valormodi2;
Cursor(2, 7); // Posició
enviavalor(Valor);
Cursor(0, 16);
if (Valormodi < Valormodi2) {
EnviaL('!');
PORTC = 0b00001111;
}
Cursor(2, 16);
if (Valormodi < Valormodi2) {
EnviaL('!');
PORTC = 0b00001111;
}
__delay_ms(200);
if (Polsad == 1) {
Modi = 0;
alarma = 1;
}
}
if (Modi == 0) {
OSCCON = 0b01111000; // IRCF = 111, rellotge a 8 MHz
Error = Sensor();
OSCCON = 0b01101000; // IRCF = 111, rellotge a 8 MHz
if (RA3 == 0) {
Bloqueig = 1;
}
if (Bloqueig == 1) {
Esborra(); // esborra la pantalla i posa el cursor en (0,0)
// MISSATGE BLOQUEIG
p = 0;
EnviaSTR("PRESS BTN1");
__delay_ms(100);
INTCON = 0b00010000;
PORTC = 0b00000000; // PORT C(LEDS)APAGAT
ANSEL = 0; // desactiva entrades analogiques
ANSELH = 0; // Desactiva les altres entrades analògiques
SLEEP();
ANSEL = 0b00000101; // Configura AN0 i AN2 com entrada analògica
Bloqueig = 0;
PORTC = 0b00000100;
TocaNota(238, 119, 2); // Valor que correspon aproximadament a do3
}
// AQUI POSAR COSES FORA DEL BLOQUEIG
if (Polsad == 1) {
TocaNota(212, 106, 2);
PORTC = 0b000000110;
alarma = 1;
p = 0;
}
if (Polsad == 3) {
TocaNota(212, 106, 2);
PORTC = 0b000000100;
alarma = 0;
}
if (Polsad == 4) {
Fahrenheit = 0;
TocaNota(212, 106, 2); // Valor que correspon aproximadament a re3
Valormodi = 300;
Valormodi2 = 100;
}
if (Polsad == 5) {
Fahrenheit = 1;
TocaNota(212, 106, 2); // Valor que correspon aproximadament a re3
Valormodi = (300 * 1.8 + 320);
Valormodi2 = (100 * 1.8 + 320);
}
if (Error == 0) { // Llegeix el sensor i si és correcte segueix
// Enviem la humitat
Valor = Lectura[2]; // Humitat
Esborra();
Cursor(2, 0); // Posició
EnviaL('H');
Cursor(2, 2);
eshumitat = 1;
enviavalor(Valor);
// Enviem Temperatura
Valor = Lectura[1]; // Temperatura
if (Valor >= 32768) { // Si el bit més significatiu està activat és negatiu
Negatiu = 1; // És negatiu
Valor = Valor - 32768; // Agafem el valor absolut
} else {
Negatiu = 0; // És positiu
}
if (Fahrenheit == 1) {
Valor = (Valor * 1.8 + 320);
}
Cursor(0, 0); // Posició
EnviaL('T');
Cursor(0, 2);
eshumitat = 0;
enviavalor(Valor);
if (Valormodi < Valor) {
if (alarma == 1) {
TocaNota(212, 106, 2); // Valor que correspon aproximadament a re3
corretextalarma();
}
}
if (Valormodi2 > Valor) {
if (alarma == 1) {
TocaNota(400, 63, 2);
TocaNota(400, 63, 2);
TocaNota(400, 63, 2);
corretextalarma();
}
}
Cursor(0, 0); // Posició
if (Polsad == 2) {
Modi = 1;
}
} else {
Esborra(); // Posició
EnviaSTR("ERROR DE LECTURA error code: ");
Error = Error + '0'; // Passa el valor a ASCII
EnviaL(Error); // Número
}
__delay_ms(500); // Retard d'1 s
}
}
}
char Sensor(void) {
char Bytes[5]; // Vector per a guardar els cinc bytes que envia el sensor
char Temps; // Guarda el valor de TMR1L
for (int j = 0; j < 5; j++) { // 5 bytes
Bytes[j] = 0; // Posem el vector a zero
}
TRISA = 0b11011111; // Tot el port A és d'entrada excepte, de moment, RA5
PORTA = 0b00000000; // RA5 a 0
__delay_ms(2); // Retard de 2 ms
PORTA = 0b00100000; // RA5 a 1
__delay_us(15); // Retard de 15 us
// Un cop activat, esperem la resposta
TRISA = 0b11111111; // Tot el port A és d'entrada, inclosa RA5
// Esperem a rebre el pols d'inici
// Primer un L d'uns 80 us
// Per començar, s'ha de desactivar l'entrada
// i s'ha de reactivar al cap d'entre 70 i 90 us
while (Sens) // S'ha desactivat l'entrada?
; // No, doncs esperem
TMR1H = 0;
TMR1L = 0; // Sí, doncs comencem a comptar el temps
while ((!Sens) && (TMR1L < 45)) // Esperem que s'activi l'entrada
; // O passin més de 90 us
Temps = TMR1L; // Agafa el valor de TMR1L
TMR1H = 0;
TMR1L = 0; // Torna a començar a comptar el temps
if (Temps > 45) { // És més gran
return 1; // Error 1 - L inicial massa llarg
}
if (Temps < 35) { // Mirem que no sigui menor que 70 us
return 2; // Error 2 - L inicial massa curt
}
// L inicial ja està
while (Sens && (TMR1L < 45)) // Esperem a que es desactivi l'entrada
; // O passin més de 90 us
Temps = TMR1L; // Agafa el valor de TMR1L
TMR1H = 0;
TMR1L = 0; // Torna a començar a comptar el temps
if (Temps > 45) { // És més gran
return 3; // Error 3 - H inicial massa llarg
}
if (Temps < 35) { // Mirem que no sigui menor que 70 us
return 4; // Error 4 - H inicial massa curt
}
// H inicial ja està
// Ara hem de rebre els bits
TMR1H = 0;
TMR1L = 0; // Torna a començar a comptar el temps
for (int j = 0; j < 5; j++) { // 5 bytes
for (int k = 0; k < 8; k++) { // 8 bits a cada byte
Bytes[j] = 2 * Bytes[j]; // Rodem a l'esquerra el bit anterior
// per deixar lloc al nou
// Si no n'hi havia cap no canvia res
// ja que estava a zero
// Esperem a rebre un bit
// Primer un L d'uns 80 us
// Ara l'entrada està a zero
// S'ha d'activar al cap d'entre 10 i 90 us
while ((!Sens) && (TMR1L < 45)) // Esperem que s'activi l'entrada
; // O passin més de 90 us
Temps = TMR1L; // Agafa el valor de TMR1L
TMR1H = 0;
TMR1L = 0; // Torna a començar a comptar el temps
if (Temps > 45) { // És més gran
return 5; // Error 5 - Valor L del bit massa llarg
}
if (Temps < 5) { // Mirem que no sigui menor que 10 us
return 6; // Error 6 - Valor L del bit massa curt
}
// Ja tenim el valor L del bit. Ara esperem un H
while (Sens && (TMR1L < 40)) // Esperem a que es desactivi l'entrada
; // O passin més de 80 us
Temps = TMR1L; // Agafa el valor de TMR1L
TMR1H = 0;
TMR1L = 0; // Torna a començar a comptar el temps
if (Temps > 40) { // És més gran
return 7; // Error 7 - Valor H del bit massa llarg
}
if (Temps < 6) { // Mirem que no sigui menor que 12 us
return 8; // Error 8 - Valor H del bit massa curt
}
// Ja hem comprovat que no sigui massa curt ni massa llarg
// Si és més petit que 38 us és un pols curt, o sigui un 0
// Si és curt no cal fer res, el 0 ja hi és
// Si és més gran que 60 us és un pols llarg, o sigui un 1
if (Temps > 19) { // És més gran que 38 us
// Sí, doncs no és un pols curt
if (Temps > 30) { // És més gran que 60 us
// És un pols llarg
Bytes[j] = Bytes[j] + 1; // Entrem un 1
} else {
return 9; // Error 9 - Valor H del bit incorrecte
}
}
}
}
// Ja tenim els 5 bytes. Fem la suma de comprovació
// Cal sumar els quatre primers bytes
// Però sense portar-ne
Valor = 0; // Primer la posem a zero
for (int j = 0; j < 4; j++) { // 4 bytes
Valor = Valor + Bytes[j]; // Sumem un dels quatre elements
if (Valor > 255) { // Mirem si és més gran del que cap a un byte
// Si és més gran, només pot haver activat un bit del segon byte
// el que correspon a 256
Valor = Valor - 256; // Restem les que en portàvem
}
}
if (Valor != Bytes[4]) { // No coincideixen
return 10; // Error 10 - Falla la suma de comprovació
}
Lectura[0] = Bytes[4]; // Suma de comprovació
Lectura[1] = 256 * Bytes[2] + Bytes[3]; // Temperatura
Lectura[2] = 256 * Bytes[0] + Bytes[1]; // Humitat
return 0; // Recepció correcta
}
void EnviaL(char Caracter) {
TXREG = Caracter; // Agafa el caràcter i l'envia
_delay(5); // Donem temps
while (PIR1bits.TXIF == 0) // Esperem que s'acabi d'enviar
; // No fem res
}
void EnviaSTR(char cadena[]) { // PER A QUE FUNCIONI CAL CADENA "string"==> "" I NO ''.
int j;
j = strlen(cadena);
for (int i = 0; i < j; i++) {
if (p + i < 17) {
EnviaL(cadena[i]);
}
}
}
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
}
return Pols;
}
// Funcio que fa sonar sons al 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 enviavalor(int Valor) {
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
for (int j = 0; j < 5; j++) { // 5 dígits
Digits[j] = Digits[j] + '0'; // Li sumem el codi ASCII de 0
} // Això és la temperatura multiplicada per 10
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
} // Els dos darrers zeros els mostrarem sempre
}
}
if (Negatiu) {
Digits[4] = '-'; // Si és negatiu, posem el -
}
for (int j = 4; j > 0; j--) { // 4 dígits (el 5è és el decimal)
EnviaL(Digits[j]); // Número
}
EnviaL(','); // Coma
EnviaL(Digits[0]); // Número
EnviaL(' '); // Espai
if (eshumitat == 0) {
if (Fahrenheit == 0) {
EnviaL(0b11011111); // Graus
EnviaL('C'); // Lletra
}
if (Fahrenheit == 1) {
EnviaL(0b11011111); // Graus
EnviaL('F');
}
} else {
EnviaL('%');
}
}
void corretextalarma(void) {
for (int k = 16; k > 0; k--) {
Esborra(); // Posició
EnviaL('T');
Cursor(0, 2);
eshumitat = 0;
enviavalor(Valor);
Cursor(2, k);
p = k;
if (Valormodi2 > Valor) {
EnviaSTR("Warning: Tmin!");
__delay_ms(100);
}
if (Valormodi < Valor) {
EnviaSTR("Warning: Tmax!");
__delay_ms(100);
}
Polsad = Polsador();
if (Polsad == 3) {
k = 0;
alarma = 0;
PORTC = 0b00000100;
}
}
}

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