Usar TMR0 para programar un evento

0

Estoy tratando de usar TMR0 en un PIC18F2420 para cronometrar la apertura de un dispositivo y mostrar el porcentaje que está abierto. el problema que tengo es que se ha congelado casi todas las demás operaciones. No estoy muy seguro de dónde me equivoqué. Si alguien pudiera ayudar, lo apreciaría enormemente. Tengo mi reloj interno configurado para 4MHz y Tmr2 está siguiendo la pista en una interrupción externa.

mi código principal en los conjuntos de configuración     GIE = 1;     GIEL = 1;

y mi rutina que estoy rastreando conjuntos TMR0ON = 1;

void int (void)

{
RCONbits.IPEN=1;    
INTCON2bits.RBPU=0;
INTCONbits.INT0IE=1;
INTCON3bits.INT1IE=1;

INTCON3bits.INT1IP=1;

INTCON2bits.INTEDG0=0; //interrupt at falling edge
INTCON2bits.INTEDG1=0;
GIE=1;   // Global interrupt enable
INTCON2bits.TMR0IP=0;
INTCON2bits.RBIP=0;
INTCONbits.TMR0IE =1;
INTCON2bits.TMR0IP = 0;
}

//========================================================================
void Counter(void)
{

Timer0count=0;
TMR0ON=0;
TMR0=0x00;
//PR2=0xFF;
T0CON=0xD0;
TMR0IF=0;
TMR0IE=1;
TMR0IP=0;
TMR0ON=0;

}
//========================================================================
void Counter1(void)
{

//  Timer0count=0;
TMR0ON=0;
TMR0=0x00;
//  PR2=0xFF;
T0CON=0xD0;
TMR0IF=0;
TMR0IE=1;
TMR0IP=0;
TMR0ON=1;

}
//========================================================================
#pragma interrupt_level 0
void interrupt low_priority lowISR()
{
if(TMR0IE && TMR0IF)
{
    if((Timer0count) >= 16)  //915 is a count for a minute
    {

        TMR0IF=0;
        TMR0IE=0;   
        TMR0=0x00;  
        Timer0count=0;
        TMR0ON=0;
        percent++;
    }
    else
    {       
        TMR0IF=0;
        TMR0IE=1;   
        TMR0=0x00;  
        Timer0count++;          
    }
Counter1();
}
}
    
pregunta Chris

2 respuestas

3

Es difícil seguir lo que piensas que se supone que debe hacer tu código, ya que está prácticamente sin comentarios. Además, tu código no funciona, por lo que es irrelevante de todos modos. Retrocedamos y pensemos en cómo atacar mejor este problema.

Aparentemente, desea realizar un seguimiento de cuánto tiempo acumulado gasta una señal digital en cualquiera de los estados. Si esto sucede en el tiempo humano, como lo implica la "apertura" y el "cierre" de algún dispositivo, la verificación periódica está bien. Cada 10 ms debe estar bien, probablemente incluso cada 100 ms. Tenga en cuenta que el período de muestreo real no importa, siempre que sea regular y lo suficientemente rápido, ya que en última instancia solo le importa la proporción de tiempo abierto a cerrado. Las muestras por unidad de tiempo se cancelan.

El temporizador 2 con su registro de período incorporado es bueno para configurar una interrupción periódica. En esta interrupción, todo lo que hace es incrementar uno de los dos contadores dependiendo de si el dispositivo está abierto o cerrado. Probablemente estos tengan que ser contadores amplios, como 32 bits cada uno.

Cuando se le solicita la fracción del tiempo de apertura de la tapa, el código del primer plano toma una instantánea de los dos contadores y hace la división.

Cuando toma las instantáneas, debe asegurarse de que está obteniendo un valor consistente, ya que podría producirse una interrupción y cambiar las cosas entre la lectura de los bytes individuales del valor. Hay dos formas habituales de solucionar esto: deshabilite las interrupciones durante los pocos ciclos que se requieren para copiar cada valor, o después de leer el valor, verifíquelo nuevamente y vuelva a intentarlo si ha cambiado.

    
respondido por el Olin Lathrop
1

Es probable que tengas demasiadas "cosas" dentro del controlador de interrupciones.

Ciertamente hay alguna duplicación, por ejemplo, tienes "TMR0IF = 0;" tanto en su if / else como en su función "Counter1" a la que llama inmediatamente después de if / else.

Dependiendo de las capacidades de optimización de su compilador, también podría considerar no realizar llamadas a funciones desde dentro de su controlador de interrupciones para ahorrar en un par de instrucciones para la llamada / devolución de funciones y quizás algo de administración de pila.

También puede aumentar la configuración del preescalador que ha asignado a TMR0 para que se desborde e interrumpa con menos frecuencia (pero, obviamente, esto se debe a sus cálculos de medición).

    
respondido por el brhans

Lea otras preguntas en las etiquetas