TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: pocher en 05 de Abril de 2008, 04:07:21

Título: Problemas encontrados con el compilador de CCS
Publicado por: pocher en 05 de Abril de 2008, 04:07:21
Abro este hilo porque por culpa de un mal funcionamiento (bajo mi punto de vista) del compilador he perdido varias horas.

Creo que para que esto no le sucediera a nadie más, deberíamos poner aquí en este Tema todos los problemas-errores que creamos que tiene el compilador, los discutiríamos entre todos y si efectivamente se trata de un error del compilador alguno de los moderadores pasaría a limpio un resumen del problema y lo incluiríamos en un Tema con chincheta arriba de todo para que estuviera bien visible y que por estos errores nadie más perdiese más tiempo.

Os paso a detallar lo que me ha pasado. El PROBLEMA está en la interrupción por cambio de estado en portB RB4..RB7, resulta que el compilador al salir de la interrupción baja la bandera RBIF pero no hace una lectura/escritura en el portB y estas dos cosas se deben cumplir (mirar el Datasheet) para que de nuevo no entre en la interrupción hasta que realmente haya otro cambio de estado. Si no se hace una lectura/escritura en el portB el programa se vuelve loco y está contínuamente entrando y saliendo de la interrupción.

La SOLUCION es leer/escribir el portB antes de abandonar la interrupción mediante un input ó un output de relleno, ó mejor aún para no perder tiempo hacerlo en ensamblador como bien dice jfh900 mediante las sentencias: #asm movf port_b,0 #endasm

Programa de ejemplo en el que sucede esto:

Código: [Seleccionar]
#include <16F876a.h>
#fuses NOWDT,XT, NOPUT, NOPROTECT
#use delay(clock=4000000)

#byte port_b=6

#INT_RB
Interrupcion_RB()
{
delay_ms(20);     //Antirebotes
  //#asm movf port_b,0 #endasm //Sin quitamos esta instrucción de relleno no funciona bien la interrupción
output_toggle(PIN_a0);
}

void main()
{
set_tris_a(0x00);      // Todo salidas
  set_tris_b(0xFF);    // Todo entradas
  output_a(0x00);

  enable_interrupts(INT_RB);
  enable_interrupts(GLOBAL);

  while(true);
}

Os animo a que comenteis este PROBLEMA y también a que si habeis detectado más problemas del compilador que los pegueis en este Tema para ser comentados.

Un saludo





Título: Re: Problemas encontrados con el compilador de CCS
Publicado por: vszener en 05 de Abril de 2008, 04:35:48
Yo en su día también pensé que era un error del compilador, pero creo que no lo es, el CCS sigue fiel, en este aspecto, al datasheet, que pone que el flag RBIF se debe 'limpiar' por software.

Al igual que si programamos en ASM el MPSAM no limpia este registro, sino que es tarea del programador de ponerlo a '0', el CCS hace igual, deja la tarea al programador.

En su día me acuerdo que tube una charla sobre este caso mismo con el amigo jfh900 en el post de Ejemplitos...

Aunque pienso igual que tu, que ya que se debe hacer pues que lo haga el compilador por sí mismo y nos ahorre tareas.


Suerte!!! ;)
Título: Re: Problemas encontrados con el compilador de CCS
Publicado por: pocher en 05 de Abril de 2008, 06:06:06
Si miras el fichero.lst verás como el compilador sí limpia por software el flag 0 del registro INTCON (RBIF) (Hace un BCF 0B.0) pero por lo que parece no hay una lectura/escritura del portb con lo que la interrupción vuelve a dispararse.
Título: Re: Problemas encontrados con el compilador de CCS
Publicado por: migsantiago en 05 de Abril de 2008, 11:41:58
Hola

CCS trae un ejemplo del uso de esa interrupción... EX_PBUTT.C. Me imagino que haciéndolo como ese no debe haber problema.

En su manejo de la interrupción hacen esto:

