Autor Tema: problema interrupcion rda.  (Leído 12577 veces)

0 Usuarios y 3 Visitantes están viendo este tema.

Desconectado cheapekt

  • PIC12
  • **
  • Mensajes: 93
problema interrupcion rda.
« en: 05 de Noviembre de 2008, 10:36:41 »
Buenas a todos,
He cogido un código de la página "rincón del ccs"
es el siguiente.
Código: [Seleccionar]
#include   <16f877.h>
#FUSES NOWDT                    //No Watch Dog Timer
#FUSES HS                       //High speed Osc (> 4mhz)
#FUSES NOPUT                    //No Power Up Timer
#FUSES PROTECT                  //Code protected from reads
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected
#FUSES NODEBUG                  //No Debug mode for ICD
#use delay(clock=20000000)
#use standard_io(c)
#use rs232(baud=9600,parity=N,bits=8,stop=1,xmit=PIN_C6,rcv=PIN_C7,enable=PIN_C5,errors)
char Keypress=' ';

#int_rda
void serial_isr() {

  Keypress=0x00;
  if(kbhit()){
    Keypress=getc();
    if(Keypress!=0x00){
      putchar(keypress);
      keypress=0x00;
      printf("hola amigo");
    }
  }
}


void main() {

  enable_interrupts(global);
  enable_interrupts(int_rda);

  printf("\r\n\Listen on RS232 (Int)\r\n");

  do {


  } while (TRUE);
}

En teoria cuando recibe cualquier carácter en el PC tendria que llegar el mensaje "hola amigo", pero sin embargo no me llega este mensaje al PC,
¿alguien me puede explicar porque motivo no lo envia?
Muchas gracias un saludo!

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: problema interrupcion rda.
« Respuesta #1 en: 05 de Noviembre de 2008, 14:00:18 »
Hola.

Prueba de la siguiente manera y me cuentas:

Código: C#
  1. #include <16f877.h>
  2. #FUSES NOWDT //No Watch Dog Timer
  3. #FUSES HS //High speed Osc (> 4mhz)
  4. #FUSES NOPUT //No Power Up Timer
  5. #FUSES PROTECT //Code protected from reads
  6. #FUSES NOBROWNOUT //No brownout reset
  7. #FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
  8. #FUSES NOCPD //No EE protection
  9. #FUSES NOWRT //Program memory not write protected
  10. #FUSES NODEBUG //No Debug mode for ICD
  11. #use delay(clock=20000000)
  12. #use standard_io(c)
  13. #use rs232(baud=9600,parity=N,bits=8,xmit=PIN_C6,rcv=PIN_C7)
  14. char Keypress=' ';
  15.  
  16. #int_rda
  17. void serial_isr()
  18. {
  19.         Keypress=0x00;
  20.         if(kbhit())
  21.         {
  22.                 Keypress=getc();
  23.                 if(Keypress!=0x00)
  24.                 {
  25.                         putchar(keypress);
  26.                         keypress=0x00;
  27.                         printf("hola amigo");
  28.                 }
  29.         }
  30. }
  31.  
  32.  
  33. void main()
  34. {
  35. enable_interrupts(global);
  36. enable_interrupts(int_rda);
  37.  
  38. printf("\r\n\Listen on RS232 (Int)\r\n");
  39.  
  40. do {} while (TRUE);
  41. }

Saludos
El papel lo aguanta todo

Desconectado cheapekt

  • PIC12
  • **
  • Mensajes: 93
Re: problema interrupcion rda.
« Respuesta #2 en: 05 de Noviembre de 2008, 16:29:05 »
gracias por tu ayuda MLO_
 He probado tu codigo, y no me enviaba nada, luego he cambiado la sentencia
#use rs232(baud=9600,parity=N,bits=8,xmit=PIN_C6,rcv=PIN_C7)  por
#use rs232(baud=9600,parity=N,bits=8,stop=1,xmit=PIN_C6,rcv=PIN_C7,enable=PIN_C5)
 y me imprime pero tansolo lo que está en el main ("\r\n\Listen on RS232 (Int)\r\n")

