TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: NoSepComo en 24 de Noviembre de 2017, 09:54:17

Título: Acceso UART en CCS
Publicado por: NoSepComo en 24 de Noviembre de 2017, 09:54:17
Buenas a tod@s,

A ver, tengo un problema con una comunicación serial, que me está trayendo de cabeza...
Intento crear una comunicación serie entre un programa en un PC y un PIC18f4520, pero antes pues voy probando lo básico, que es a enviar y recibir con un terminal y la PCB donde está el micro.
Para enviar no tengo ningún problema, pero no puedo recibir nada... Si incluyo un "getc()" en el código del bucle infinito, se bloquea el micro, si lo intento a través de la rutina int_RDA no hace ni caso. Os adjunto el código del programa
Código: [Seleccionar]
#include <18f4520.h>
#use delay(clock=20000000)  //Meto 20M por el cristal, a ver como va
#fuses XT, NOWDT, PUT, NOWRT, HS
//#use fast_io(B)
#use standard_io(C)
#byte CMCON = 0xFB4
#use rs232(baud=9600,xmit=pin_c6, rcv=pin_c7, bits=8, parity=N)

//Variables globales de programa
int16 retPreTrig = 100; //100 us para el pretrigger
int16 retardo = 59;
int16 ventana = 7;
int Pulsador = 0;
char ch;


#INT_RDA
void serial_isr()
{
    ch = getchar();
    output_high(PIN_B6);
    delay_ms(1000);
    output_low(PIN_B6);
    putc(ch);
}

#INT_COMP
void isr(void)
{
    if(Pulsador == 1)
    {
        //delay_ms(retardo);
        while(C1OUT != 1)
        {
        }
        if(C1OUT == 1)
        {
           delay_us(retPreTrig);
           output_high(PIN_C1);
           delay_ms(retardo);
           output_high(PIN_C0);
           delay_ms(ventana);
           output_low(PIN_C0);
           output_low(PIN_C1);
           Pulsador = 0;
        }
    }
}

void main()
{
    //Configuración de puertos e interrupciones
   CMCON = 0b00000110;
   setup_comparator(A0_A3_A1_A2);
   setup_vref(VREF_HIGH|15|VREF_F5);

   set_tris_b(0x00);
   set_tris_a(0x0F);
   set_tris_c(0x80);

   enable_interrupts(INT_RDA);
   enable_interrupts(INT_COMP);
   enable_interrupts(GLOBAL);

   output_c(0);
   output_b(0);
 

   //hilo principal
   while(TRUE)
   {
       delay_ms(100);

       if(input(PIN_B7)==1)
       {
           //putc('1');
           printf("HOLA");
           putc(ch);
           output_high(PIN_B6);
           delay_ms(1000);
           output_low(PIN_B6);
       }
       
   }
}
Estoy haciendo diversas pruebas y ya no se porque falla la verdad...
Agradezco cualquier ayuda.

Un saludo!
Título: Re:Acceso UART en CCS
Publicado por: MGLSOFT en 24 de Noviembre de 2017, 11:06:11
Primera cosa que veo mal, las temporizaciones de hasta un segundo dentro de las interrupciones, esta mal y deberas sacarlas para que funcione una interrupción adecuadamente, especialmente en las comunicaciones seriales.
Título: Re:Acceso UART en CCS
Publicado por: NoSepComo en 24 de Noviembre de 2017, 14:55:00
Hola MGLSOFT,

Gracias por tu respuesta lo primero. El Lunes cuando vuelva al curro lo pruebo y comento.
Un saludo!
Título: Re:Acceso UART en CCS
Publicado por: remi04 en 25 de Noviembre de 2017, 07:39:07
Los modulos usart suelen tener un fifo de 3 bytes “creo”, en la recepción.  Ese buffer hay que leerlo siempre antes de que se llene por que si se llena se activa el error de overflow y se para la recepcion de la usart hasta que la reinicies.

  A lo mejor en tu prueba, al enviar con la terminal estas enviando un caracter + CR+LF.  Si es asi y solo lees uno, en la siguiente vez se te parará el puerto.

 Yo siempre utilizo el bit CREN y habilito y detengo la recepción donde lo necesito. Si no, es que tienes que tener en cuenta todo lo que esperas que llegue a RX para que no desborde el fifo.