Código: [Seleccionar]
#int_rb
void detect_rb_change() {
   int current;
   static int last=0;

   set_tris_b(0xF0);
   current=input_b();

   #if LOWTOHIGH
   if ((!bit_test(last,4))&&(bit_test(current,4))) {dbutton4=1;}
   if ((!bit_test(last,5))&&(bit_test(current,5))) {dbutton5=1;}
   if ((!bit_test(last,6))&&(bit_test(current,6))) {dbutton6=1;}
   if ((!bit_test(last,7))&&(bit_test(current,7))) {dbutton7=1;}
   #elif HIGHTOLOW
   if ((!bit_test(current,4))&&(bit_test(last,4))) {dbutton4=1;}
   if ((!bit_test(current,5))&&(bit_test(last,5))) {dbutton5=1;}
   if ((!bit_test(current,6))&&(bit_test(last,6))) {dbutton6=1;}
   if ((!bit_test(current,7))&&(bit_test(last,7))) {dbutton7=1;}
   #endif

   last=current;
}
Título: Re: Problemas encontrados con el compilador de CCS
Publicado por: jfh900 en 05 de Abril de 2008, 11:47:03
Efectivamente este fue un problema que a mi personalmente me llevo muchas horas, aunque después leyendo el datasheet del micro entendí cual era el problema. La verdad es que la solución es muy fácil y al final trabaja correctamente.

Un saludo
Título: Re: Problemas encontrados con el compilador de CCS
Publicado por: pocher en 05 de Abril de 2008, 14:15:41
migsantiago ese ejemplo seguro que funciona bien ya que se efectua dentro de la interrupción una lectura del portb mediante current=input_b();

jfh900 al final se resuelve pero las horas perdidas hasta que al final ves el problema no te las devuelve nadie. El problema se resuelve, como bien sabes, haciendo una lectura/escritura del portb dentro de la interrupción, pero esto creo que lo tenían que haber hecho los de CCS, no nosotros.

¿Qué os parece, metemos esto como un olvido del compilador y le ponemos una chincheta para que la gente lo vea y nadie más se vuelva "tarumba" (majareta) con esto?
Título: Re: Problemas encontrados con el compilador de CCS
Publicado por: jfh900 en 05 de Abril de 2008, 14:26:35
A mi me parece bien.

Un saludo
Título: Re: Problemas encontrados con el compilador de CCS
Publicado por: migsantiago en 05 de Abril de 2008, 14:52:25
Chincheta obligatoria.  :idea:

Pero hay que editar el título del tema a: "Problema con Interrupción RB4-7" o algo así.
Título: Re: Problemas encontrados con el compilador de CCS
Publicado por: pocher en 05 de Abril de 2008, 16:30:49
Oido cocina, mañana que es domingo, no puedo, pero el lunes le pongo una chincheta.

La idea que yo tengo es poner aquí en este tema un determinado "bug" de CCS (de cualquier cosa), discutirlo entre todos y si se llega a la conclusión que efectivamente es un "bug" hacer una buena explicación y copiarlo en limpio en el tema con chincheta. El título del Tema con chincheta podría ser "Posibles bugs del compilador de CCS" si os parece bien.

Antes de seguir con esta cruzada he de decir que para mí el compilador de C que más me gusta es el de CCS, no porque sea el mejor, que quizá no lo sea, sino por la gran cantidad de personas que lo usan y que en un momento dado te pueden ayudar a resolver una duda.

Esta tarde se vé que tengo ganas de fastidiar al compilador y creo que he descubierto otra cosa que no funciona bien. Ojala me equivoque, por eso lo pongo aquí para discutirlo.

Se trata de la prioridad de las interrupciones en los PIC18.

Si un PIC18 tengo 2 interrupciones y una de ellas la declaro como de alta prioridad, pués si cuando se está ejecutando la instrucción de baja prioridad, llega la de alta prioridad pués se debe de abandonar inmediatamente la primera rutina e ir a atender a la rutina de alta prioridad.

Cuando finalice la rutina de alta prioridad retornará al punto donde se había quedado en la rutina de baja prioridad. Bueno, el caso es que creo que esto no funciona.

Os pongo un programa de ejemplo y os digo como reacciona.

Código: [Seleccionar]
#include <18F452.h>

