TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: guillotte en 05 de Junio de 2007, 23:07:54

Título: Interrupciones RS232 AYuda por favor
Publicado por: guillotte en 05 de Junio de 2007, 23:07:54
Estoy realizando un pequeño proyectito y no se como recibir por interrupciones a traves de rs 232. He probado de todo hace dias que estoy luchando pero no hay caso. Si alguien tiene un ejemplito que me pueda servir le estaria muy agradecido.
Por las dudas estoy programando en C, y el micro que quiero manejar es el 18F252.
Título: Re: Interrupciones RS232 AYuda por favor
Publicado por: micro_cadaver en 05 de Junio de 2007, 23:26:47
puedes postear tu codigo? a ver si ahi mismo  encontramos el error, yo uso el C18 para el C de los 18FXXXX
Título: Re: Interrupciones RS232 AYuda por favor
Publicado por: guillotte en 06 de Junio de 2007, 09:58:54
Hay pego una parte del programa, que para mi es la parte donde yo tengo problemas.
De todas maneras si necesitas pego todo el programa. La funcion void salida() la utilizo para separar el paquete que envio desde un programa de visual, esto anda bien porque lo he probado recibiendo sin interrupciones y recibe bien. pero cada 4 o 10 se detiene el proseso o se tilda.
Desde ya muchas gracias y disculpe las molestias ocacionadas

#include "C:\Documents and Settings\usuario\Mis documentos\Montes\18F252\final3\final3.h"
#include <KBD.C>
#include <24256.C>
#include <STDLIB.H>
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,restart_wdt)

static int reloj,Tiempo_testeobat;
static int TIME_APAGADO;
         *
         * Hay otra varibles declaradas
         *
#int_RTCC
RTCC_isr()
{
reloj++;
Tiempo_testeobat++;
TIME_APAGADO++;
}
//******************************************************************************
#int_RDA       //cuando llega un dato habilito band_rx y capturo el dato
RDA_isr()
{
 
 if(kbhit())
  {
      rxdato=getc();
      bandera_rxdato=true;
      var++;
     }
}

   *
   *
void salida()
{
if(bandera_rxdato==true)
   {
   bandera_conv=false;
      if(var==1)
      {
          if(rxdato==0xf0)//si es f0 es la direccion del hand
           {
            destino=rxdato;
            bandera_rxdato=false;
           }
          else          //si no salgo
           {
            rxdato=0;
            bandera_rxdato=false;
            var=0;
            bandera_conv==true;
           }
      }
      if(var==2)
      {
         origen=rxdato;
         bandera_rxdato=false;
      }
      if(var==3)
      {
         comando=rxdato;
         bandera_rxdato=false;
      }
      if(var==4)
      {
         dir_a=rxdato;
         bandera_rxdato=false;
      }
      if(var==5)
      {
         dir_b=rxdato;
         bandera_rxdato=false;
      }
      if(var==6)
      {
         contador=rxdato;
         bandera_rxdato=false;

       }
      if(var==7)
      {
         valor=rxdato;
         bandera_rxdato=false;
         var=0;
         Termino_salida=true;
         bandera_conv=true;
      }

    }
    return ;
}

   *
   *

void main()
{
   port_b_pullups(TRUE);

   SET_TRIS_A(0x01);//10000 22/06/07
   SET_TRIS_C(0x00);
   setup_adc_ports(AN0);
   setup_adc(ADC_CLOCK_INTERNAL);

   setup_spi(FALSE);
   //setup_adc_ports(NO_ANALOGS);
   //setup_adc(ADC_OFF);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_128|RTCC_8_bit);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);

   enable_interrupts(INT_RTCC);
   //enable_interrupts(INT_RDA); Interrupcion recepcion rs232
   enable_interrupts(GLOBAL);
   init_ext_eeprom();
   kbd_init();
    *
    *
    *

}
Título: Re: Interrupciones RS232 AYuda por favor
Publicado por: micro_cadaver en 06 de Junio de 2007, 10:36:53
m... codigo es en CCS, no lo domino mucho, puedo sospechar por otro lado de tu rutina de interrupcion del RDA supongo que esa es la del EUSART, porque la veo muy extensa... para ser una interrupción, otra cosa ... donde defines si tienes prioridad en las interrupciones? o esta en modo compatibilidad? una cosa mas, no se si sera a proposito pero la habilitacion del RDA esta en off.
Título: Re: Interrupciones RS232 AYuda por favor
Publicado por: guillotte en 06 de Junio de 2007, 11:29:30
PUEDE SER LO DE LA PREORIADAD,  SE ME PASO ES QUE ANTERIORMENTE ESTUVE PROBANDO CON OTRA PARTE DEL PROGRAMA Y ME OLVIDE DE SACARLO. (ES SIN LAS //)

Y RDA NO CREO QUE SEA TAN LARGO SOLO TIENE 3 ASIGNACIONES Y UNA PREGUNTA DE TODOS MODOS LO HE PROBADO SOLO PONIENDO LA CAPTURA DEL DATO Y NADA.
EN QUE LENGUAJE TRABAJAS? PORQUE UNA DE ESAS PUEDA TOMAR TU EJEMPLO.
GRACIAS POR RESPONDER.
Título: Re: Interrupciones RS232 AYuda por favor
Publicado por: micro_cadaver en 06 de Junio de 2007, 11:43:16
yo programo en C18, volviendo a tu caso lo que estaba en //

   //enable_interrupts(INT_RDA); Interrupcion recepcion rs232
 
de eso entiendo que solo sirve para habilitar la interrupcion del EUSART, a lo que me referia era al bit de prioridades  IPEN del registro RCON, eso es lo malo que me falta level para ayudarte porque no uso el CCS para los 18FXX, pero de todas formas ese bit tiene que ser declarado en alguna libreria de la interrupcion, porque este pic puede tener interrupcion de jerarquia alta o baja, donde la alta puede interrumpir a la interrupcion de baja jerarquia. Estoy seguro que mas gente posteara y te ayudara.  :-/
Título: Re: Interrupciones RS232 AYuda por favor
Publicado por: guillotte en 06 de Junio de 2007, 11:54:27
Muchas gracias por tu aporte indagare en las preoridades. Y por tu respuesta tan rapida.
Título: Re: Interrupciones RS232 AYuda por favor
Publicado por: MGLSOFT en 07 de Junio de 2007, 19:50:05
Busca en la ayuda de #Priority...
Ademas deberias activar el manejo de errores de la Usart, busca y lee en #Use RS232 en la seccion ERRORS... :mrgreen: :mrgreen:
El colgado de la recepcion a mi se me producia por errores de recepcion, que cuando es por software no debes preocuparte ya que lo hace solo..
Título: Re: Interrupciones RS232 AYuda por favor
Publicado por: guillotte en 08 de Junio de 2007, 08:30:01
Ok, estuve viendo el Datasheet pic 18f252 tiene diferentes bancos y si no mal entendi los registros donde trabaja la parte de comunicacion es el banco 15. De todos modos sigo probando y nada. Puedo enviar del pic pero no puedo recibir. Ahora voy a indagar en priority. Mil Gracias por responder.
Título: Re: Interrupciones RS232 AYuda por favor
Publicado por: micro_cadaver en 08 de Junio de 2007, 09:00:31
mmm.... sabes que modulo posee el PIC con el protocolo RS232, ese modulo se llama EUSART, busca ese modulo en tu datasheet y nos comentas.
Título: Re: Interrupciones RS232 AYuda por favor
Publicado por: guillotte en 08 de Junio de 2007, 12:31:57
Los registros que usan son:
INTCONPIR1,PIE1:IPR1;RCSTA;TXREG;TXSTA;SPBRG.
El registro que comentas no lo tengo. estos registros son sacados de la hoja de datos. Lo que pasa que para configurar sestos registros tengo que hacer referencia al numero de banco de memoria y en eso tengo dudas pero sigo buscando.
Título: Re: Interrupciones RS232 AYuda por favor
Publicado por: micro_cadaver en 08 de Junio de 2007, 13:00:46
ya esta bien a esos registros me referia. lo del EUSART es el nombre de todo el modulo de transmisión. leelos y no te preocupes mucho de las configuraciones de bancos porque el CCs te lo pone todo en bandeja de plata  :mrgreen:
Título: Re: Interrupciones RS232 AYuda por favor
Publicado por: microman en 08 de Junio de 2007, 13:36:35
En lugar de enviar secuencialmente los datos via serial deberias enviar un string de caracteres y luego simplemente deberas almacenarlo en un array para luego procesarlo. Para ello seria conveniente que definas una estructura de la trama que enviaras desde la PC hacia tu micro.

Una estructura de trama podria ser el siguiente:
ID_trama;Dir_origen;Dir_destino;dato;chk

Donde:

ID_trama seria un caracter ASCII : 1byte
Dir_origen codificado en HEX en formato ASCII: cantidad de bytes requeridos asi para enviar la dir 0xF0 se necesitan 4 bytes
Dir_destino codificado en HEX en formato ASCII: cantidad de bytes requeridos asi para enviar la dir 0xF00 se necesitan 5 bytes
dato: de acuerdo a que quieras enviar aqui puede ser variable desde 1 byte hasta n (n un numero suficiente de acuerdo a las necesidades)
chk: es opcional, es un checksum para control de errores. Obviamente requerira un procesamiento adicional.
; : el punto y coma es un separador de campos, de esta forma se facilita la identificacion de los campos y posterior procesam.

Un ejem de trama seria:
C;0xFE;0XED;hola;1F

De esta forma tienes una cadena con 19 caracteres. Puedes delimitar tu proyecto a 32 caracteres como máximo.

Bueno en CCS escribirias algo asi:

#include "C:\Documents and Settings\usuario\Mis documentos\Montes\18F252\final3\final3.h"
#include <KBD.C>
#include <24256.C>
#include <STDLIB.H>
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,restart_wdt)

#define Lon_Trama 32

char Buffer_Rx[Lon_Trama];



static int reloj,Tiempo_testeobat;
static int TIME_APAGADO;
         *
         * Hay otra varibles declaradas
         *
#int_RTCC
RTCC_isr()
{
reloj++;
Tiempo_testeobat++;
TIME_APAGADO++;
}
//******************************************************************************
#int_RDA       //cuando llega un dato habilito band_rx y capturo el dato
RDA_isr()
{
   gets(Buffer_Rx);
   bandera_rxdato=true;
}
 *
   *
void salida()
{
//if(bandera_rxdato==true) seria mejor consultar dentro del main puesto asi no necesitarias realizar la llamada a la funcion
  // {

  bandera_rxdato=false; // aqui debes de limpiar tu bandera para que puedas ingresar la proxima vez
// En lugar de realizar if anidados seria mejor usar un switch-case
// Tb una vez desparseado tu trama en cada campo los valores ascii de las direcciones deberas convertirlos en valores enteros
// Utiliza para ello la funcion atoi()....espero esto t sirva

     if(var==1)
      {
          if(rxdato==0xf0)//si es f0 es la direccion del hand
           {
            destino=rxdato;
            bandera_rxdato=false;
           }
          else          //si no salgo
           {
            rxdato=0;
            bandera_rxdato=false;
            var=0;
            bandera_conv==true;
           }
      }
      if(var==2)
      {
         origen=rxdato;
         bandera_rxdato=false;
      }
      if(var==3)
      {
         comando=rxdato;
         bandera_rxdato=false;
      }
      if(var==4)
      {
         dir_a=rxdato;
         bandera_rxdato=false;
      }
      if(var==5)
      {
         dir_b=rxdato;
         bandera_rxdato=false;
      }
      if(var==6)
      {
         contador=rxdato;
         bandera_rxdato=false;

       }
      if(var==7)
      {
         valor=rxdato;
         bandera_rxdato=false;
         var=0;
         Termino_salida=true;
         bandera_conv=true;
      }

   // }
    return ;
}

   *
   *

void main()
{
   port_b_pullups(TRUE);

   SET_TRIS_A(0x01);//10000 22/06/07
   SET_TRIS_C(0x00);
   setup_adc_ports(AN0);
   setup_adc(ADC_CLOCK_INTERNAL);

   setup_spi(FALSE);
   //setup_adc_ports(NO_ANALOGS);
   //setup_adc(ADC_OFF);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_128|RTCC_8_bit);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);

   enable_interrupts(INT_RTCC);
   enable_interrupts(INT_RDA); Interrupcion recepcion rs232
   enable_interrupts(GLOBAL);
   init_ext_eeprom();
   //kbd_init();

    *
    *
    *
while (TRUE) // si no colocas dentro de un bucle infinito una vez terminada la ultima linea de tu funcion main () tu micro se queda sin hacer mas nada....o es eso lo que deseas :shock:?
{
    if(bandera_rxdato==true)
      salida();

   //****** tu codigo restante

}


}


Espero te sirva...

Saludos

Título: Re: Interrupciones RS232 AYuda por favor
Publicado por: guillotte en 08 de Junio de 2007, 14:34:09
Comprendido el mensaje, pero tengo problemas en la habilitacion de la interrupcion, mejor dicho yo creo que tengo problemas en la configuracion.  No lo puedo simularlo, pero dentro de la interrupcion he colocado un led de manera que cada vez  que pase por la interrupcion se prenda para saber que paso por la interrupcion. Pero nunca se prende.
Si se prende cuando transmite esta parte de transmitir lo hace bien.
Con respecto al resto del codigo es muy largo pero si les interesa lo agrego.
En este proyecto  trabajo con:
Pic 18f252.
Un teclado de 4x4.
Display de 4x20.
      *El display a su vez es manejado por un integrado 74ls164 para reducir pines.
