En aquest cas el dispositiu mesura el corrent i en mostra el valor eficaç a la pantalla. A més, permet indicar-li quan l'aparell està en mode de repòs, prement el polsador 0, i llavors l'aparell informarà a l'usuari de quan l'aparell està en mode de repòs i quan no ho està; això s'indica amb els LED.
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 #include <math.h> #define _XTAL_FREQ 4000000 // La freqüència del rellotge és 4 MHz #define numEsp 2 #define clrbit(var, bit) ((var) &= ~(1 << (bit))) #define flipbit(var, bit) ((var) ^= (1<<(bit)))
unsigned int refer, mesura;
int Valor;
char port; // Variable auxiliar del port C
char control; // Variable de control de la funció TocaNota
// Si és 0 nota, si és 1 silenci
int bucles; // Comptador d'iteracions de la nota
int silenci; // Durada del silenci
unsigned int suma = 0;
float mitjana, RMS;
unsigned char compta = 0;
char Digits[5]; // Variable amb el número dígit a dígit
// Digits[0] són les unitats
int Comp_val = 30;
int Avis = 0;
char caracter;
// Definició de les funcions que farem servir void Esborra(void); // Esborra la pantalla i posa el cursor a l'inici void EnviaL(char Caracter); // Envia un caràcter void TocaNota(char valPre, char valPos, char valPR2, int numbuc, int numsil); float TractaInput(unsigned int suma, unsigned int compta);
void main (void) {
// Configuració d'entrades i sortides
TRISC = 0b11010000; // Posa els bits 0 a 3 (els LEDs: RC0, RC1, RC2, RC3) del port C com a sortida (0),
// tambe el bit 5 (el brunzidor: RC5) del port C ha d'estar com a sortida (0),
// i els altres quatre com a entrada (1)
PORTC = 0;
TRISA = 0xFF; // Tot el port A és d'entrada
__delay_ms(2000); // Esperem que arrenqui la pantalla
// Configuració de la comunicació amb la pantalla
BRGH = 1; // Configuració de velocitat
BRG16 = 0; // Paràmetre de velocitat de 8 bits
SPBRG = 25; // Velocitat de 9600 baud
SYNC = 0; // Comunicació asíncrona
TX9 = 0; // Comunicació de 8 bits
SPEN = 1; // Activa comunicació sèrie
TXEN = 1; // Activa comunicació
// Entrades analògiques
ANSEL = 0b00000000; // Desactiva totes les entrades analògiques
ANSELH = 0b00000011; // I activa AN8 i AN9
ADCON1 = 0b00010000; // Posa el conversor a 1/8 de la freqüència
// Configuració d'interrupció
INTCON = 0b11000000; // Habilitem la interrupció per PIE
// i deshabilitem les altres
PIE1 = 0b00000001; // Activa la interrupció per Timer 1
// Configuració del Timer 1
TMR1IF = 0; // Aquest bit es posarà a 1 quan el temporitzador acabi
// cal desactivar-lo des del programa
TMR1H = 253; // Inicialitza el Timer1
TMR1L = 143;
T1CON = 0b00000000; // Configuració de Timer1
// 00 - Factor d'escala de 1
// I el posem en marxa
GIE = 1; // Habilitem les interrupcions a nivell general
while (1){ // Inici del bucle de programa
// guarda el valor actual (Amp) i sera el que fara de comparacio maxima a partir d'ara
if (PORTAbits.RA3 == 0) {
Comp_val = RMS;
}
if(compta == 32){ // Quan ja tenim totes les mesures
Esborra(); // Posició a la pantalla
RMS = TractaInput(suma, compta); // I el valor eficaç
Valor = (int)round(RMS);
//Pantalla surt un 10. valor es els digits mostrats a la pantalla en format enter (no ascii encara)
if (RMS >= 10 && RMS > Comp_val && Avis == 0){ //12 per tenir marge
//PINTEM VERD (no repos)
PORTC = 0b00001100; //Encen RC0, RC1
Avis = 1;
TocaNota(0, 7, 239, 105, 105); // Valor que correspon aproximadament a do3
} else if (RMS <= Comp_val){
//Pintem vermell (repos)
PORTC = 0b00000011; //Encen RC2, RC3
if (Avis == 1) {
TocaNota(0, 5, 253, 132, 132); // Valor que correspon aproximadament a mi3
Avis = 0;
}
}
// Preparem per mostrar el valor
// Descomposem en dígits
for (signed char j = 0; j < 5; j++){ // 5 dígits
Digits[j] = Valor % 10 + '0';
Valor = Valor / 10;
}
// Eliminem zeros a l'esquerra
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') { // Mirem si el segon dígit és 0
Digits[3] = ' '; // Si ho és, hi posem un espai
}
}
// Enviem a la pantalla
for (signed char j = 4; j >= 0; j--){ // 5 dígits
if(j == 1){
EnviaL(','); // Coma
}
EnviaL(Digits[j]); // Número
}
// Afegim les unitats
EnviaL(' '); // Espai
EnviaL('A');
compta = 0;
suma = 0;
}
if(compta == 0){ // Preparem una sèrie de mesures
// Llegim el valor de referència
ADCON0 = 0b10100001; // Activa el conversor connectat a AN8
// amb el resultat justificat per la dreta
GO_DONE = 1; // Posa en marxa el conversor
while (GO_DONE == 1) // Mentre no acabi
; // ens esperem
// Descartem la primera lectura
GO_DONE = 1; // Posa en marxa el conversor
while (GO_DONE == 1) // Mentre no acabi
; // ens esperem
refer = ADRESH << 8 | ADRESL;
// Preparem per a les lectures
ADCON0 = 0b10100101; // Activa el conversor connectat a AN9
// amb el resultat justificat per la dreta
GO_DONE = 1; // Posa en marxa el conversor
while (GO_DONE == 1) // Mentre no acabi
; // ens esperem
// Descartem la primera lectura
__delay_ms(1000); // Esperem un segon
TMR1H = 253; // Inicialitza el Timer1
TMR1L = 143;
TMR1ON = 1; // Posa en marxa el temporitzador, per començar les mesures
}
}
}
void __interrupt() temporit(void){
// No desactivem les interrupcions perquè només en tenim una que dura poc
if(TMR1IF){ // Comprovem que hi ha interrupció per Timer 1
TMR1ON = 0; // Aturem el Timer
TMR1H = 253; // Inicialitza el Timer1
TMR1L = 143;
TMR1ON = 1; // El tornem a engegar
TMR1IF = 0; // Tornem a posar el bit a zero
// Anem a llegir el corrent
GO_DONE = 1; // Posa en marxa el conversor
while (GO_DONE == 1) // Mentre no acabi
; // ens esperem
mesura = ADRESH << 8 | ADRESL;
if(mesura < refer){
suma = (suma + refer) - mesura; // Ho sumem
} else {
suma = (suma + mesura) - refer; // Ho sumem
}
compta++;
}
if(compta == 32){
TMR1ON = 0; // Aturem les lectures
}
if (PIR1bits.TMR2IF) { // Comprovem que hi ha interrupció per Timer2
PIR1bits.TMR2IF = 0; // Desactiva el bit que indica interrupció pel Timer2
if (control == 0){ // Si estem tocant una nota
flipbit(port, 5); // Inverteix la sortida del brunzidor
PORTC = PORTC ^ port; // Ho copia al port C
}
bucles--; // Comptador per a la durada de la nota
if (bucles == 0){ // Si és zero, ja ha passat la durada de la nota
if ((control == 1) || (silenci == 0)){ // Si s'acaba el silenci
T2CONbits.TMR2ON = 0; // Desactiva el Timer2
PIE1bits.TMR2IE = 0; // Desactiva les interrupcions per Timer2
}
if (control == 0){ // Si estem tocant una nota
clrbit(port, 5); // A l'acabar, deixa la sortida desactivada (es passa el RC5 a 0)
PORTC = PORTC ^ port; // Ho copia al port C (ara es 0, o LOW VOLTAGE, i apaga el brunzidor)
if (silenci > 0){ // Si es preveu silenci
bucles = silenci; // Agafem la durada del silenci
control = 1; // Toca silenci
}
}
}
}
}
void EnviaL(char Caracter){
TXREG = Caracter; // Agafa el caràcter i l'envia
__delay_ms(1); // Donem temps
while (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 TocaNota(char valPre, char valPos, char valPR2, int numbuc, int numsil) {
// Funció per tocar una nota
while(T2CONbits.TMR2ON) // Si està tocant una nota
; // Esperem que acabi
valPos &= 0b00001111; // Per precaució, posem a zero els bits no emprats
valPre &= 0b00000011; // Per precaució, posem a zero els bits no emprats
T2CON = ((valPos<<3) | valPre); // Ho posa a la configuració del temporitzador
PR2 = valPR2; // Preselecció del Timer2
bucles = numbuc; // Comptador d'iteracions
silenci = numsil; // Durada del silenci
control = 0; // Comencem tocant la nota
PIE1bits.TMR2IE = 1; // Activem les interrupcions per Timer2
T2CONbits.TMR2ON = 1; // Activem el Timer2
}
float TractaInput(unsigned int suma, unsigned int compta){
mitjana = (float)suma / compta; // Calculem la mitjana
return ((30 / numEsp) * 5 * 100 * 1.1107 * mitjana / 1023.0);
}

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