Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: xerex en 04 de Septiembre de 2005, 16:28:00
Título: interrupciones & delay
Publicado por: xerex 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.
Título: RE: interrupciones & delay
Publicado por: pocher 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
Título: RE: interrupciones & delay
Publicado por: xerex 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.
Título: RE: interrupciones & delay
Publicado por: pocher en 05 de Septiembre de 2005, 10:18:00
Si que es raro. Quieres pegar el programa para que pueda verlo.
Título: RE: interrupciones & delay
Publicado por: omix 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.
Título: RE: interrupciones & delay
Publicado por: xerex 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!!!!
Título: RE: interrupciones & delay
Publicado por: pocher 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.
Título: RE: interrupciones & delay
Publicado por: xerex 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 }
Título: RE: interrupciones & delay
Publicado por: pocher 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?
Título: RE: interrupciones & delay
Publicado por: xerex 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
lo consideraremos un expediente x de concurrencia como decia omix.
Gracias de todas formas. Un saludo.
Título: RE: interrupciones & delay
Publicado por: pocher 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 }
Título: RE: interrupciones & delay
Publicado por: xerex 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!
Título: RE: interrupciones & delay
Publicado por: rmelectron 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.
Título: RE: interrupciones & delay
Publicado por: omix 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; }
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.
Título: RE: interrupciones & delay
Publicado por: rmelectron 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
//----------------------------------------------------------- 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
Título: RE: interrupciones & delay
Publicado por: MGLSOFT en 26 de Septiembre de 2005, 12:56:00
je..je.. En la pagina del CCS estan las explicaciones a tus problemas....
Lee esto: 3.190 The internal error PPUSE has been fixed 3.191 The read/write program_memory functions missing from some parts is now back 3.191 An accuracy problem in the delay functions is fixed