No hace caso a la interrupcion lanzada desde el PC, ¿alguien me peude ayudar?
No logro realizar interrupciones  int_rda,

Gracias!!! espero que alguna alma caritativa logre ayudarme, un saludo!

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: problema interrupcion rda.
« Respuesta #3 en: 05 de Noviembre de 2008, 17:36:02 »
Hola.

Me parece extrano porque a mi si me funciono con el codigo que te envie!!!!  :?



Te adjunto el codigo, el .hex y el archivo del proteus.

Saludos
El papel lo aguanta todo

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re: problema interrupcion rda.
« Respuesta #4 en: 05 de Noviembre de 2008, 17:38:46 »
Puede ser un problema de hard, porque esos programas me han funcionado desde el primer día, y solo con #use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7).  :shock:
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado Giovanny

  • PIC12
  • **
  • Mensajes: 97
    • Supercomponentes
Re: problema interrupcion rda.
« Respuesta #5 en: 05 de Noviembre de 2008, 17:52:24 »
si estas usando max 232 o similar, revisalo, me ha pasado que solo medio chip sirve y el otro medio no..  prueba y nos cuentas.
igual que redpic lo he probado con #use rs232(baud=9600,xmit=PIN_C6,rcv=PIN_C7).  solamente y trabaja bien.
        Saludos desde Colombia! Que hermoso país....

Desconectado cheapekt

  • PIC12
  • **
  • Mensajes: 93
Re: problema interrupcion rda.
« Respuesta #6 en: 05 de Noviembre de 2008, 18:35:23 »
Vale muchas gracias amigos revisare el hardware y os comentare que tal me ha ido.. muy amables

UN saludo!!!

Desconectado cheapekt

  • PIC12
  • **
  • Mensajes: 93
Re: problema interrupcion rda.
« Respuesta #7 en: 06 de Noviembre de 2008, 09:55:04 »
Una pregunta.
¿Qué significan exactametne estos warning?

