Autor Tema: interrupciones & delay  (Leído 4487 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado xerex

  • PIC16
  • ***
  • Mensajes: 138
    • Mi servidor, mi casa.
interrupciones & delay
« en: 04 de Septiembre de 2005, 16:28:00 »
Hola xavales, he comenzado a hacer "cositas" con los pic y tengo una duda:

cuando utilizo en el ccs la funcion delay_ms o delay_us, me dice el compilador que me deshabilitara las interrupciones del micro (deshabilitandolas cuando entra en la funcion delay_ms o delay_us). hay alguna posibilidad de que no me las deshabilite y que las interrupciones se ejecuten cuando se estan ejecutando dichas funciones?????

Gracias de antemano.
Es falso eso de que el saber no ocupa lugar....


No se donde poner tanto libro.... :P

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2568
RE: interrupciones & delay
« Respuesta #1 en: 05 de Septiembre de 2005, 00:59:00 »
Eso no es así. Cuando está dentro de la función delay_ms() sí que puedes abandonarla para atender a una interrupción. El tiempo no cuenta, es al volver de la interrupción cuando retoma la temporización por donde la había dejado. Puede que el cálculo de la temporización no sea exacto por culpa de la interrupción.

Un saludo

Desconectado xerex

  • PIC16
  • ***
  • Mensajes: 138
    • Mi servidor, mi casa.
RE: interrupciones & delay
« Respuesta #2 en: 05 de Septiembre de 2005, 10:02:00 »
Bueno no es del todo verdad, eso creia yo, pero ayer el compilador me ponia eso como warning:

Interrupts disabled during call to prevent re-entrancy:  @delay_ms1

ves esto es lo que pone y esto es lo que hace, no deja ninguna interupcion ejecutarse si esta dentro de la funcion delay, no ejecuta interrupciones en la funcion delay_ms.... porque? hay alguna manera de quitarlo?

Gracias y un saludo.
Es falso eso de que el saber no ocupa lugar....


No se donde poner tanto libro.... :P

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2568
RE: interrupciones & delay
« Respuesta #3 en: 05 de Septiembre de 2005, 10:18:00 »
Si que es raro. Quieres pegar el programa para que pueda verlo.

Desconectado omix

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 244
RE: interrupciones & delay
« Respuesta #4 en: 05 de Septiembre de 2005, 13:50:00 »
Hola xerex, lo que te esta pasando seguramente es pq estas llamando a la función delay_ms desde una interrupcion y desde el main. Esto se debe a que si cuando estas dentro de la llamada del delay_ms se produce una interrupcion y esta llama tambien a delay_ms puede provocar una corrupcion en los datos, puesto que se esta llamando a la misma funcion desde dos flujos de ejecucion "paralelos". Es uno de los problemas que se da en programacion concurrente.
Para poderla usar sin problemas deberias proteger dicha funcion de manera que no se pueda entrar a ella desde dos sitios distintos a la "vez". Una manera de hacerlos es deshabilitando las interrupciones, por eso quiza es por lo que te da ese error el compilador.

A mi en el hitech, lo he tenido que hacer mas de una vez para poder llamar a una funcion desde dentro de una interrupcion y desde el main.

Saludos.

Desconectado xerex

  • PIC16
  • ***
  • Mensajes: 138
    • Mi servidor, mi casa.
RE: interrupciones & delay
« Respuesta #5 en: 05 de Septiembre de 2005, 16:00:00 »
Gracias Omix, tenias razon, utilizo delay_us en la interrupcion y delay_ms en la funcion principal del sistema aunque son dos funciones distintas las debe tomar de la misma manera asi que debe ser una concurrencia y por eso el compilador inhibe las interrupciones.

Nunca te acostaras sin compilar un programa mas jejeje.

Gracias de nuevo a todos!!!!
Es falso eso de que el saber no ocupa lugar....


No se donde poner tanto libro.... :P

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2568
RE: interrupciones & delay
« Respuesta #6 en: 06 de Septiembre de 2005, 00:18:00 »
¿Puedes poner el programa? tengo curiosidad por probarlo. A mí el compilador no me dá error.

Desconectado xerex

  • PIC16
  • ***
  • Mensajes: 138
    • Mi servidor, mi casa.
RE: interrupciones & delay
« Respuesta #7 en: 06 de Septiembre de 2005, 10:27:00 »
bueno aki te dejo el programa, es una practica que he echo con los pic para empezar a programarlos mira haber si tu compilador te lo compila yo utilizo el PCW DE CCS VER.: 3.190

#include <16F84a.H>
#fuses HS,NOWDT // OSCILADOR CRISTAL DE CUARZO Y SIN WD
#use delay(clock=4000000)

int alas=0,cola=0,panza=0;
// DEFINICION DE INTERUPCION EXTERNA
#int_ext
void interupcion_externa (void) // se producira una interrupcion cada 20 ms
{
int i=0;
   
   delay_us(1200);
   while (input(PIN_B0))
      {
      i++;
      delay_us (100);
      }
   if (i>=3) //suponemos superior a 300 microsegundos
      {

      if (input(PIN_A3))
         {
         // LUCES DE ALAS
         if (alas <= 15)
            {
            output_bit(PIN_A0,0);
            output_bit(PIN_b2,0); // alas
            output_bit(PIN_b3,0); // alas
            alas++;
            }
         if   ((alas >=15)&&(alas<=20))
            {
            output_bit(PIN_A0,1);
            output_bit(PIN_b2,1); // alas
            output_bit(PIN_b3,1); // alas
            alas++;
            }
         if (alas == 20)
            {
            alas = 0;
            }
         // LUCES COLA
         if (cola <= 10)
            {
            output_bit(PIN_A1,0);
            cola++;
            }
         if   ((cola >=10)&&(cola<=15))
            {
            output_bit(PIN_A1,1);
            cola++;
            }
         if (cola == 15)      
            {
            cola = 0;
            }
         // LUCES COLA
         if (panza <= 10)
            {
            output_bit(PIN_B7,0);
            panza++;
            }
         if   ((panza >=10)&&(panza<=15))
            {
            output_bit(PIN_B7,1);
            panza++;
            }
         if (panza == 15)      
            {
            panza = 0;
            }
         // LUCES FRONTALES
         output_BIT(PIN_b6,1);
         }
      else
         {
         output_bit(PIN_A0,1); // alas
         output_bit(PIN_A1,1); // cola
         output_BIT(PIN_b6,1); //Frontal
         output_BIT(PIN_b7,1); // Panza
         output_bit(PIN_b2,1); // alas
         output_bit(PIN_b3,1); // alas
         }
      }
   else
      {
      output_bit(PIN_A0,0);
      output_bit(PIN_A1,0);
      output_BIT(PIN_b6,0);
      output_BIT(PIN_b7,0);
      output_bit(PIN_b2,0); // alas
      output_bit(PIN_b3,0); // alas
      }
}
// PROGRAMA PRINCIPAL
void main (void)
{
long int x=0;
//configuracion de puertos
SET_TRIS_A(0x04); // PUERTO A COMO SALIDA
SET_TRIS_B(0X03); // PUERTO B COMO ENTRADA

// HABILITACION DE INTERUPCIONES EXTERNAS Y GLOBAL
ext_int_edge(L_TO_H); // interrupcion para comparacion flanco de subida
enable_interrupts(int_ext); // habilitacion de interupcion externa
enable_interrupts(global);
output_bit(PIN_A0,0); // alas
output_bit(PIN_A1,0); // cola
output_BIT(PIN_b6,0); //Frontal
output_BIT(PIN_b7,0); // Panza
output_bit(PIN_b2,0); // alas
output_bit(PIN_b3,0); // alas
while (true)
   {
   if (x<= 2000)
      {
      output_bit(PIN_A2,1);
      x++;
      }
   if ((x >=2000)&&(x<=4000))
      {
      OUTPUT_BIT(PIN_A2,0);
      x++;
      }
   if (x == 4000)
      x=0;
   }
               delay_ms(100); <- esta es la  funcion que me da el error segun el compilador
}
Es falso eso de que el saber no ocupa lugar....


No se donde poner tanto libro.... :P

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2568
RE: interrupciones & delay
« Respuesta #8 en: 07 de Septiembre de 2005, 02:35:00 »
Pués el programa tal cual lo tienes no dá ningún tipo de error.

Otra cosa: ¿Para que pones el delay_ms(100) detrás del while(true), si no lo va a ver nunca?

Desconectado xerex

  • PIC16
  • ***
  • Mensajes: 138
    • Mi servidor, mi casa.
RE: interrupciones & delay
« Respuesta #9 en: 07 de Septiembre de 2005, 11:08:00 »
Perdona, me equivoque y lo puse fuera, va dentro del while!!
no se a que se debera pero el compilador me da error Enfurruñado

lo consideraremos un expediente x de concurrencia como decia omix.

Gracias de todas formas. Un saludo.
Es falso eso de que el saber no ocupa lugar....


No se donde poner tanto libro.... :P

Desconectado pocher

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 2568
RE: interrupciones & delay
« Respuesta #10 en: 07 de Septiembre de 2005, 11:18:00 »
Así sigue sin dar error:

Codigo:
   while (true)
   {
      if (x<= 2000)
      {
         output_bit(PIN_A2,1);
         x++;
      }
      if ((x >=2000)&&(x<=4000))
      {
         OUTPUT_BIT(PIN_A2,0);
         x++;
      }
      if (x == 4000)
         x=0;
      delay_ms(100); //<- esta es la funcion que me da el error segun el compilador   
   }



Desconectado xerex

  • PIC16
  • ***
  • Mensajes: 138
    • Mi servidor, mi casa.
RE: interrupciones & delay
« Respuesta #11 en: 07 de Septiembre de 2005, 12:56:00 »
pues no se sera el compilador ccs este de marras!!! ke desastre.... Gracias de todas formas!
Es falso eso de que el saber no ocupa lugar....


No se donde poner tanto libro.... :P

Desconectado rmelectron

  • PIC10
  • *
  • Mensajes: 5
RE: interrupciones & delay
« Respuesta #12 en: 10 de Septiembre de 2005, 08:44:00 »
Tambien tengo problemas con la interrupcion temporal del TMR0 cuando utilizo una llamada a delay_ms en el programa ppal. No se que pasa, pero la interrupción no funciona adecuadamente y he comprobado que: si el tiempo de la interrupcion es del orden del tiempo que establede delay_ms en el ppal empiezan los problemas. En principio lo he solucionado anidando dentro de una estructura "for" la llamada delay_ms de un valor muy inferior al tpo de interrupcion. Pero en algunos sigo con algunos problemas referidos a este tema.

Si me pueden a ayudar, les agradezco.

Desconectado omix

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 244
RE: interrupciones & delay
« Respuesta #13 en: 10 de Septiembre de 2005, 12:19:00 »
Hola, como ya os dije anteriormente el error ese se debe a que puede surgir un problema de reentrancia al llamar a la funcion delay_ms o cualquier otra desde una interrupcion y desde el main. Para que entendais que es lo que puede ocurrir en caso de hacerlo os pongo un ejemplo:

int a = 25;

void funcion_no_reentrante(){
     int c;
     c = a;
     a = c + 5;
}

#int_rtcc
void interrupcion(){
  //codigo
   funcion_no_reentrante();
  //mas codigo
}

void main(){
  while(1){
     //codigo
     funcion_no_reentrante();
    //codigo
  }
}

Si tenemos el codigo anterior y lo ponemos en ejecucion y vemos lo que ocurre en una pasada de ejecucion, pueden ocurrir varias cosas con la funcion funcion_no_reentrante y son las siguientes:
1- Se ejecuta la funcion en el main y despues ocurre la interrupcion y se vuelve a ejecutar, lo cual no produce ningun problema ya que el resultado sera a = 35, es decir se le suma dos veces 5 a la variable a.
2- Se ejecuta primero la funcion en la interrupcion y luego en el main, ocurre exactamente lo mismo que en el caso 1.
3- Suponemos ahora que mientras estamos con la ejecucion de la funcion en el main se ejecuta solamente c = a (c = 25); y se produce la interrupcion la cual llama a dicha funcion y la ejecuta y por tanto al salir de la interrupcion a = 30. Ahora se continua la ejecucion por donde se habia quedado desde que se produjo la interrupcion y por lo tanto se ejecuta el a = c +5; lo cual deja un resultado en a = 30, lo que es incorrecto, puesto que deberia de ser 35, es decir, se le deberia de haber sumado 10 a a.
4- Se pueden dar mas combinaciones, pero ninguna de ellas sera correcta, solo lo seran si se ejecutan las llamadas a la funcion en serie, es decir, primero una y luego la otra.

Despues de este ejemplo ilustrativo, podeis ver que lo que esta haciendo el compilador a la hora de deshabilitar las interrupciones cuando se llama a la funcion delay_ms desde el main, es precisamente para prevenir que ocurran errores como el anterior.
En la mayoria de las ocasiones el compilador de CCS no produce dicho error, puesto que dicho compilador trata de crear de hacer todas las funciones que pueda que sean inline, con esto ahorra problemas de este tipo y tambien reduce el uso de ram, aunque se aumenta el uso de la rom. Lo de inline, para el que no lo sepa lo que hace es sustituir la llamada a la funcion por el codigo de dicha funcion. Esto lo podeis comprobar al desensamblar el codigo, si mirais podeis ver que la mayoria de las veces al hacer un delay, por ejemplo, te pone el codigo correspondiente en vez de la llamada a la funcion.

uff, menudo rollo os he metio :P, pero espero que asi quede la cosa mas clara.

Un saludo.

Desconectado rmelectron

  • PIC10
  • *
  • Mensajes: 5
RE: interrupciones & delay
« Respuesta #14 en: 24 de Septiembre de 2005, 09:15:00 »
Estimados Amigos:

Les pego el codigo para aclarar mi problema puntual. Cuando el tiempo de la interrupcion temporal del tmr0 es del orden del tiempo de delay en el main, empiezan los problemas. NO SE TRATA DE LLAMADAS RECURRENTES DE UNA MISMA FUNCION. De todas maneras no estoy seguro si el compilador hace un backup de las variables (a parte de w,status,etc) compartidas antes de atender la interrupcion. Pero bueno este punto lo comentamos despues.

//Este programa enciende unos leds y los apaga cuando ha trancurrido
//un breve tiempo dependiendo de una variable

#include <16F873.h>

#fuses HS,NOWDT,PROTECT,PUT,BROWNOUT,NOLVP,NOCPD,WRT

#use delay(clock=16000000)

//Configuración de los puertos en modo manual (set_tris, en main)
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)

