TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: Diego E. en 31 de Octubre de 2013, 18:17:49

Título: Usart se bloquea
Publicado por: Diego E. en 31 de Octubre de 2013, 18:17:49
Hola amigos, tengo un programa que recibe un dato por el módulo usart y lo entrega a una variable, cuando le llegan muchos byte seguidos la interrupción del módulo usart se bloquea y no vuelve a entrar, el resto del programa funciona perfecto.

A alguno de ustedes le ha sucedido algo similar.

Saludos.
Título: Re: Usart se bloquea
Publicado por: RALF2 en 31 de Octubre de 2013, 19:08:29
Es raro pero si estas utilizando el ccs y el puerto serial, por hardware, podrias agregar la opcion errors para que te resetee la usart.
Lo otro que puede estar ocuriendo es que tardas mucho tiempo manipulando el primer byte que te llego y luego cuando llega otro no te da tiempo de procesarlo y eso bloquea la usart del pic.   :mrgreen:
Prueba enviando los datos que llegan por la usart mas lento y nos dices.   ;-)

Saludos
Título: Re: Usart se bloquea
Publicado por: Diego E. en 31 de Octubre de 2013, 22:33:02
Hola Ralf, gracias por responder, si alcanzan a llegar varios byte al buffer y este no se ha leído el usart se bloquea ?, voy a probar con el detector de errores y te cuento,

Saludos.
Título: Re: Usart se bloquea
Publicado por: RALF2 en 31 de Octubre de 2013, 22:36:04
Citar
Hola Ralf, gracias por responder, si alcanzan a llegar varios byte al buffer y este no se ha leído el usart se bloquea ?

Asi mismo es, lo puedes leer en el data sheet del Pic   :mrgreen:
Título: Re: Usart se bloquea
Publicado por: MGLSOFT en 31 de Octubre de 2013, 23:13:31
Puede tener uno en el buffer y otro entrando, si hay un tercero se bloquea...
Título: Re: Usart se bloquea
Publicado por: MGLSOFT en 31 de Octubre de 2013, 23:14:45
a que velocidad tienes puesto el puerto?
Título: Re: Usart se bloquea
Publicado por: Diego E. en 01 de Noviembre de 2013, 09:12:16
Hola Marcos, el puerto lo tengo a 4800, lo curioso es que en mi programa inmediatamente se genera la interrupción descargo el buffer.

Saludos.
Título: Re: Usart se bloquea
Publicado por: MGLSOFT en 01 de Noviembre de 2013, 09:15:30
Publica tu código, es posible ayudarte mas de ese modo...
Título: Re: Usart se bloquea
Publicado por: Diego E. en 01 de Noviembre de 2013, 10:42:42
El programa consiste en lo siguiente:

Recibe por el usart dos byte de un módulo RF, si el dato es valido lo reenvía por un módulo serial por software a través de el pin RA4, tiene un temporizador para detectar si el módulo de RF deja de enviar para enviar un código de fiscalización, le hice una rutina que detecta si la interrupción del usart se bloquea y así reiniciar el micro.

Gracias por tu interés.

Saludos.