if(c='H'){   Assignament inside relational expression...... ¿no es correcta la expresión?

Después em salen 3 warning mas que dicen
Interrupts disabled during call to prevent re-entrancy: (@I2C_WRITE_1)
Interrupts disabled during call to prevent re-entrancy: (@delay_ms1)
Interrupts disabled during call to prevent re-entrancy: (@PUTCHAR_BIU_1)

Estos 3 warning me señalan la llave que cierra el programa

Creo que por eso no me funciona mi programa, o quizas puede ser un motivo.

He comprobado el hardware y creo que esta correcto.
Cuando la patilla C5 esta a nivel bajo las patillas de habilitacion del max485 están a nivel bajo las 2, es decir las patillas 2 y 3 del max485 estan a nivel bajo. EN este estado el PIC tiene la patilla de transmisión (C6) a nivel alto y la patilla de recepción (C7) a nivel bajo. En este estado entonces el max485 su patilla 1(recepción) se pone a nivel bajo, y la patilla 4 (ransmisión) se pone a nivel alto.


Estoy usando rs485, y esta consigna
#use rs232(baud=9600,parity=N,bits=8,stop=1,xmit=PIN_C6,rcv=PIN_C7,enable=PIN_C5)
hace que por defecto el pin C5 esté a un nivel bajo. Es decir estamos en el caso que he puesto anteriormente, quizas como el PIC está en este estado no deja que le lleguen datos, y tengo que modificar el software. Estoy un poco perdido. el programa en cuestión es el siguiente. Si alguien me puede ayudar se lo agradezco enormemente.

Código: [Seleccionar]
#include <16F877.h> // Se añade la libreria del PIC a utilizar



#FUSES NOWDT,HS,NOPUT,PROTECT,NOBROWNOUT,NOLVP,NOCPD,NOWRT,NODEBUG
#use delay(clock=20000000)      //Velocidad del reloj


#use rs232(baud=9600,parity=N,bits=8,stop=1,xmit=PIN_C6,rcv=PIN_C7,enable=PIN_C5) //enable=PIN_C5 hace que el C maneje el pin de habilitación


#define EEPROM_SDA PIN_C4   
#define EEPROM_SCL PIN_C3   

#include <24512.c> // Se añade la libreria de la EEPROM 24LC512
#include <external_eeprom.c> // Se añade la libreria para controlar una EPROM externa

//Interrupción probocada por el PC para volcar datos


#int_rda
void serial_isr(){

///////////////////////////////////////////////////////////////////////////////////
///                                                                             ///                                 
///            LECTURA DE DATOS EN LA EEPROM Y ENVIAR AL PC                     ///                             
///                                                                             ///
///////////////////////////////////////////////////////////////////////////////////
      int dato=0,dir2=0,i=0,f=0,g=0,h=0,j=0,k=0;
      float dato2=0;
      char c;
     disable_interrupts(int_rda);//Aqui deshabilito la interrupción
   
      if (kbhit()) 
 //wait until a character has been received
 
    c = getc(); 
 //read character from UART
 
      if(c='H'){
      printf(" Interrupcion ");
     
   
   dato=read_ext_eeprom(dir2); // Leemos la hora en la EEPROM
   dir2=dir2+1; // Incrementamos el puntero de la EEPROM
   printf("%u",dato);// Enviamos dato a ordenador
   delay_ms(200);

   dato=read_ext_eeprom(dir2); // Leemos los minutos en la EEPROM
   dir2=dir2+1; // Incrementamos el puntero de la EEPROM
   printf("%u",dato);// Enviamos dato a ordenador
   delay_ms(200);

   dato=read_ext_eeprom(dir2); // Leemos los segundos en la EEPROM
   dir2=dir2+1; // Incrementamos el puntero de la EEPROM
   printf("%u",dato);// Enviamos dato a ordenador
   delay_ms(200);


      delay_ms(200);
      for (f=0; f<4; f++){ // Leemos las irradiancias de la EEPROM EXTERNA
         dato2= read_float_ext_eeprom(dir2);
         delay_ms(200);     
         dir2=dir2+4;
         printf("%f",dato2);// Enviamos dato a ordenador
      }
      for (g=0; g<4; g++){// Leemos las temperaturas ambientes en la EEPROM EXTERNA
         dato2= read_float_ext_eeprom(dir2);
         delay_ms(200);     
         dir2=dir2+4;
         printf("%f",dato2);// Enviamos dato a ordenador
      }     
      for (h=0; h<4; h++){// Leemos las temperaturas en la placa de la EEPROM EXTERNA
         dato2= read_float_ext_eeprom(dir2);
         delay_ms(200);     
         dir2=dir2+4;
         printf("%f",dato2);// Enviamos dato a ordenador
      }
      for (i=0; i<4; i++){// Leemos las velocidades del viento de la EEPROM EXTERNA
         dato2= read_float_ext_eeprom(dir2);
         delay_ms(200);
         dir2=dir2+4;
         printf("%f",dato2);// Enviamos dato a ordenador
      }
      for (j=0;j<4;j++){// Leemos los voltios de la EEPROM EXTERNA
         dato2= read_float_ext_eeprom(dir2);
         delay_ms(200);   
         dir2=dir2+4;
         printf("%f",dato2);// Enviamos dato a ordenador
      }
      for (k=0;k<4;k++){// Leemos las intensidades de la EEPROM EXTERNA
         dato2= read_float_ext_eeprom(dir2);
         delay_ms(200);   
         dir2=dir2+4;
         printf("%f",dato2);// Enviamos dato a ordenador
      }
   }
}
////////////////////////////////////////////////////////////////////////////////////
///                                                                              ///
///                                                                              ///   
///                           PROGRAMA PRINCIPAL                                 ///
///                                                                              ///
///                                                                              ///
////////////////////////////////////////////////////////////////////////////////////
void main(void) // Inicio del programa principal
{

///////////////////////////////////////////////////////////////////////////////////
///                              ///                                 
///            DECLARACIÓN DE LAS VARIABLES E INICIALIZACION DE ÉSTAS           ///                             
///                              ///
///////////////////////////////////////////////////////////////////////////////////
//Variables float que contienen datos de las tablas

   float irra[]    = {1, 2, 3, 6};
   float tempa[]    = {6, 3, 2, 1};
   float tempm[]    = {2, 4, 5, 6};
   float vel[]    = {2, 4, 5, 6};
   float volt[]    = {2, 4, 5, 6};
   float inte[]    = {2, 4, 5, 6};

//Variables int que contienten el valor de la fecha
   int min,sec,hr;

//Inicialización de las variables necesarias para movernos por la EEPROM
   int dir=0;

//Iniciaización variables para necesarias para moverse dentro de los datos
   int f=0,g=0,h=0,i=0,j=0,k=0;

   min=0;
   sec=0;
   hr=0;

////////////////////////////////////////////////////////////////////////////////////
///                                                                              ///                                 
///        GUARDAR DATOS EN EEPROM EXTERNA Y INICIALIZAR CONTAJE RELOJ           ///                             
///                                                                              ///
////////////////////////////////////////////////////////////////////////////////////
   
   init_ext_eeprom(); // Inicializamos EEPROM EXTERNA

   delay_ms(200);// retraso 200 milisegundos para no colapsar PIC
   
   
   //rtc_get_time(hr,min,sec); //Guardamos la hora, minuto y segundo que nos da el RTC
   write_ext_eeprom(dir,hr); // Escribimos la hora en la EEPROM
   dir=dir+1; // Incrementamos el puntero de la EEPROM

   write_ext_eeprom(dir,min); // Escribimos los minutos en la EEPROM
   dir=dir+1; // Incrementamos el puntero de la EEPROM

   write_ext_eeprom(dir,sec); // Escribimos los segundos en la EEPROM
   dir=dir+1; // Incrementamos el puntero de la EEPROM

      delay_ms(200);
      for (f=0; f<4; f++){ // Escribimos las irradiancias en la EEPROM EXTERNA
         write_float_ext_eeprom(dir, irra[f]);
         delay_ms(200);     
         dir=dir+4;
      }
      f=0;

      for (g=0; g<4; g++){// Escribimos las temperaturas ambientes en la EEPROM EXTERNA
         write_float_ext_eeprom(dir, tempa[g]);
         delay_ms(200);     
         dir=dir+4;
      }
      g=0;

      for (h=0; h<4; h++){// Escribimos las temperaturas en la placa en la EEPROM EXTERNA
         write_float_ext_eeprom(dir, tempm[h]);
         delay_ms(200);     
         dir=dir+4;
      }
      h=0;

      for (i=0; i<4; i++){// Escribimos las velocidades del viento en la EEPROM EXTERNA
         write_float_ext_eeprom(dir, vel[i]);
         delay_ms(200);
         dir=dir+4;
      }

      i=0;
      for (j=0;j<4;j++){// Escribimos los voltios en la EEPROM EXTERNA
        write_float_ext_eeprom(dir, volt[j]);
        delay_ms(200);   
         dir=dir+4;
      }
      j=0;

      for (k=0;k<4;k++){// Escribimos las intensidades en la EEPROM EXTERNA
         write_float_ext_eeprom(dir, inte[k]);
         delay_ms(200);   
         dir=dir+4;
      }
      k=0;

            printf(" ariburri ");
            delay_ms(500);                  // espera por ejemplo 0,5 seg para enviar nuevamente el dato,
            output_HIGH(PIN_B1);        // por ejemplo conectas un led entre el pin B1 y masa y este debe prender
            delay_ms(250);                  // espera por ejemplo 0,25 seg
            output_LOW(PIN_B1);         // se apaga el led
            delay_ms(250);                  // esperas otros 0,25 seg para enviar nuevamente el dato,
                     
 
  do{
                       
                     enable_interrupts(global);
                     enable_interrupts(int_rda);
 
   }while(TRUE);

}

Cualquier error que creeis que estoy cometiendo y no lo veo por favor diganmelo, no se que hacer.

Gracias y siento las molestias y mi pesadez

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re: problema interrupcion rda.
« Respuesta #8 en: 06 de Noviembre de 2008, 10:02:29 »
Con respecto a

if(c='H'){   Assignament inside relational expression...... ¿no es correcta la expresión?

En C = es asignación y == comparación por lo que te esta avisando de que estas asignando el valor 'H' a la variable c y que por lo tanto no estas comparando si el valor de c es igual a 'H'

A otra cosa mariposa. Con todo el respeto, cariño y consideración del mundo: Tu #int_rda es una barbaridad.  :mrgreen:

Hay un principio general que dice que "En una interrupción haz exactamente lo imprescindible para atenderla, el resto debe hacerse fuera de ella"

Y tu interrupción #int_rda, que se dispara cada vez que recibe un carácter, recoge el primero recibido y se pone a escribir la USART, a leer la EEPROM, a hacer cálculos, bucles, print-efes y solo le falta que la mandes a por tabaco.

Te recomiendo encarecidamente que reestructures tu código para que la interrupción reciba lo que la interrumpe y haga todo el resto en el main().

En el foro hay decenas de ejemplos de cómo hacer esto de forma sencilla a la par que elegante. Voy a mirar por ahí y después te pongo unos ejemplos, o dale caña al buscador de Foro que para eso lo pagamos. ja, ja, ja  :D :D :D

« Última modificación: 06 de Noviembre de 2008, 10:10:53 por RedPic »
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re: problema interrupcion rda.
« Respuesta #9 en: 06 de Noviembre de 2008, 10:14:26 »
Fíjate en este simplísimo ejemplo que colgué en el hilo Teoría y praxis de las com serie TTL : 3.- Comandos de un solo carácter
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado cheapekt

  • PIC12
  • **
  • Mensajes: 93
Re: problema interrupcion rda.
« Respuesta #10 en: 06 de Noviembre de 2008, 10:15:33 »
Muchisimas gracias sr. RedPic, ya tengo un problema resuelto. Ahora el programa no imprime por defecto en el PC el contenido de la EEPROM, pero
Ahora la interrupción no salta en ningún momento. Ya que estoy enviando la letra "H" al pic, pero este ni se inmuta, entonces en ningún momento vuelca la información de la EEPROM en el PC,

Gracias de neuvo

Desconectado cheapekt

  • PIC12
  • **
  • Mensajes: 93
Re: problema interrupcion rda.
« Respuesta #11 en: 06 de Noviembre de 2008, 10:16:47 »
Perdón he contestado sin leer lo posterior,... me lo miro y le informo un saludo!

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re: problema interrupcion rda.
« Respuesta #12 en: 06 de Noviembre de 2008, 11:11:56 »
Ahgggggg Ay, que me dá un soponcio ... ja, ja, ja  :D :D :D

El ver trozo de tu código te juro que hasta duele ... ja, ja, ja  :D :D :D

Esta forma de habilitar las interrupciones es la primera vez que la veo y te aseguro que si lo ven Brian W. Kernighan y Dennis M. Ritchie (los creadores del C) les dá también un soponcio, pero no te preocupes que todo tiene arreglo en esta vida (menos eso que ni nombramos, por si acaso)  :P
Código: C#
  1. do{
  2.  
  3.     enable_interrupts(global);
  4.     enable_interrupts(int_rda);
  5.  
  6.    }while(TRUE);

Venga, vamos a ir ordenando las cosas poco a poco y verás como al final todo sale perfecto.  :mrgreen:

Si todo tu programa se ejecuta en dos partes:

una únicamente una vez al resetear el PIC que es todo el trozo dentro del main() antes de do{}While(TRUE);

y otra solo cuando se recibe cierto carácter por la USART

entonces deberíamos tener una estructura de este tipo:

Código: C#
  1. // FUSES DEFINES e INCLUDES
  2.  
  3. // VARIABLES GLOBALES
  4. Char rec;
  5.  
  6. // INTERRUPCION
  7. #int_rda
  8. void rda_handler(void){
  9.   if(Kbhit()){
  10.     rec=getc();
  11.   }
  12. }
  13.  
  14. // MAIN
  15. void main(void){
  16.  
  17.   // TODO LO NECESARIO PARA PONER EN MARCHA EL PIC o TU PROGRAMA
  18.  
  19.  
  20.   // HABILITO INTERRUPCIONES
  21.   enable_interrupts(int_rda);
  22.   enable_interrupts(global);
  23.   // BUCLE INFINITO
  24.   do{
  25.  
  26.     // DETECTO NECESIDAD DE HACER ALGO Y LO HAGO
  27.     if(rec=='H'){
  28.       rec='\0'; // Para no volver a entrar has recibir un nuevo 'H'
  29.  
  30.        // AQUI HAGO TODO LO QUE ANTES HACÍA DENTRO DE LA INTERRUPCIÓN
  31.  
  32.     }
  33.  
  34.   }while(TRUE);
  35.  
  36. }

¿Me he explicado medio bien?  o ...  :mrgreen:

« Última modificación: 06 de Noviembre de 2008, 11:19:33 por RedPic »
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado MLO__

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 4581
Re: problema interrupcion rda.
« Respuesta #13 en: 06 de Noviembre de 2008, 11:56:17 »
Hola.

Pongo mi cuota aprendida en el manejo del RS485  :mrgreen: (Gracias a RedPic y Nocturno)

Cuando simule el sistema en el proteus (con el codigo aqui posteado inicialmente) aparecio el siguiente warning
Logic contentions detected on net #00029 (el mismo que me aparecio en mi caso y que evidencio la falla en el RX - MASTER, pero en mi caso debido al mal manejo en la impedancia de los transmisores de los modulos PIC SLAVE)

Siguiendo mas a fondo el warn, me lleva a la linea de Rx del microcontrolador y encuentro la siguiente informacion:
Two or more outputs of the same strength attempt to drive the net into opposing logic state



Es decir, al inicializar la rutina del serial (#use rs232) con el pin de habilitacion, existe un conflicto entre el estado logico inicial del Virtual COM y el Rx del PIC, lo que hace que no funcione correctamente, ademas en la compilacion del programa en C aparece el warning : Interrupts disabled during call to prevent re-entrancy:  (@PUTCHAR_BIU_1)

Al quitar la parte de enable=pin_c5 los warning en proteus y de compilacion desaparecen y el sistema opera tal como deberia, respondiendo a la interrupcion.

Si vas a usar RS485, te recomiendo que no uses el pin de habilitacion del CCS y generes tu mismo las funciones de habilitacion de Rx y Tx, no es complicado hacerlo.

Saludos
El papel lo aguanta todo

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re: problema interrupcion rda.
« Respuesta #14 en: 06 de Noviembre de 2008, 12:12:40 »
En otro hilo, creo que era tuyo MLO, también digo lo mismo.

En RS485 no uso los enable's automáticos del CCS sino que yo mismo habilito la transmisión o recepción del mismo.

Código: C++
  1. void main(void){
  2.  
  3.   // Por defecto siempre estoy a la escucha
  4.   output_low(TX_485_ENABLE);
  5.  
  6.   // Bucle Infinito
  7.   While(True){
  8.  
  9.     if(Tengo_Algo_Que_Decir){
  10.       // Habilito la transmisión ...
  11.       output_high(TX_485_ENABLE);
  12.       // ... lo digo
  13.       printf("Hello World");
  14.       // ... y Deshabilito la transmisión volviendo a su estado "natural"
  15.       output_low(TX_485_ENABLE);
  16.     }
  17.  
  18.   }
  19.  
  20. }
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania