Haz una pregunta
  Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos
Foros Registrarse ¿Olvidaste tu contraseña?

Temas similares

26/02/2013 #1


Duda con interrupciones PIC
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.
26/02/2013 #2

Avatar de cosmefulanito04

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:

Código 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
    
}

26/02/2013 #3

Avatar de fdesergio

Estas resguardando los REGs importantes cuando entras a la ISR o rutina de interrupciones???
26/02/2013 #4


cosmefulanito04 dijo: Ver Mensaje
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:

Código 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

fdesergio dijo: Ver Mensaje
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
26/02/2013 #5

Avatar de cosmefulanito04

¿Tenés forma de asignar la prioridad de las interrupciones?
26/02/2013 #6


cosmefulanito04 dijo: Ver Mensaje
¿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.
26/02/2013 #7

Avatar de cosmefulanito04

Para resolver ese SPI por soft, ¿usas interrupciones externas y otro timer?
27/02/2013 #8


cosmefulanito04 dijo: Ver Mensaje
Para resolver ese SPI por soft, ¿usas interrupciones externas y otro timer?
no exactamente, para el SPI no uso interrupciones, pero sí uso es otro timer para otras acciones cuando me comunico por SPI.
27/02/2013 #9

Avatar de cosmefulanito04

cristianclc dijo: Ver Mensaje
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.
28/02/2013 #10


cosmefulanito04 dijo: Ver Mensaje
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.
Respuesta
¿Tienes una mejor respuesta a este tema? ¿Quieres hacerle una pregunta a nuestra comunidad y sus expertos? Registrate

Foros de Electrónica » Diseño digital » Microcontroladores y sistemas embebidos

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO ©2011, Crawlability, Inc.