Código: C
  1. #include <16f1827.h>
  2.  
  3. #use delay(clock = 16mhz)
  4.  
  5. #use rs232(baud=2400, xmit=pin_b2,rcv=pin_b1,stop=2,stream=rs232)
  6. #use rs232(baud=4800, xmit=pin_b0,rcv=pin_b0,stop=2,stream=potencia,timeout=4)
  7.  
  8. #fuses intrc_io, wdt, put, brownout, nomclr
  9.  
  10. #byte   porta = 0x0c            //Definicion de variables del pic
  11. #byte   portb = 0x0d
  12. #byte   wpua = 0x20c
  13. #byte   wpub = 0x20d
  14. #byte   option_reg = 0x95
  15.  
  16. #define dip_sw porta
  17. #define pin_rx bit_test(portb,1)
  18. #define pin_cheq_rf pin_b7
  19.  
  20. int const dir_potencia = 0b10100010;
  21. int dato_recibido[5];
  22. int con_recibir;
  23. int codigo_tecla;
  24. int direccion;
  25. int con_modo_env;
  26. int con_recibir_rf;
  27. int res_codigo_tecla;
  28. int con_seguridad_rf;
  29.        
  30. short ban_enviar;
  31. short ban_tmr1;
  32. short ban_pin_rx;
  33.  
  34. void enviar_dato();
  35. void tiempo_recibir();
  36. void seguridad_rf();
  37.  
  38. ///////////////////////////////////////////////////////////////////////////////
  39. //******************INTERRUPCIONES*********************************************
  40. //*****************************************************************************
  41. //*****************************************************************************
  42. //*****************************************************************************
  43. //*****************************************************************************
  44. //*****************************************************************************
  45. //Vector de interrupcion de la recepcion de datos por el usart
  46. #int_rda                               
  47. void interrupcion_rx()
  48. {
  49.         int respaldo;
  50.        
  51.         respaldo = getc(rs232);
  52.         output_toggle(pin_cheq_rf);
  53.         con_seguridad_rf = 0;
  54.        
  55.         if(con_modo_env == 2)
  56.         {              
  57.                 if(respaldo == direccion) {con_recibir_rf = 0;}
  58.                 return;
  59.         }
  60.        
  61.         con_recibir_rf = 0;
  62.        
  63.         if(con_modo_env == 1)
  64.         {
  65.                 codigo_tecla = respaldo;
  66.                 res_codigo_tecla = respaldo;
  67.                 con_modo_env = 2;      
  68.                 return;
  69.         }
  70.        
  71.         if(respaldo == direccion) {con_modo_env = 1;}  
  72. }
  73. ///////////////////////////////////////////////////////////////////////////////
  74. //se recibe la comunicación del pic de potencia
  75. #int_ext
  76. void recibir_mando()
  77. {
  78.         set_timer2(0);
  79.         clear_interrupt(int_timer2);
  80.         enable_interrupts(int_timer2);
  81.        
  82.         dato_recibido[con_recibir] = getc(potencia);
  83.         con_recibir++;
  84.        
  85.         if(con_recibir == 4)
  86.         {
  87.                 con_recibir = 0;
  88.                         if(dato_recibido[0] == dir_potencia)
  89.                 {
  90.                         ban_enviar = 1;
  91.                         //enviar_dato_pc();
  92.                         memset(dato_recibido, 0, sizeof(dato_recibido));
  93.                         set_timer1(65536 - 2500);
  94.                 }
  95.         }
  96. }
  97. ///////////////////////////////////////////////////////////////////////////////
  98. //vector de interrupcion por desbordamiento del timer 1
  99. #int_timer1                                    
  100. void interrupcion_tmr1()
  101. {
  102.         set_timer1(0);
  103.         ban_tmr1 = 1;
  104.        
  105.         if(!ban_enviar) {return;}
  106.         ban_enviar = 0;
  107.        
  108.         if(codigo_tecla != 0) {enviar_dato();}  //si no han presionado tecla no envia
  109. }
  110. ///////////////////////////////////////////////////////////////////////////////
  111. //Vector de interrupcion por desbordamiento del timer 2
  112. #int_timer2                                    
  113. void interrupcion_tmr2()
  114. {
  115.         con_recibir = 0;
  116.         memset(dato_recibido, 0, sizeof(dato_recibido));
  117.         disable_interrupts(int_timer2);
  118. }
  119. ///////////////////////////////////////////////////////////////////////////////
  120. //******************PROGRAMA GENERAL*******************************************
  121. //*****************************************************************************
  122. //*****************************************************************************
  123. //*****************************************************************************
  124. //*****************************************************************************
  125.  
  126. #zero_ram       //Borrado de la memoria ram
  127.  
  128. void main()             //Rutina principal
  129. {
  130. set_tris_a(0b11111111);         //Configuracion del puerto a
  131. set_tris_b(0b00111011);         //Configuracion del puerto b
  132.  
  133. porta = 0b11111111;
  134. portb = 0b00111111;
  135.  
  136. setup_comparator(nc_nc_nc_nc);
  137.  
  138. setup_oscillator(osc_16mhz | osc_intrc | osc_pll_off);
  139.        
  140. delay_ms(10);
  141.  
  142. setup_timer_0(rtcc_div_1 | rtcc_ext_h_to_l);
  143. setup_timer_1(t1_internal | t1_div_by_8);
  144. setup_timer_2(t2_div_by_64,250,8);
  145. port_b_pullups(true);  
  146.  
  147. setup_wdt(wdt_512ms);
  148. ext_int_edge(h_to_l);
  149. clear_interrupt(int_ext);
  150. enable_interrupts(int_ext);
  151. enable_interrupts(int_rda);
  152. enable_interrupts(int_timer1);
  153. enable_interrupts(int_timer2);
  154. enable_interrupts(global);
  155.  
  156. putc('A', rs232);
  157.  
  158. ///////////////////////////////////////////////////////////////////////////////
  159. //***********************RUTINAS GENERAL DE TECLADO****************************
  160. //*****************************************************************************
  161. while(true)            
  162.         {
  163.                 restart_wdt();
  164.                 delay_ms(5);
  165.                 tiempo_recibir();
  166.                 seguridad_rf();
  167.         }
  168. }
  169. ///////////////////////////////////////////////////////////////////////////////
  170. //***********************RUTINAS***********************************************
  171. //*****************************************************************************
  172. //*****************************************************************************
  173. //*****************************************************************************
  174. //*****************************************************************************
  175. //rutina que envia los datos al pic de potencia
  176. void enviar_dato()     
  177. {
  178.         disable_interrupts(int_timer0);
  179.        
  180.         fputc(0b10100001, potencia);
  181.         fputc(codigo_tecla, potencia);
  182.         fputc(10, potencia);
  183.         fputc(5, potencia);
  184.        
  185.         set_timer2(0);
  186.         clear_interrupt(int_timer0);
  187.         enable_interrupts(int_timer0);
  188.         input(pin_b0);
  189.         codigo_tecla = 0;
  190. }
  191. ///////////////////////////////////////////////////////////////////////////////
  192. //sei se deja de recibir un dato durante 150 ms se envía la función de apagado
  193. void tiempo_recibir()
  194. {
  195.         direccion = dip_sw >> 1;
  196.         direccion &= 0b00001111;
  197.         direccion |= 0b10100000;
  198.                
  199.         con_recibir_rf++;
  200.         if(con_recibir_rf == 30 && con_modo_env == 2)
  201.         {
  202.                 codigo_tecla = res_codigo_tecla + 1;
  203.                 res_codigo_tecla = 0;
  204.                 con_modo_env = 0;
  205.         }
  206. }
  207. ///////////////////////////////////////////////////////////////////////////////
  208. //se chequea el pin de rx rf y se se bloquea la interrupción se resetea el pic
  209. void seguridad_rf()
  210. {
  211.         if(!pin_rx && !ban_pin_rx)
  212.         {
  213.                 ban_pin_rx = 1;
  214.                
  215.                 con_seguridad_rf++;            
  216.                 if(con_seguridad_rf == 5)
  217.                 {
  218.                         con_seguridad_rf = 0;
  219.                         reset_cpu();
  220.                 }              
  221.         }
  222.         if(pin_rx && ban_pin_rx) {ban_pin_rx = 0;}     
  223. }
Título: Re: Usart se bloquea
Publicado por: MGLSOFT en 01 de Noviembre de 2013, 10:55:00
Estas utilizando el mismo pin para enviar y recibir en la segunda uart ??

La primera es por hardware ?? Los pines B1 y B2 son de hardware ??
Título: Re: Usart se bloquea
Publicado por: manwenwe en 01 de Noviembre de 2013, 11:08:41
No se casi nada de CCS pero... ¿dentro de la interrupción no deberías borrar el flag de la fuente que ha producido la interrupción?. Si no... en cuanto el PC sale de la interrupción vuelve a entrar....

Un saludo.
Título: Re: Usart se bloquea
Publicado por: MGLSOFT en 01 de Noviembre de 2013, 11:31:31
Se borra solo el flag de int, en CCS.

Porque usas 2 bit de stop en las comunicaciones ??
Título: Re: Usart se bloquea
Publicado por: manwenwe en 01 de Noviembre de 2013, 11:36:50
Se borra solo el flag de int, en CCS.

Porque usas 2 bit de stop en las comunicaciones ??

Lo decía porque en "void interrupcion_rx()" no se borra ningún flag. Perdón.
Título: Re: Usart se bloquea
Publicado por: MGLSOFT en 01 de Noviembre de 2013, 11:38:34
Entiendo.
Es que el manejador de interrupciones de CCS lo hace solo, si uno mira el codigo en asm generado, se ve que es asi... :mrgreen:
Título: Re: Usart se bloquea
Publicado por: Diego E. en 01 de Noviembre de 2013, 12:06:27
Tengo dos módulos el primer UART es hardware y el segundo es una comunicación especial utilizando el mismo pin RB0, interrupción externa, ambos tienen 2 bit de stop.

Acá todo funciona perfecto, el problema es que cuando el módulo RF envía datos muy seguidos la interrupción UART 1 (Hardware) se bloquea y no vuelve a recibir, como comenté antes, lo que hice fue estar preguntando independientemente por el PIN RX de este UART 1 e ir incrementando un contador, cuando hay interrupción por UART 1 se borra el contador, pero si la interrupción está bloqueada el contador incrementa hasta cierto valor y ahí se resetea el PIC.
Título: Re: Usart se bloquea
Publicado por: MGLSOFT en 01 de Noviembre de 2013, 12:09:54
Prueba a darle prioridad a una interrupción sobre la otra, a ver si mejora.
Mira de usar priority (la ayuda te guiara en como usarlo).
Título: Re: Usart se bloquea
Publicado por: RALF2 en 01 de Noviembre de 2013, 12:35:45
Diego que modulos RF estas usando? te pregunto esto porque si operan como estos (http://www.google.co.ve/url?sa=i&source=images&cd=&docid=vkJ2Rksd2GlacM&tbnid=I9DLNEVJZ6_LAM:&ved=&url=http%3A%2F%2Farticulo.mercadolibre.com.ar%2FMLA-476322992-kit-modulos-rf-tx-rx-41800-y-43392-mhz-140-metros-_JM&ei=_slzUvf3I_HasAScw4GwCA&psig=AFQjCNFsTR1DHcQ7ir9ufyEDKdgXUp7zUA&ust=1383406462658338) es muy posible que sea el problema  :mrgreen:
Título: Re: Usart se bloquea
Publicado por: Diego E. en 01 de Noviembre de 2013, 14:01:17
Marcos, voy a probar con la prioridad, aunque con el chequeo redundante del pin RX que hice me funciona, pero quería hacerlo de una manera más ortodoxa.

RALF, estoy utilizando este, pero al igual que el que muestras el ruido no puede ser mayor, entregan unas descargas de ruido impresionantes, enloquecen cualquier sistema.

(http://www.electronicaestudio.com/i/f/Receptor%20LR.jpg)

Para desbloquear la interrupción hay alguna otra forma diferente a resetear el micro ?
Título: Re: Usart se bloquea
Publicado por: MGLSOFT en 01 de Noviembre de 2013, 14:10:52
Prueba a habilitar la opción errors, en la llamada a use rs232(), como te dijo Ralf, es mas prolijo..
Título: Re: Usart se bloquea
Publicado por: RALF2 en 01 de Noviembre de 2013, 14:11:19
Yo tengo un modulo de esos y es tal como me lo imagine.  :mrgreen:
El problema con esos modulos es la rafaga de ruido que cuelga el Usart del pic. Por eso utilizo los Xbee  :D  no tienen ese problema, para nada, si pudieras probarlos veras que todo te funcionara fino!

Una solucion podria ser utilizar un encoder (HT12E) del lado del transmisor y un decoder (HT12D) del lado del receptor, como una posible solucion. Esos chips son fantasticos para ser utilizados con esos modulos ruidosos   :mrgreen: o cualquier otro similar a estos.
Desgraciadamente no creo sinceramente que logres resolver el problema si utilizas esos modulos ruidosos conectados directamente con la usart del pic  :(  el ruido te colgara cada rato la Usart.
Puedes emplear comunicacion RS232 por software pero perderias la interrupcion.   :?
Título: Re: Usart se bloquea
Publicado por: Diego E. en 01 de Noviembre de 2013, 14:21:09
En algunas aplicaciones he utilizado Xbee, son excelentes, lamentablemente en esta aplicación está el PCB ya diseñado,.

Nunca he utilizado errors, por lo que he visto en el datasheet son dos banderas, una si no llega el stop y otra si hay desbordamiento del buffer, si alguna de estas banderas se activa con limpiarla se desbloquea la interrupción ?
Título: Re: Usart se bloquea
Publicado por: RALF2 en 01 de Noviembre de 2013, 14:36:13
Citar
si alguna de estas banderas se activa con limpiarla se desbloquea la interrupción ?
Cuando se bloquea el Usart se debe resetear el bit CREN, eso sino estoy equivocado, lo hace la option ERRORS; que te comente con anterioridad, eso podria ayudar pero con tanto ruido entrando por la usart  :?