#DEVICE HIGH_INTS=true

#use delay(clock=4000000)

#use fast_io(B)

#byte port_a = 0xF80
#byte port_b = 0xF81

//#PRIORITY int_ext,int_rb
//#PRIORITY int_rb,int_ext

#INT_TIMER0                        // Interrupción externa en RB0                     
interrupcion_TIMER0()          // Función de atención a la interrupción
{
delay_ms(3000);
  output_toggle(PIN_B1);
  disable_interrupts(INT_TIMER0); 
}

#INT_EXT                        // Interrupción externa en RB0                     
interrupcion_RB0()          // Función de atención a la interrupción
{
delay_ms(3000);
output_toggle(PIN_A0);
}

//#INT_RB                        // Interrupción externa en RB4-RB7   
#INT_RB HIGH
//#INT_RB FAST                     
interrupcion_RB4_RB7()          // Función de atención a la interrupción
{
delay_ms(3000);
  #asm movf port_b,0 #endasm //Hace falta leer el portb, si no va mal
  output_toggle(PIN_B3);
}

main()
{
set_tris_b(0xF5); // RB4 salida, RB4-RB7,RB0 entradas.
  set_tris_a(0x00);
  bit_clear(port_a,0);
bit_clear(port_b,1);
bit_clear(port_b,3);
//output_low(PIN_B3);

setup_counters(RTCC_8_BIT,RTCC_DIV_128);

  enable_interrupts(GLOBAL);
  enable_interrupts(INT_RB);
  enable_interrupts(INT_EXT);

  while(1)
  {
  if(input(pin_b2))
  enable_interrupts(INT_TIMER0);
  }
}



La interrupción de RB0 es de baja prioridad y la de RB4..RB7 de alta.

Si activamos la interrupción RB0 y a continuación activamos la de RB4..RB7 tendría que ejecutar primero la interrupción RB4..RB7 y activar la salida RB3 para luego regresar a la interrupción RB0 y activar la salida RA0. Pués no, hace justamente lo contrario, primero activa la salida RA0 y luego la salida RB3.

Aquí os lo dejo, pensarlo.
Título: Re: Problemas encontrados con el compilador de CCS
Publicado por: gu1llermo en 05 de Abril de 2008, 17:38:14
Hola pocher, la idea de bugs del compilador CCS me parece buena, porque a mi también me ha pasado que pienso que es un error del CCS (y lo más probable es que así sea  :wink: 8)) jejeje mentira, es mío y es un error por desconocimiento, por ejemplo para el caso de leer el puerto B en una interrupción por cambio de estado del RB7:RB4 desde asembler vengo leyendo el puerto B al ocurrir y además desactivar el flag de interrupción, como ya hemos visto todo así lo indica el datasheet, el porqué el compialador del CCS no incluye esta lectura del puerto B, es porque supongo que si entramos allí tenemos que leerlo para saber si fue un flanco ascendente o descendente, por lo que al salir ya hemos hecho la lectura y el compilar se encarga de borrar la bandera de dicha interrupción, el ejemplo que colgó migsantiago está demasiado bueno  8)

Por otro lado, no e trabajado todavía con las priroridades de las interrupciones pero creo ver porque entra 1ero en la interrupción del RB0 antes de la de RB7:RB4, prueba esto

Agrega un clear_interrupt()

Código: [Seleccionar]
...
enable_interrupts(GLOBAL);
enable_interrupts(INT_RB);
clear_interrupt(INT_EXT);// Para evitar posible interrupción indeseada antes de tiempo
enable_interrupts(INT_EXT);
...

Igual cuando habilites una interrupción de timers es bueno hacer un clear_interrupt y así evitar interrupciones prematuras.

Otra cosa, no veo que habilites el flanco en el que quiere que entre por la interrupción de RB0, utilizando la instrucción: ext_int_edge() yo por lo general lo defino, para saber cuando ocurre y porque no sé cuál es la que hace por defecto, tendría que ver el datasheet.

Para terminar, decir que la idea me gusta, porque como bien dices a veces tardamos mucho tiempo tratando de resolver algo y lo primero que pensamos es que el compilador no sirve  8) me pasó también hace poco tratando de pasar una estructura por referencia a una función, en éste subforo se puede encontrar la solución que me han dado.

Saludos.
Título: Re: Problemas encontrados con el compilador de CCS
Publicado por: Cryn en 06 de Abril de 2008, 00:24:49
interesantes observaciones. tambien sucedio algo similar conmigo, pero con el rs232, en realidad conla interrupcion rda:

Código: [Seleccionar]
#int_rda
void isr_rda()
{
output_toggle(pin_a1);
...
}

si no se coloca un c=getc(); por algun lado, de preferencia al inicio
igual se queda colgado en la interrupcion
Título: Re: Problemas encontrados con el compilador de CCS
Publicado por: pocher en 06 de Abril de 2008, 02:13:16
Hola Guillermo.

El entrar en la interrupción RB4..RB7 no necesariamente a de ser para leer el portB, puedes leer el portA, incrementar un contador, activar un flag, tomarte una caña ...  ¡a no! esto último no.  :D

El añadir clear_interrupt(INT_EXT); lo único que hace es borrar el flag INTF inicialmente (comprobado). Lo que tendría que hacer el programa es que si activamos la entrada RB0 y a continuación p.e. la entrada RB7 pués debería abandonar la interrupción de RB0 inmediatamente y hacer la de RB4..RB7, pero no lo hace.

Si no se incluye ext_int_edge() hace por omisión el flanco ascendente (en el tratamiento de prioridades de interrupciones que estamos haciendo esto sería indiferente).

Hola Cryn.

Conforme lo tienes debería de ir bien sin necesidad de c=get(c) . En este tipo de interrupción RDA he entrado en ocasiones solo para para activar un flag y salir y no es necesario el get(c). Convendría que especificaras concretamente el programa donde te pasó.

PD. El tratamiento de las prioridades lo estoy haciendo sobre simulador. El lunes si puedo lo pruebo físicamente.



Título: Re: Problemas encontrados con el compilador de CCS
Publicado por: gu1llermo en 06 de Abril de 2008, 11:23:29
Ah! ok, ya te entiendo un poco mejor pocher, y una pregunta: cómo te das cuenta de que no deja la interrupción RB0 para atender la RB7? estás simulando en el Mplab? por otro lado, para que esto sucediera, me refiero a que deje de atender la interrupción RB0 para atender la RB7 sería habilitando el bit GIE al entrar en cualquier otra rutina de manejo de interrupción excepto en la de RB7, pero el problema de esto es que si estamos en la interrupción del timer0 (por ejemplo) y ocurre una interrupción del timer1, entonces dejará de atender la interrupción del timer0 para atender la del timer1, y si ocurren muchas interrupciones al mismo tiempo puede ocurrir un overflow del stack del pic y alli si que nos volvemos un 8  :?.

Por eso de estar dentro de un interrupción para dejarla, la única forma que veo es habilitando el bit GIE, el problema: cualquier otra interrupción aprovechará esa condición para entrar, a menos que estemos utilizando solo dos interrupciones  y solo habilitamos dicho bit dentro del manejo de la interrupción de menor prioridad :idea: allí si me imagino que podríamos hacer eso  :wink:

PD: Acabo de leer que estás haciendo las pruebas en el simulador, porque probarlo en físico no sé como hacerlo, todo corre muy rápido  :shock: 8) en cambio en el simulador le doy step by step  ;-)

Saludos.
Título: Re: Problemas encontrados con el compilador de CCS
Publicado por: Cryn en 07 de Abril de 2008, 00:55:50
Conforme lo tienes debería de ir bien sin necesidad de c=get(c) . En este tipo de interrupción RDA he entrado en ocasiones solo para para activar un flag y salir y no es necesario el get(c). Convendría que especificaras concretamente el programa donde te pasó.

bueno dejame buscar el código de ser necesario, porque lo hice como te mencione, sin el getc() y no me salia de la interrupcion, eso lo vi depurando en el proteus, se quedaba colgado ahí
aumente el getc() y recien salia de la interrupcion, de veras :mrgreen:
Título: Re: Problemas encontrados con el compilador de CCS
Publicado por: pocher en 07 de Abril de 2008, 13:40:10
Ah! ok, ya te entiendo un poco mejor pocher, y una pregunta: cómo te das cuenta de que no deja la interrupción RB0 para atender la RB7?

Me doy cuenta viendo las salidas:

Si activamos la interrupción RB0 se mete dentro de su rutina (concretamente en el delay_ms(3000)) y si a continuación activamos la de RB4..RB7 tendría que dejar el delay_ms y ejecutar por completo la rutina de interrupción RB4..RB7 activando la salida RB3 para luego regresar a la rutina de interrupción RB0 (al  delay_ms(3000)) y activar la salida RA0. Pués no, hace justamente lo contrario, primero activa la salida RA0 y luego la salida RB3, es decir se comporta sin tener en cuenta la prioridad de RB4..RB7.

Todo esto lo hice con el simulador, ahora recien acabo de probarlo físicamente con un 18F4550 y también va mal (la prioridad se la pasa por el forro).

Me he metido en el buscador del FORO y he estado largo rato leyendo mensajes sobre prioridades en las interrupciones, pero en todos los que he leido y han sido unos cuantos nadie se queja de que el compilador lo esté haciendo mal (programas que tengan prioridad de interrupciones no he visto ninguno). Que raro, ¿no se le ha presentado este problema a nadie? ... a ver si estoy "pa lla" (ido, grillao, zombi, aguilipollao).

Título: Re: Problemas encontrados con el compilador de CCS
Publicado por: pocher en 07 de Abril de 2008, 13:51:47
Otra cosa que acabo de ver con la prueba física.

Para que funcione bien la interrupción RB4..RB7, la lectura/escritura del portB mediante por ejemplo un #asm movf port_b,0 #endasm se tiene que hacer antes del output_toggle(PIN_a0). Este output_toggle es el del primer programa que puse, el que solo tiene la interrupción RB4..RB7. En el otro programa, lo mismo hay que meter el #asm movf port_b,0 #endasm nada más entrar en la interrupción )
Título: Re: Problemas encontrados con el compilador de CCS
Publicado por: pocher en 08 de Abril de 2008, 09:24:59
Decididamente el tema de las prioridades con interrupciones falla. He estado probando físicamente (y con PROTEUS) otras combinaciones de prioridades (INT_TMR0,INT_EXT y INT_RB) y algunas van bien pero otras fallan.

Lo considero como bug y lo clasifico como tal en el tema con chincheta.

Un saludo
Título: Re: Problemas encontrados con el compilador de CCS
Publicado por: erdanieee en 11 de Septiembre de 2009, 06:05:16
Hola a todos! Se que el hilo es un poco antíguo, pero recientemente he tenido un problema con la interupción RB, y como solucionarlo me ha llevabo algún tiempo, he decidido postearlo aquí por si a alguien le es útil.

   Bueno, el problema surgió cuando intenté simular en PROTEUS (v. 7.2) un programa sencillo en CCS (v.4.088) para PIC16f84A que hacía uso de varias interrupciones, entre ellas la RB. Al iniciar la simulación, PROTEUS lanzaba un mensaje de error que decía algo así como "violation access error in module <UNKNOW>".

   Tras debuggearlo me dí cuenta de que fallaba justo al activar la interrupción RB, y que si comentaba esa línea el programa funcionaba perfectamente (salvo que no hacía la interrupción  :)). Despues de varias pruebas, se me ocurrió ver el listado en ensamblador y observé que esa línea es codificada por 3 sentencias en ensamblador que ponen a uno los bits 5 y 6 del registro STATUS,  y el bit 3 del registro INTCON. El (INTCON,3) es para habilitar la interrupción RB, (STATUS,5) para seleccionar el banco (lo cual es innecesario ya que INTCON se puede acceder tanto desde el banco 1 como desde el 0), pero lo que me sorprendió fué que modificara (STATUS,6) que en el datasheet pone cláramente que no se usa y debe mantenerse a cero!!!. Al eliminar esta línea la simulación funcionó perfectamente, asiq probablemente PROTEUS no acepta que se modifiquen bits que no deberían ser usados en el PIC.

   Dado que hay más gente que ha usado esta interrupción y no ha tenido este problema, supongo que el bug afectará sólo a algunos PICs. Espero que no sea muy liosa la explicación y que, si a alguien más le ocurre esto, sepa cómo solucionarlo.

