Estoy buscando un poco de ayuda y consejo sobre mi código.
Estoy usando C18 en el entorno MPLab, PIC18f4520 con Fosc @ 4MHz, y usando timer0 en modo de 16 bits para contar hasta el desbordamiento, establecer el bit de desbordamiento y el indicador de interrupción, luego saltar a ISR e incrementar un 'conteo' variable. Esto se envía a un puerto con LED conectados para que pueda obtener una confirmación visual del funcionamiento del programa.
Sin embargo, el recuento emitido siempre es '1' (es decir, 0x01) y creo que el ISR solo ocurre una vez, si es que ocurre.
Cualquier ayuda que pueda ofrecer sería muy apreciada.
Aquí está mi código:
void main (void) /* */
{
TRISA = 0; /* */
TRISC = 0; /* */
TRISB = 0;
TRISD = 0x00;
RTOS();
}
void low_interrupt (void)
{
_asm GOTO timer_isr _endasm
}
#pragma code
#pragma interruptlow timer_isr
void timer_isr (void)
{
INTCONbits.TMR0IF = 0;
count = count++;
LATD = count;
RTOS();
}
void RTOS (void)
{
T0CONbits.T08BIT = 0; // 16-bit timer
T0CONbits.T0CS = 0; // increment on instruction cycle input
T0CONbits.T0SE = 0; // increment on low--> high transition of clock
T0CONbits.PSA = 1; // T0 prescaler not assigned i.e. 1:1 prescaler.
RCONbits.IPEN = 1; //Enable Interrupt Priorities
INTCONbits.GIEL = 1; //Enable Low Priority Interrupt
INTCONbits.GIE = 1; //Enable Global Interrupts
INTCONbits.TMR0IE = 1; //Enable Timer0 Interrupt
INTCON2bits.TMR0IP = 0; //TMR0 set to Low Priority Interrupt
INTCONbits.TMR0IF = 0; // T0 int flag bit cleared before starting
T0CONbits.TMR0ON = 1; // timer0 START
while (1);
}
Gracias de antemano por cualquier orientación que pueda ofrecer.
Está llamando a RTOS() en su interrupción y la función RTOS() tiene "while (1);" en él (¿bucle infinito?)
No estoy seguro de por qué restablecería los registros de interrupción completos dentro de su interrupción.
Tener un bucle infinito en su interrupción probablemente hará que su programa no funcione correctamente.
Además, revisa el comentario de Roger Rowland: "¿Dónde está count
definido? ¿Lo has marcado volatile
? – Roger Rowland hace 15 minutos". Este es un error bastante común y también podría ser el punto aquí.
volatile
a su int
, así que volatile int count;
vea si eso hace la diferencia y, en cualquier caso, lea por qué a veces es necesario .while (1);
RTOS() que está en su interrupción. ¡Incluso si restablece el indicador de interrupción, la interrupción no interrumpirá en su rutina de interrupción actual! Por lo tanto, se quedará atascado en el tiempo. Le sugiero que ponga el while(1);
en su principal, o lo borre por completo. `while(1){ //algún código }' a menudo se realiza en main para mantener el programa en ejecución/bucle en ese código. Pero no debe hacer este ciclo en una rutina de servicio de interrupción.void timer_isr (void) { INTCONbits.TMR0IF = 0; count = count++; LATD = count; RTOS(); }
Este es su código de rutina de interrupción. Llama RTOS()
... Y RTOS()
tiene un while(1)
modo de que nunca salga del bucle o ISR (rutina de servicio de interrupción). Entonces sí, la interrupción solo ocurre una vez, como pensabas.while(1);
para que se ejecuten continuamente. . Sin embargo, para ejecutar su código de forma continua, while(1);
a menudo se coloca en el archivo main. Aunque esto no resuelve el problema. (siempre y cuando no tenga el CTOS() en su interrupción. Le sugiero que revise su programa paso a paso, o verifique si alguna vez sale de la interrupción.No estoy familiarizado con C18, pero uso su sucesor XC8.
Con respecto a su ISR, ¿el compilador C18 sabe ejecutar void low_interrupt (void) cuando se genera una interrupción de baja prioridad? He visto funciones designadas para interrupciones con algunos compiladores, pero XC8 funciona de la siguiente manera:
// HP int declared with 'high_priority' identifier, name function as you see fit
interrupt high_priority void isr_high(void)
// LP int declared with 'low_priority' identifier, name function as you see fit
interrupt low_priority void isr_low(void)
Si C18 usa nombres de funciones designados en su lugar, asegúrese de que los tenga correctos.
En segundo lugar, así es como habría manejado el desbordamiento del temporizador:
interrupt high_priority void isr_high(void)
{
// TIMER0 Overflow
if (INTCONbits.TMR0IF)
{
LATEbits.LE0 ^= 1; // Toggle RE0
INTCONbits.TMR0IF = 0; // Clear the interrupt flag
}
}
Espero que esto ayude.
Gracias por toda la ayuda.
Con un poco de trabajo en MPLabSim, encontré mi error y el código corregido a continuación funciona correctamente, al menos en MPLabSim:
EDITAR: ¡ahora también funciona en hardware real!
void main (void) /* */
{
TRISA = 0; /* */
TRISC = 0; /* */
TRISB = 0;
TRISD = 0x00;
RTOS();
}
void low_interrupt ()
{
_asm GOTO timer_isr _endasm
}
#pragma code
#pragma interrupt low_interrupt //save =PROD
void timer_isr ()
{
if(INTCONbits.TMR0IF==1)
{
count++;
INTCONbits.TMR0IF = 0;
}
}
void RTOS ()
{
T0CONbits.T08BIT = 0; // 16-bit timer
T0CONbits.T0CS = 0; // increment on instruction cycle input
T0CONbits.T0SE = 0; // increment on low--> high transition of clock
T0CONbits.PSA = 1; // T0 prescaler not assigned i.e. 1:1 prescaler.
RCONbits.IPEN = 1; //Enable Interrupt Priorities
INTCONbits.GIEL = 1; //Enable Low Priority Interrupt
INTCONbits.GIEH = 0; // disable high priority interrupts
INTCONbits.GIE = 1; //Enable Global Interrupts
INTCONbits.TMR0IE = 1; //Enable Timer0 Interrupt
INTCON2bits.TMR0IP = 0; //TMR0 set to low Priority Interrupt
INTCONbits.TMR0IF = 0; // T0 int flag bit cleared before starting
T0CONbits.TMR0ON = 1; // timer0 START
counter(count);
}
void counter ()
{
LATD = count;
}
Rogelio Rowland
count
define? ¿ Lo has marcadovolatile
?usuario17592
count++;
en lugar decount = count++;
. El++
operador guarda el nuevo valor para usted.