//Salidas digitales
#define BLANCO_on  output_high(PIN_C0)
#define BLANCO_off output_low(PIN_C0)

#define B_on  output_high(PIN_C1)
#define B_off output_low(PIN_C1)

#define G_on  output_high(PIN_C2)
#define G_off output_low(PIN_C2)

#define R_on  output_high(PIN_C3)
#define R_off output_low(PIN_C3)

#define LED_on  output_high(PIN_C4)
#define LED_off output_low(PIN_C4)

#define A_on  output_high(PIN_C5)
#define A_off output_low(PIN_C5)


// ****************************************************************
//          DELARACIONES DE VARIABLES GLOBALES
// ****************************************************************
int1  FLAG;
int1  FLAG1;
int V_RX;      //recepcion
int CONT;      //GRAL

int   PWM_R;
int   PWM_G;
int   PWM_B;
int   PWM_BLANCO;
int   PWM_A;

long  V_INT;
char RX[8];          //para recepcion del puerto

int1 EFECTO;

int   V_ESCENA;

// ****************************************************************
//          DELARACIONES DE CONSTANTES GLOBALES
// ****************************************************************
const int C_TMR0=170;

void tonto(void);
void SET_INT(void);
void tonto2(void);

//-----------------------------------------------------------------------------
void SET_INT(void)
{
 R_off;G_off;B_off;BLANCO_off;A_off;

 setup_timer_1(T1_DISABLED);
 setup_timer_2(T2_DISABLED,0,1);
 disable_interrupts(INT_TIMER1);
 enable_interrupts(int_rda);
 disable_interrupts(INT_EXT);

 setup_counters(RTCC_INTERNAL,RTCC_DIV_1);//16 uS  SENTENCIA PROBLEMATICA
 set_rtcc(C_TMR0);
 V_INT=0;

 enable_interrupts(INT_RTCC);
 enable_interrupts(GLOBAL);}