Un saludo
Título: Re: Problemas encontrados con el compilador de CCS
Publicado por: jadacuor en 16 de Noviembre de 2009, 12:43:05
Chincheta obligatoria.  :idea:

Pero hay que editar el título del tema a: "Problema con Interrupción RB4-7" o algo así.

hola, soy nuevo en este foro asi que espero no estar violando ninguna regla...mi problema radica en que tengo un programa hecho en ccs (en el cual manejo interrupciones timer1 y rb4-7) para 16f877a y corre perfectamente en proteus... pero al intentar pasarlo al 18f452 no funcionan bien las interrupciones en especial la #int_rb  ya que algunas veces sin haber cambio en el puerto b , ingresa a la interrupcion y cuando ingresa no sale...como si no borrara la bandera de interrupcion..(creo yo)... espero una ayuda por favor .....gracias

este es el codigo::


#include <18F452.h>
#fuses XT,NOWDT,NOPROTECT,NOLVP, CCP2C1
#use delay(clock=4000000)




#use fast_io(c)
#byte portb = 6
#byte portd = 8


 #INT_TIMER1
 void isr_tmr1()
 {output_toggle(pin_b0);
  set_timer0(0);
  set_timer1(20000);
}


 #INT_RB
 void isr_rb()
{output_toggle(pin_b0);
portd = swap(portb);
}


void main(){
disable_interrupts(GLOBAL);
set_tris_d(0);
set_tris_b(255);
setup_timer_0(RTCC_EXT_L_TO_H|RTCC_DIV_2);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_4);





enable_interrupts(INT_RB);
enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);
output_d(0);
set_timer0(0);
set_timer1(20000);

 while( TRUE )
 {output_c(0);}
}
Título: Re: Problemas encontrados con el compilador de CCS
Publicado por: Cryn en 16 de Noviembre de 2009, 14:21:03
Cuando se usa la interrupción por cambio de estado en RB4-RB7, en la rutina de interrupción se debe leer y escribir el puerto, yo hago así:

output_b(input_b());

Entonces tu código por ahí debería quedar:

#INT_RB
void isr_rb(){
   output_toggle(pin_b0);
   portd = swap(portb);
   output_b(input_b());
   clear_interrupt(int_rb);  //se ser necesario se limpia el flag de rb
}

Esto ya esta explicado en otros hilos, te recomiendo busques un poco más.

Saludos
Título: Re: Problemas encontrados con el compilador de CCS
Publicado por: salchig en 17 de Noviembre de 2009, 22:37:33
Hola amigos..   
Soy nuevo el el tema de programacion de Microcontroladores y estoy empesando por el lenguaje C.
A mi me surgio el mismo problema que a "erdanieee"  que no puedo simular en Proteus  :5] interrupciones en el puerto B con el PIC 16f84A. Me sale este error "violation access error in module <UNKNOW>". siempre que habilito la interrupcion    enable_interrupts(int_rb);  Estoy usando el CCS 4.023 y proteus 7.6 sp0
Pongo un codigo de muestra.. Agradeceria cualquier ayuda
 

#include <16F84A.h>

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES XT                       //Crystal osc <= 4mhz
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading

#use delay(clock=4000000)

int t=10,p=5;
void setear();
#int_rb

rb_isr() {
output_b(0x07);
delay_ms(1000);
    }

