Duda con interrupciones PIC

#1
Hola! estoy trabajando en un proyecto con microcontroladores y tengo que activar una salida cada cierto tiempo. Para hacer esto uso la interrupción por desborde del tmr0 para incrementar una variable, cuando ésta llega a cierto valor, activo una salida.
El problema que tengo es que cuando en el código me comunico por spi (por ej cuando se presiona un pulsador) con un integrado, la salida tarda más tiempo del que debería en activarse.

Hay alguna posibilidad de que el tiempo de llamado a la interrupción no sea constante? de más esta decir que la rutina de spi no modifica para nada la variable que uso para activar la salida, ni tampoco el tmr0.

Muchas gracias!

Aclaración 1: Estoy trabajando con el oscilador interno del PIC porque no necesito precisión de tiempo.
Aclaración 2: El SPI lo uso por soft.
 
#2
Por lo que decís, realizar el SPI por soft le lleva tiempo al uC y pasa lo que mencionas. Tal vez para evitar ese problema, resolvé el cambio de la salida en la misma interrupción (no mediante un flag y luego en el código principal), para evitar que el código SPI te frene.

Ejemplo en C:

PHP:
#define CUENTA_INICIAL 1000
unsigned int cuenta=CUENTA_INICIAL;

interrupcion_timer0()
{
   cuenta--;
   
   if(!cuenta)
     {
      cuenta=CUENTA_INICIAL;
      ... //Cambio el estado del puerto
     }
}

int main()
{
  //Inicialización general (timer, SPI, puerto, etc)
  while(1)
    {
     //Código principal donde llamás al SPI por soft
    }
}
 
#4
Por lo que decís, realizar el SPI por soft le lleva tiempo al uC y pasa lo que mencionas. Tal vez para evitar ese problema, resolvé el cambio de la salida en la misma interrupción (no mediante un flag y luego en el código principal), para evitar que el código SPI te frene.

Ejemplo en C:

PHP:
#define CUENTA_INICIAL 1000
unsigned int cuenta=CUENTA_INICIAL;

interrupcion_timer0()
{
   cuenta--;
   
   if(!cuenta)
     {
      cuenta=CUENTA_INICIAL;
      ... //Cambio el estado del puerto
     }
}

int main()
{
  //Inicialización general (timer, SPI, puerto, etc)
  while(1)
    {
     //Código principal donde llamás al SPI por soft
    }
}
perdón, me olvidé de aclarar que la activación de la salida la resuelvo en la misma interrupción. Muchas gracias por responder ;)

Estas resguardando los REGs importantes cuando entras a la ISR o rutina de interrupciones???
el código lo tengo escrito en c, estoy usando el compilador ccs. Muchas gracias por responder ;)
 
#6
¿Tenés forma de asignar la prioridad de las interrupciones?
en principio te diría que no, pero no estoy totalmente seguro. En qué estás pensando?

Me preocupa no entender lo que está pasando, encima el spi, por motivos que no vale la pena aclarar, esta programado por mi mismo, entonces no es más que otra sección de mi mismo código.

Hasta donde tenía entendido las interrupciones, una vez configurados los registros vinculados, ocurrían cada ciertos lapsos de tiempo que nada tenían que ver con las secciones de código que naturalmente no modifiquen estos registros.
 
#9
no exactamente, para el SPI no uso interrupciones, pero sí uso es otro timer para otras acciones cuando me comunico por SPI.
O sea usas un 2do timer con su interrupción.

Tal vez lo que sucede, es que mientras estas resolviendo el SPI, salta una interrupción para el timer del SPI, y luego al toque salta la interrupción del timer del puerto. Entonces dependiendo del caso, ese tiempo que te toma atender una interrupción e ir a la otra, es lo suficientemente grande como para que tengas ese problema.

En algunos uC, podés configurar la prioridad en la atención de la interrupción, obligando al uC atender 1ero al timer del puerto y luego al timer del SPI.

Otra podría ser, que la interrupción del timer que maneja al SPI, se dé con menor frecuencia.
 
#10
O sea usas un 2do timer con su interrupción.

Tal vez lo que sucede, es que mientras estas resolviendo el SPI, salta una interrupción para el timer del SPI, y luego al toque salta la interrupción del timer del puerto. Entonces dependiendo del caso, ese tiempo que te toma atender una interrupción e ir a la otra, es lo suficientemente grande como para que tengas ese problema.

En algunos uC, podés configurar la prioridad en la atención de la interrupción, obligando al uC atender 1ero al timer del puerto y luego al timer del SPI.

Otra podría ser, que la interrupción del timer que maneja al SPI, se dé con menor frecuencia.
Al final pude encontrar el problema, la que no pude encontrar es la explicación de por qué ocurre. Paso a explicar.

1) Debugueando con MPLAB, puse un breakpoint justo antes de que se ejecutara la función de SPI, una vez detenido el programa analicé el registro donde se habilita o deshabilita la interrupción por desborde del tmr0 (registros TMR0). Estaba todo OK.

2) Luego puse un break en el primera sentencia de la función SPI y volví a analizar el TMR0. Nuevamente estaba todo OK.

3) Luego de seguir agregando breaks en la función SPI y de encontrar de que spre estaba todo OK se me dio por analizar el registro INTCON y oh sorpresa encontré el problema.


Por alguna razón cósmica apenas entro a la función SPI (2) se me deshabilitan las interrupciones globales, y por ende TODAS las interrupciones. Entonces puse la sentencia ENABLE_INTERRUPTS( GLOBAL ) en la función SPI y se solucionó el problema.

Contento de la vida, vuelvo a probar el código y me doy cuenta de que todavía tenía retardo, no tanto como antes pero todavía tenía.

Entonces me puse a analizar el INTCON por si se modificaba en alguna otra parte del código y agregué un break por escritura del INTCON. Cuando probé esto me llevé la sorpresa de que la función delay_ms() de CCS modifica el INTCON, para colmo de una manera muy rara!. Deshabilita y habilita las int globales varias veces a medida de que se va ejecutando la función, provocandome los retardos que tenía.

Muchas gracias cosmefulanito por seguir el tema e intentar ayudarme! Saludos.
 

Temas similares

Arriba