Título: Re:Acceso UART en CCS
Publicado por: KILLERJC en 25 de Noviembre de 2017, 12:09:09
Los modulos usart suelen tener un fifo de 3 bytes “creo”, en la recepción.  Ese buffer hay que leerlo siempre antes de que se llene por que si se llena se activa el error de overflow y se para la recepcion de la usart hasta que la reinicies.

Solo algunos PICs, la mayoria de la gama 16/18 poseen solo lugar para 1 solo byte, asi que la interrupcion debe ser atendida rapidamente.

Y tambien deberia quitar los delays de las interrupciones. Nada que lleve delay debe estar en una interrupcion.
Título: Re:Acceso UART en CCS
Publicado por: NoSepComo en 27 de Noviembre de 2017, 05:34:13
Hola a todos,

Gracias por vuestras respuestas lo primero.
He modificado el código para quitar delays en las interrupciones, y por descartar he comentado el código del comparador (que funcionaba bien), pero aún así sigue sin reconocer los datos entrantes, es como que no entrase en la rutina #INT_RDA. Sin embargo la parte de mandar datos funciona perfectamente y yo los veo en un terminal en el PC.
Os paso el código de nuevo:
Código: [Seleccionar]
#include <18f4520.h>
#use delay(clock=20000000)  //Meto 20M por el cristal, a ver como va
#fuses XT, NOWDT, PUT, NOWRT, HS
//#use fast_io(B)
#use standard_io(C)
#byte CMCON = 0xFB4
#use rs232(baud=9600,xmit=PIN_C6, rcv=PIN_C7, bits=8, parity=N)

//Variables globales de programa
int16 retPreTrig = 100; //100 us para el pretrigger
int16 retardo = 59;
int16 ventana = 7;
int Pulsador = 0;
int bandera = 0;
char ch;


#INT_RDA
void serial_isr()
{
    bandera = 1;
}

/*#INT_COMP
void isr(void)
{
    if(Pulsador == 1)
    {
        //delay_ms(retardo);
        while(C1OUT != 1)
        {
        }
        if(C1OUT == 1)
        {
           delay_us(retPreTrig);
           output_high(PIN_C1);
           delay_ms(retardo);
           output_high(PIN_C0);
           delay_ms(ventana);
           output_low(PIN_C0);
           output_low(PIN_C1);
           Pulsador = 0;
        }
    }
}*/

void main()
{
    //Configuración de puertos e interrupciones
   //CMCON = 0b00000110;
   //setup_comparator(A0_A3_A1_A2);
   //setup_vref(VREF_HIGH|15|VREF_F5);

   set_tris_b(0x00);
   set_tris_a(0x0F);
   set_tris_c(0x80);

   enable_interrupts(GLOBAL);
   enable_interrupts(INT_RDA);
   //enable_interrupts(INT_COMP);
   

   output_c(0);
   output_b(0);
 

   //hilo principal
   while(TRUE)
   {
       delay_ms(100);

       if(input(PIN_B7)==1)
       {
           //putc('1');
           printf("HOLA");
           //putc(ch);
           output_high(PIN_B6);
           delay_ms(1000);
           output_low(PIN_B6);
       }

       if(bandera==1)
       {
           output_high(PIN_B6);
           delay_ms(1000);
           output_low(PIN_B6);
           bandera = 0;
       }
   }
}
A alguien se le ocurre que puede fallar?
Gracias por vuestra ayuda
Título: Re:Acceso UART en CCS
Publicado por: remi04 en 27 de Noviembre de 2017, 13:57:39
Cambia tu main completo por este que te pongo y cárgalo (es para probar la comunicación basica).  Configura el terminal del pc para que envíe solo el carácter sin incluir LF +CR sin NULL ni nada, que no envíe nada, solo el carácter tecleado.

  Conecta la terminal y arranca el programa, mira a ver si te devuelve el carácter que le das en cada pregunta. La pregunta se repetirá.

 
Código: C
  1. void main()
  2. {
  3.    set_tris_b(0x00);
  4.    set_tris_a(0x0F);
  5.    set_tris_c(0x80);
  6.    output_c(0);
  7.    output_b(0);
  8.  
  9.    while(1)
  10.                {
  11.                  printf("Escribe un caracter: ");
  12.                  ch = getchar();
  13.                  printf("El caracter recibido es: %c \r\n",ch);
  14.                }
  15.    
  16. }

