Cómo controlar la interrupción usando el temporizador en el microcontrolador

1

Hola, estoy usando el microcontrolador 8051. Tengo un medidor de agua digital que proporciona datos binarios del tipo 0 1 0 1. Lo adjunté con 8051 INT1 para que pueda recibir interrupciones. Ahora, cuando el agua fluya a través del medidor, comenzará a enviar interrupciones (impulsos de 0101) a 8051 INT1. Ahora quiero contar los pulsos totales y enviarlos.

Para eso estoy usando este programa en Kiel en lenguaje C: [2do Actualizado]

#include<reg51.h> // include at89x51 . h
#include<stdio.h>// include stdio . h
#include<stdlib.h>// include stdlib . h

unsigned long  value,x;
unsigned long check;
unsigned long time_overflow_count=0;
void initialize_GSM_modem(void);
void initialize_serialcommunication(void);
unsigned char Command_CMGF[]="AT+CMGF=1\r"; 
// AT+CMGF for selecting Text Mode
unsigned char CtrlZ=0x1A;                   
// CTRL+Z for sedning SMS after the message has been entered
unsigned char Command_CMGS[]="AT+CMGS=\"+9xxxxxxxxx\"\r"; 
// recepient mobile number
unsigned char Command_AT[]="AT\r";
unsigned char msg02[]="Hello!";

unsigned char buf[10]={0};


void send(void)interrupt 1
{
time_overflow_count=time_overflow_count+1;
if (time_overflow_count==5){
if(value==x){

sprintf((char*)buf, "R %lu", value);

time_overflow_count=0;

initialize_GSM_modem();
value=0;
}
}
TR0=1;
}

void input_counting(void) interrupt 2
{
TR0=0;
TL0=0x00;
TH0=0x00;

value=value+1;
TR0=1;

}


void main (void) {

TMOD = 0x21;
TH1 = 0xFD;
TL0=0x55;
TH0=0x55;
SCON = 0x50;
TR1=1;
EX1=1;///Enable external intrrupt 1
EA=1;
IE1=1;
IT1=1;
PX1=1;
ET0=1;

TI=1;
while(1)
{
x=value;
}
}

void delay(void){
unsigned int i;
for(i=0;i<50;i++);
}


 void delay2(void){
unsigned long i;
for(i=0;i<15000;i++);
}

 void initialize_GSM_modem(void)
 {
 delay2();
puts(Command_CMGS);
delay2();
puts((char *)buf);
delay2();

while(!TI); TI = 0;SBUF = 0x1A;
 }

* Actualizado: * Por lo tanto, al usar esto estoy tratando de obtener una interrupción del temporizador que verifica cuando no hay pulsos durante algún intervalo de tiempo, luego se supone que el flujo del medidor está completo y envía el mensaje.

Pero hay un error: no sé por qué, pero nuestro programa continúa enviando mensajes continuos varias veces, incluso si no inicio el contador de agua. Si inicio el contador de agua, envía el valor total en la parada y, si no lo hago, sigue enviando 0 a intervalos regulares

Lo que quiero es que espere a que fluya el agua (o se interrumpa para comenzar) y luego verifique el último valor y lo envíe solo una vez.

La próxima vez que inicie el medidor, debería esperar y enviar el valor nuevamente, pero no debería seguir enviando 0s a intervalos regulares.

ACTUALIZACIÓN : he actualizado el código y está funcionando bien, pero no funciona como deseo

Por favor, sugiere

Gracias

    
pregunta TheBond

2 respuestas

2

Parece que su defecto arquitectónico subyacente es que tiene la recepción de impulsos acoplados al envío de la información de caudal o agua acumulada. Además, asegúrese de que este medidor de agua ya produzca pulsos digitales limpios, o que rebote la señal en caso de que se trate de un interruptor mecánico.

En el caso más general en el que tiene que rebotar los pulsos de agua, no interrumpa los pulsos en absoluto. Interrumpir regularmente desde un temporizador. Esto debe ser un mínimo de 10 veces más rápido que los pulsos a la velocidad de flujo máxima. La rutina de interrupción requerirá un número mínimo de estados alto o bajo consecutivos antes de considerar que la señal de rebote ha cambiado al nuevo estado. Una vez que eso sucede, se incrementa un contador. Los microcontroladores son mucho más rápidos que los medidores de agua, especialmente los mecánicos, por lo que la interrupción lo suficientemente rápida no debería ser un problema. Por lo general, una interrupción de 1 ms es suficiente para esto, y luego puede usarla para otros tiempos del sistema.

Ahora puede enviar periódicamente el valor del contador o cualquier delta acumulado en forma sincrónica. Para evitar la disputa sobre el contador con la rutina de interrupción, el contador de los incrementos de la rutina de interrupción puede ser de un solo byte. El código de primer plano mantiene su propia copia del último valor conocido de ese byte. Lee periódicamente el contador de la rutina de interrupción, lo compara con el último valor conocido, procesa cualquier marca nueva que represente la diferencia y luego actualiza el último valor conocido. Mientras la rutina de primer plano haga esto con la frecuencia suficiente para que el contador de un solo byte no pueda ajustarse entre las muestras, no se perderán datos.

El código de primer plano puede decidir cuándo enviar la información. Esto puede basarse en una marca de tiempo y / o cuando hay nueva información para enviar.

    
respondido por el Olin Lathrop
0

Bueno, aquí hay una buena:

Configure un temporizador para interrumpir cada uno, digamos 10 segundos si puede. Cuando inicie su programa, inicie el temporizador.

Cada vez que ingresa a la función input_counting, detenga el temporizador y borre su cuenta de nuevo a 0 (o al valor del período si se interrumpe cuando llega a cero, si cuenta hacia atrás, es decir). Luego, justo antes de dejar la interrupción, vuelva a habilitar el temporizador.

El tiempo siempre está contando, pero cada vez que recibes un pulso y tu interrupción se ejecuta, se reinicia el temporizador. El temporizador solo generará una interrupción cuando no haya pulsos durante 10 segundos (o lo que sea que establezca el período del temporizador).

Entonces, en el controlador de interrupciones para el temporizador, simplemente transmita el valor nuevamente y luego deshabilite el temporizador. Deberias hacer eso.

    
respondido por el AngryEE

Lea otras preguntas en las etiquetas