memoria externa 24lc256
*Y a la vez el pic esta alimentado por una fuente Bost un elevador de tension que va de los 3.7v a 5.5V para poder alimentarlo.
La Fuente principal es una bateria de litio que la podemos encontrar en cualquier celular.


#int_RDA       //cuando llega un dato habilito band_rx y capturo el dato
RDA_isr()
{
if(kbhit())
 {
  rxdato=getc();
 bandera_rxdato=true;
   var++;
   output_high(pin_c1);  // con este pin veo si paso por la interrupcion.
    }
}

Título: Re: Interrupciones RS232 AYuda por favor
Publicado por: microman en 08 de Junio de 2007, 16:08:34
void main()
{
   port_b_pullups(TRUE);

   SET_TRIS_A(0x01);//10000 22/06/07
   SET_TRIS_C(0x00);//.... En esta sentencia estas diciendo q todo tu puerto C está como salida...sin embargo el pin Pin_C6 debes de estar config como entrada...sino no recibiras nada a traves del USART|
//SET_TRIS_C(0x40); prueba esto..
   setup_adc_ports(AN0);
   setup_adc(ADC_CLOCK_INTERNAL);

   setup_spi(FALSE);
   //setup_adc_ports(NO_ANALOGS);
   //setup_adc(ADC_OFF);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_128|RTCC_8_bit);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);


Saludos
Título: Re: Interrupciones RS232 AYuda por favor
Publicado por: guillotte en 08 de Junio de 2007, 17:35:29
Si es verdad no se como se me paso muchas gracias ya estoy llendo ha probarlo...
Título: Re: Interrupciones RS232 AYuda por favor
Publicado por: guillotte en 10 de Junio de 2007, 21:20:49
Bueno resultado positivo recibo por la usart!!!!  como le comente prende el led que puse como testigo pero cuando hago un eco de lo que recibo me devuelve 128 248 no se porque? :shock:
Se complico pero lo importante que recibo ahora sigo buscando el otro problema.
 cuando agrego gets(Buffer_Rx); no recibo nada  :shock:. bueno sigo probando y despues le comento el resultado.


Título: Re: Interrupciones RS232 AYuda por favor
Publicado por: microman en 11 de Junio de 2007, 21:15:28
Como estas enviando los valores..?...si lo envias en formato ASCII no deberias de tener problema...
El eco lo puedes implementar dentro mismo de tu rutina de interrupcion ..algo así..

#int_RDA       //cuando llega un dato habilito band_rx y capturo el dato
RDA_isr()
{
   gets(Buffer_Rx);
   bandera_rxdato=true;
   printf("%s",Buffer_Rx);
}


Saludos
Título: Re: Interrupciones RS232 AYuda por favor
Publicado por: jodorowsky en 12 de Junio de 2007, 02:12:15
Hola, como ya dijeron por ahi, es hacer un eco para comprobar si estás recibiendo bien, mira yo hice uno sencillo que ha parpadear un led en PIN_C5, como un segundero y si recibe algo por el puerto le hace un eco, lo simulé en proteus asi que debe servir ya que no tengo un 18f... para probarlo, por si acaso te paso este código que hace es y lo pruebas... si tienes el proteus simula ahi con el virtual  terminal....


#include <18F252.h>
#device adc=8
#use delay(clock=20000000)
#fuses NOWDT,WDT128,HS, NOPROTECT, NOOSCSEN, BROWNOUT, BORV42, PUT, STVREN, NODEBUG, NOLVP, NOWRT, NOWRTD, NOWRTB, NOWRTC, NOCPD, NOCPB, NOEBTR, NOEBTRB
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)

#byte port_c=7

#int_RDA
RDA_isr()
{ char x;
 
  x=getc();
  putc(x);
}

void main()
{
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_spi(FALSE);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
   enable_interrupts(INT_RDA);
   enable_interrupts(global);

   port_c=0x00;
   output_high(PIN_B5);
   while(true)
     { output_high(PIN_C5);
       delay_ms(500);
       output_low(PIN_C5);
       delay_ms(500);
     }
}


te adjunto el hex por si acaso quieras hacer algo...
Título: Re: Interrupciones RS232 AYuda por favor
Publicado por: guillotte en 12 de Junio de 2007, 11:31:56
Bueno les comento, Funciono  :-/  pero le remarco los errores que tuve.
como bien dijo microman, con el SET_TRIS_C(0x40);, yo tenia 0x00 en realidad 0x80.
Segundo error: configuracion USART yo configure en asembler
 void Inicializo_rs232()
   {
   #asm
   
   INI232:
                MOVLW   15            //seleccion del banco.
                MOVWF   BSR
         MOVLW   6              // con 6 cargo el spbrg con 9600baudios
                MOVWF   SPBRG           
         MOVLW   0X20           
                MOVWF   TXSTA               
            MOVLW   0X90             
         MOVWF   RCSTA         
   
   
   #endasm
   }