Si te aparece la pregunta pero por mucho que le envíes, de ahí no pasa, pon esta directiva:

Código: C
  1. #bit CREN=getenv("BIT:CREN")


y el main lo cambias por este:

Código: C
  1. void main()
  2. {
  3.    CREN = 0;
  4.    set_tris_b(0x00);
  5.    set_tris_a(0x0F);
  6.    set_tris_c(0x80);
  7.    output_c(0);
  8.    output_b(0);
  9.  
  10.    while(1)
  11.                {
  12.                  printf("Escribe un caracter: ");
  13.                  CREN = 1;
  14.                  ch = getchar();
  15.                  CREN = 0;
  16.                  printf("El caracter recibido es: %c \r\n",ch);
  17.                }
  18.    
  19. }
 

A ver que pasa.
Título: Re:Acceso UART en CCS
Publicado por: NoSepComo en 27 de Noviembre de 2017, 14:27:56
Hola,
Muchas gracias por tu respuesta.
He probado el código que me has pasado, pero en ninguno de los dos casos consigo que avance más allá de la primera pregunta, parece que el getchar lo bloquea ahí...
No tengo ni idea de que pasa, he probado con otro micro por si se hubiese estropeado, pero pasa igual.
El circuito que tengo es sencillo, simplemente el micro (pic18f4520) conectado a un MAX232, con un cristal de 20 MHz y el MAX a un conector de 3 salidas y eso al PC.
Si el fallo estuviese en el hardware entiendo que no debería funcionar el envío de datos tampoco..., además en el conector del MAX cuando pongo el multímetro y envío datos desde el PC, varía la tensión, pero el micro no lo recibe...
A alguien se le ocurre algo (también probé a reinstalar el compilador de CCS por una versión más actual a ver que pasaba pero es igual...).

Gracias de antemano y un saludo.
Título: Re:Acceso UART en CCS
Publicado por: KILLERJC en 27 de Noviembre de 2017, 14:40:48
el getchar y sus variantes es bloqueante, es decir mientras no reciba nada queda encerrado en la funcion a la espera de un caracter.
Título: Re:Acceso UART en CCS
Publicado por: NoSepComo en 27 de Noviembre de 2017, 14:52:47
Hola Killer,

Graias por la respuesta.
He estado comprobando mejor las patillas del micro y he notado que de la RC7 (RX) no hay cambios en la tensión al enviar datos al micro, sin embargo en la entrada del MAX si que hay variaciones de tensión que no salen de él. Asique mañana desoldaré el MAX y lo sustituiré por otro y también revisaré el circuito de acondicionamiento a ver que pasa y os seguiré contando.

Muchas gracias por vuestras respuestas
Título: Re:Acceso UART en CCS
Publicado por: remi04 en 27 de Noviembre de 2017, 16:06:25
Hola,
Muchas gracias por tu respuesta.
He probado el código que me has pasado, pero en ninguno de los dos casos consigo que avance más allá de la primera pregunta, parece que el getchar lo bloquea ahí...
No tengo ni idea de que pasa, he probado con otro micro por si se hubiese estropeado, pero pasa igual.
El circuito que tengo es sencillo, simplemente el micro (pic18f4520) conectado a un MAX232, con un cristal de 20 MHz y el MAX a un conector de 3 salidas y eso al PC.
Si el fallo estuviese en el hardware entiendo que no debería funcionar el envío de datos tampoco..., además en el conector del MAX cuando pongo el multímetro y envío datos desde el PC, varía la tensión, pero el micro no lo recibe...
A alguien se le ocurre algo (también probé a reinstalar el compilador de CCS por una versión más actual a ver que pasaba pero es igual...).

Gracias de antemano y un saludo.

 Eso ya es el siguiente paso, comprobar el hardware del max232 y demás. Si no te ha funcionado lo que te he puesto el fallo lo tienes en el hard, no cabe más.

   Por supuesto que puede funcionar el envío pero no la recepción o viceversa, son dos canales totalmente independientes, idénticos pero en sentidos opuestos.

   En estos casos es cuando echo mano del osciloscopio y localizo de inmediato donde está el problema.