//-----------------------------------------------------------------
void tonto(void)
{if (FLAG){LED_on;FLAG=0;}
    else {LED_off;FLAG=1;}
}
//-----------------------------------------------------------------
void tonto2(void)
{ if (FLAG1){BLANCO_on;FLAG1=0;}
   else {BLANCO_off;FLAG1=1;}
}

//-----------------------------------------------------------
void DELAY(long MULT)
//Al usar interrupciones temporales, la fcion delay_ms o delay_us genera errores
//por lo tanto con este metodo de repeticion funciona bien, siempre que
//el delay interno sea menor al tpo de interrupcion temporal
//tpo=1 uS * MULT
{long k; for (k=0;k<=MULT;k=k+1){delay_us(1);}}

/**********************************************************
      TRATAMIENTO DE INTERRUPCIONES
/**********************************************************/
#INT_TIMER0
void RSI(void)
{//Se produce cada 16 uS aproximadamente

 tonto(); //verificacion visual de la evolucion de la interrupcion

V_INT=V_INT+1;
if (V_INT==256)
 {V_INT=0;
  if (!(PWM_R==0)) {R_on;}
  if (!(PWM_G==0)) {G_on;}
  if (!(PWM_B==0)) {B_on;}
  if (!(PWM_BLANCO==0)) {BLANCO_on;}
  if (!(PWM_A==0)) {A_on;}
 }
 else
  {
  if (V_INT==PWM_R) {R_off;}
  if (V_INT==PWM_G) {G_off;}
  if (V_INT==PWM_B) {B_off;}
  if (V_INT==PWM_BLANCO) {BLANCO_off;}
  if (V_INT==PWM_A) {A_off;}
  }


set_timer0(C_TMR0);   //para ajustar tpo
}


//------------------------------------------------------------------------
void main(void)
{
   set_tris_b (0b11111111);   //Define el puerto B
   delay_ms(2000);

   // Definición de puertos 0=out  1=inp
   set_tris_a (0b111111);     //Define el puerto A
   set_tris_b (0b11111111);   //Define el puerto B
   set_tris_c (0b11000000);   //Define el puerto C

   //Reset general
   OUTPUT_A(0);
   OUTPUT_B(0);
   OUTPUT_C(0);

   PWM_R=255;       //nivel de rojo
   PWM_G=0;      //nivel de verde
   PWM_B=0;     //nivel de azul
   PWM_BLANCO=0;     //nivel de blanco
   PWM_A=0;       //nivel de AMARILLO

   V_ESCENA=1;    //PRIMER ESCENA


   SET_INT();EFECTO=0;
   //Inicio ciclo de SCAN principal
   while (TRUE)
   {
      tonto2();
      DELAY(2000); //Asi funciona bien, si cambio esta fucion por
      //delay_ms o delay_us cuyo tiempo se mayor a 16 uS que es el
      //tiempo seteado de la interrupcion temporal, el programa empieza a
      //funcionar erraticamente

    }
}


Un abrazo


 

anything