void main()
{

   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   enable_interrupts(int_rb);        //registro de int_rb
   enable_interrupts(global);        //activa interrupts
   // TODO: USER CODE!!
   output_b(p);
   output_low(pin_a4);
   output_low(pin_a1);
   while(1){
   output_high(pin_A0);
   delay_ms(t*p);
   output_low(pin_A0);
   delay_ms(100-t*p);
   
   }

}
Título: Re: Problemas encontrados con el compilador de CCS
Publicado por: Rock_Isaac en 12 de Octubre de 2016, 18:55:55
La interrupcion RB0 siempre es de alta prioridad, no es configurable.

Las demas pueden ser configuradas como alta o baja prioridad...
saludos...




Oido cocina, mañana que es domingo, no puedo, pero el lunes le pongo una chincheta.

La idea que yo tengo es poner aquí en este tema un determinado "bug" de CCS (de cualquier cosa), discutirlo entre todos y si se llega a la conclusión que efectivamente es un "bug" hacer una buena explicación y copiarlo en limpio en el tema con chincheta. El título del Tema con chincheta podría ser "Posibles bugs del compilador de CCS" si os parece bien.

Antes de seguir con esta cruzada he de decir que para mí el compilador de C que más me gusta es el de CCS, no porque sea el mejor, que quizá no lo sea, sino por la gran cantidad de personas que lo usan y que en un momento dado te pueden ayudar a resolver una duda.

Esta tarde se vé que tengo ganas de fastidiar al compilador y creo que he descubierto otra cosa que no funciona bien. Ojala me equivoque, por eso lo pongo aquí para discutirlo.

Se trata de la prioridad de las interrupciones en los PIC18.

Si un PIC18 tengo 2 interrupciones y una de ellas la declaro como de alta prioridad, pués si cuando se está ejecutando la instrucción de baja prioridad, llega la de alta prioridad pués se debe de abandonar inmediatamente la primera rutina e ir a atender a la rutina de alta prioridad.

Cuando finalice la rutina de alta prioridad retornará al punto donde se había quedado en la rutina de baja prioridad. Bueno, el caso es que creo que esto no funciona.

Os pongo un programa de ejemplo y os digo como reacciona.

Código: [Seleccionar]
#include <18F452.h>

#DEVICE HIGH_INTS=true

#use delay(clock=4000000)

#use fast_io(B)

#byte port_a = 0xF80
#byte port_b = 0xF81

//#PRIORITY int_ext,int_rb
//#PRIORITY int_rb,int_ext

#INT_TIMER0                        // Interrupción externa en RB0                     
interrupcion_TIMER0()          // Función de atención a la interrupción
{
delay_ms(3000);
  output_toggle(PIN_B1);
  disable_interrupts(INT_TIMER0); 
}

#INT_EXT                        // Interrupción externa en RB0                     
interrupcion_RB0()          // Función de atención a la interrupción
{
delay_ms(3000);
output_toggle(PIN_A0);
}

//#INT_RB                        // Interrupción externa en RB4-RB7   
#INT_RB HIGH
//#INT_RB FAST                     
interrupcion_RB4_RB7()          // Función de atención a la interrupción
{
delay_ms(3000);
  #asm movf port_b,0 #endasm //Hace falta leer el portb, si no va mal
  output_toggle(PIN_B3);
}

main()
{
set_tris_b(0xF5); // RB4 salida, RB4-RB7,RB0 entradas.
  set_tris_a(0x00);
  bit_clear(port_a,0);
bit_clear(port_b,1);
bit_clear(port_b,3);
//output_low(PIN_B3);

setup_counters(RTCC_8_BIT,RTCC_DIV_128);

  enable_interrupts(GLOBAL);
  enable_interrupts(INT_RB);
  enable_interrupts(INT_EXT);

  while(1)
  {
  if(input(pin_b2))
  enable_interrupts(INT_TIMER0);
  }
}



La interrupción de RB0 es de baja prioridad y la de RB4..RB7 de alta.

Si activamos la interrupción RB0 y a continuación activamos la de RB4..RB7 tendría que ejecutar primero la interrupción RB4..RB7 y activar la salida RB3 para luego regresar a la interrupción RB0 y activar la salida RA0. Pués no, hace justamente lo contrario, primero activa la salida RA0 y luego la salida RB3.

Aquí os lo dejo, pensarlo.