Y como te ha dicho Killer, las funciones Getc, Getchar, Gets, etc detienen el programa hasta que se recibe un dato. Una forma de evitar que se pare el programa es utilizando la función kbhit(), que devuelve TRUE cuando se ha recibido algo. Lo puedes meter en un bucle while o for para hacer un timeout, tiempo de espera prudencial, si no se recibe se abandona el bucle.

   Saludos.

 
Título: Re:Acceso UART en CCS
Publicado por: NoSepComo en 28 de Noviembre de 2017, 12:24:17
Hola Remi,

Gracias por la respuesta. He intentado probar el código que me has mandado  con una simulación en Proteus. Aún así no soy capaz de que me funcione, sigo con la duda si será algún problema del compilador o no. Porque estoy intentando en proteus simular una comunicación sencilla entre dos micros y no me funciona (conecto RX del 1º con Tx del segundo y viceversa). El programa simplemente al pulsar un botón envía un caracter por el TX y el segundo PIC tiene una rutina rda que activa una bandera y en el código principal debería encender un led... No tengo errores al compilar o similar pero no funciona.
Parece que cuando envía el dato, el segundo micro queda colgado y no hace nada (y no hay ningún getchar o similar)...

Que pensáis?
Gracias por cualquier ayuda.
Título: Re:Acceso UART en CCS
Publicado por: KILLERJC en 28 de Noviembre de 2017, 14:17:41
Uni el RX con el TX del mismo PIC y cambia el programa por:

Código: C
  1. void main(void)
  2. {
  3.    set_tris_b(0x00);
  4.    set_tris_a(0x0F);
  5.    output_b(0);
  6.  
  7.    putc('a');
  8.    while(1)
  9.                {
  10.                  if(kbhit())
  11.                  {
  12.                      putc(getchar());
  13.                      output_toggle(PIN_B0);
  14.                   }
  15.                }
  16.    
  17. }

Basicamente utiliza el mismo TX para enviar un caracter que es 'a' y se lo envia al mismo micro. Al recibirlo se detecta en el while, por lo cual se envia nuevamente, asi siempre esta enviando y recibiendo. Cada ves que recibe un dato, el pin B0 deberia cambiar su estado. Esto es lo mas simple sin irte a usar otro micro. Y si bajas los baudios podrias llegar a verlo a simple vista.

Si aun asi no funciona debera ser la configuracion agergale el ERRORS, asi resetea la UART ante cualquier error cuando ocurra.

Código: C
  1. #use rs232(baud=9600,xmit=PIN_C6, rcv=PIN_C7, bits=8, parity=N, ERRORS)

Si aun asi no funciona ni en la simulacion, quedan 2 cosas. La simulacion no es buena, o que el micro tenga algo malo.
Título: Re:Acceso UART en CCS
Publicado por: micronet3 en 28 de Noviembre de 2017, 14:50:14
TU CRYSTAL ES es de 20MHZ , por lo tanto tu fuse es hs no xt
Título: Re:Acceso UART en CCS
Publicado por: NoSepComo en 30 de Noviembre de 2017, 04:52:35
Hola gente.

He probado la sugerencia de quitar el fuse XT, tenía puestos los dos por que no me di cuenta...
El código de KillerJC funciona en Proteus bien, y esto si que es un poco de locos, ahora me funciona la recepción en el micro pero no la transmisión :P... os pongo el código:
Código: [Seleccionar]
#include <18f4520.h>
#USE delay(clock=20000000)  //Meto 20M por el cristal, a ver como va
#fuses NOWDT, PUT, NOWRT, HS
#USE standard_io(C)
#byte CMCON = 0xFB4
#use rs232(baud=9600,xmit=PIN_C6, rcv=PIN_C7, bits=8, parity=N, ERRORS)

//Variables globales de programa
int16 retPreTrig = 100; //100 us para el pretrigger
int16 retardo = 59;
int16 ventana = 7;
int Pulsador = 0;
int bandera = 0;
char ch;