Pc y el pic deben trabajar a la misma velocidad sino devuelve cualquier cosa.
Bueno ahora estoy intentando con la trama que me comento microman, pero no  :(

 
Formato para recibir:
 #int_rda
   RDA_isr()
        {
         // gets(Buffer_Rx);=> cuando quiero recibir la trama completa no va no no.
          rxdato=RCREG; =>cuando recibo asi de a uno funciona bien.
          bandera_rxdato=true;   
          var++;
          }
cuando lo quiero convertir uso asi pero no se si esta bien.

origen=(atoi(Buffer_Rx[1])); estoy probando asi pero no anda sigo probando.

Bueno dejo la inquietud, Y muchas gracias por responder.
Título: Re: Interrupciones RS232 AYuda por favor
Publicado por: microman en 15 de Junio de 2007, 19:40:53
Citar
guillotte
void Inicializo_rs232()
   {
   #asm
   
   INI232:
                MOVLW   15            //seleccion del banco.
                MOVWF   BSR
         MOVLW   6              // con 6 cargo el spbrg con 9600baudios
                MOVWF   SPBRG           
         MOVLW   0X20           
                MOVWF   TXSTA               
            MOVLW   0X90             
         MOVWF   RCSTA         
   
   
   #endasm
   }
CCS tiene una directiva de preprocesador para la configuración eficiente del modulo USART ...te recomiendo q lo utilices...

Prueba con esto en la cabecera de tu programa:
Código: C
  1. #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
[/color] [/b]

Respecto a como recibis la cadena deberas de recordar que la funcion gets() recibe una cadena entera hasta que el ultimo caracter sea un caracter de fin de cadena (caracter null generalmente)....o bien un retorno de carro (ASCII decimal igual a 13 creo)... Recuerda que un sistema windows el retorno de carro viene acompañado de un caracter nueva linea (ASCII decimal igual a 10 creo)...
Si al procesar tu cadena en tu PC y lo envias al PIC olvidas colocar este caracter la funcion gets() se quedará en una espera infinita hasta que llegue dicho caracter...

La funcion atoi() convierte un string a entero tipo int... bien para poder aplicar deberas desempaquetar tu trama en campos donde esten los valores a convertir y cargarlo en otro array auxiliar (Utiliza la funcion memcopy para copiar parte de un string a otro...) para llevar a cabo la conversion.. si simplemente tu le pasas el nombre del arreglo Buffer_Rx lo que intentara tu funcion atoi() es realizar la conversion de la cadena entera alojada en dicho array...es decir hasta que encuentre un caracter de fin de cadena... No olvides esto puesto que es un punto muy critico a la hora de trabajar con cadenas o string...y seguro te dara dolores de cabeza..igual como yo los tuve.... :mrgreen:

Tambien asegurate al pasar el argumento a la funcion atoi() que esta sea por referencia...esto lo logras usando de esta forma
Si:
Código: C
  1. int aux[4]='\0';  //.... este es la manera de que inicializo mi string
  2. int valor;
  3. valor=atoi(&aux[0]);
Espero que te sea de ayuda....


Saludos..


Título: Re: Interrupciones RS232 AYuda por favor
Publicado por: guillotte en 20 de Junio de 2007, 10:09:53
Ok, entoces la funcion gets(); queda esperando. Y que funcion puedo usar o como puedo hacer?
Bueno te comento que estuve probando y envio los datos al pic y es como que algunos valores los tomas y otros no y los comparo con un numero y muestra un mensaje en el display. pero como te comente nose porque algunos valores los toma y otros no.
los cargo en un array y los comparo. bueno sigo probando....
gracias por responder.

Título: Re: Interrupciones RS232 AYuda por favor
Publicado por: microman en 26 de Junio de 2007, 16:41:29
Podrias levantar tu codigo para que se te pueda ayudar mejor.....
Título: Re: Interrupciones RS232 AYuda por favor
Publicado por: guillotte en 02 de Julio de 2007, 08:58:32
Bueno, muchisimas gracias por su preocupacion anduvo bien si alguien le interesa saber. El ccs tiene librerias de usar y no hace falta cofigurar en asm. Luego me fallo la memoria 24lc256 no funcionaba por lo tanto la cambie por otra y funciono  :-/ todo.
Bueno si le hace falta mas detalle solo pregunten... Desde ya muchas gracias por su ayuda.