#INT_RDA
void serial_isr(void)
{
    ch=getchar();
    bandera = 1;
}
void main()
{
   //CREN = 0;
   set_tris_b(0x80);
   set_tris_a(0x0F);
   //set_tris_c(0x80);
   //output_c(0);
   output_b(0);

   enable_interrupts(GLOBAL);
   enable_interrupts(INT_RDA);

   while(1)
               {
       /*if(kbhit())
       {
           output_toggle(PIN_B6);
           delay_ms(500);
       }*/
       if(bandera==1)
       {
           output_toggle(PIN_B6);
           putc(ch);
           puts(ch);
           bandera=0;
       }
       if(input(PIN_B7)==1)
       {
           //printf("HOLA");
           putc('c');
           output_high(PIN_B6);
           delay_ms(1000);
           output_low(PIN_B6);
       }
               }

}

Asique estoy loquísimo con esto, he probado con distintos comandos pero nada... Se os ocurre que puede estar sucediendo.

Gracias y un saludo!
Título: Re:Acceso UART en CCS
Publicado por: remi04 en 01 de Diciembre de 2017, 05:54:28
Haz otra prueba de hardware, desconecta el tx y el rx del max al micro, unelos en el max. Es decir, une el tx del max con el rx del max, del micro olvidate ahora. Conecta el terminal y prueba a enviar un caracter, tienes que recibirlo a la misma vez.

  Ya es para descartar que tengas problemas de conexiones. ¿Puedes poner alguna foto donde se vea como tienes montado el circuito??
Título: Re:Acceso UART en CCS
Publicado por: NoSepComo en 04 de Diciembre de 2017, 08:32:06
Hola a todos,
He hecho un nuevo descubrimiento, os pego el código que estoy utilizando, a ver si vosotros entendéis mejor que yo lo que sucede:
Código: [Seleccionar]
#include <18f4520.h>
#use delay(clock=20000000)  //Meto 20M por el cristal, a ver como va
#fuses NOWDT, PUT, NOWRT, HS
#use fast_io(B)
#use standard_io(C)
#use rs232(baud=9600,xmit=PIN_C6, rcv=PIN_C7, bits=8, parity=N, ERRORS)

//Variables globales de programa
int bandera = 0;
char ch;


#INT_RDA
void serial_isr(void)
{
    ch=getchar();
    bandera = 1;
}


void main()
{
    //Configuración de puertos e interrupciones
   set_tris_b(0x80);
   set_tris_a(0x0F);
   set_tris_c(0x80);

   //output_c(0);
   output_low(PIN_C6);
   output_b(0);

   enable_interrupts(GLOBAL);
   enable_interrupts(INT_RDA);
 

   //hilo principal
   while(TRUE)
   {
       delay_ms(100);

       if(input(PIN_B7)==1)
       {
           //putc('1');
           printf("HOLA");
           //putc(ch);
           output_high(PIN_B6);
           delay_ms(1000);
           output_low(PIN_B6);
       }

       if(bandera==1)
       {
           output_toggle(PIN_B6);
           printf("retardo = %c ",ch);
           bandera=0;
       }
       /*if(kbhit()==1)
       {
           ch=getchar();
           output_high(PIN_B6);
           delay_ms(1000);
           output_low(PIN_B6);
           putc(ch);
       }*/
   }
}

Pues resulta que, si dejo ese output_c(0) sin comentar (al principio del main) me funciona el micro sólo para recibir datos, pero no es capaz de enviar nada, sin embargo si lo dejo comentado (o con el PIN_C7 sin tocar) me funciona la transmisión solamente pero no la recepción. No tengo ni idea de lo que pasa pero acotando he visto que el fallo está ahí.
A ver que se os ocurre a vosotros.

Muchas gracias por cualquier ayuda y un saludo!
Título: Re:Acceso UART en CCS
Publicado por: KILLERJC en 04 de Diciembre de 2017, 14:36:33
Citar
Pues resulta que, si dejo ese output_c(0) sin comentar (al principio del main) me funciona el micro sólo para recibir datos, pero no es capaz de enviar nada, sin embargo si lo dejo comentado (o con el PIN_C7 sin tocar) me funciona la transmisión solamente pero no la recepción. No tengo ni idea de lo que pasa pero acotando he visto que el fallo está ahí.

CCS cambia los pines como entradas/salidas segun si usas input o output, para que CCS no haga eso sobre algun puerto usa:

Código: C
  1. #USE FAST_IO(C)

De esa forma va a hacer caso al set_tris_c()
Sino va a seguir cambiandolo como quiera el compilador.