TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: Rseliman en 04 de Julio de 2015, 14:44:14

Título: Pic16f628a USART problema para recibir
Publicado por: Rseliman en 04 de Julio de 2015, 14:44:14
Hola a todos , hace un tiempo ya que estoy lidiando con un pic 16 f y su UART , funciona perfectamente transmitiendo datos , pero a la hora de recibir , solo recibo basura ...simule en proteus y lo mismo , no se si es la libreria o me falta configurar algo , creo que no ...les paso el codigo a ver si me pueden dar una mano por favor programo en XC8 MPLABX version 3.0

les paso el programa casi completo completo   ... ...cuando le envio datos recibo basura ...

Muchisimas gracias a todos



Fuses

Código: [Seleccionar]
// PIC16F628A Configuration Bit Settings

// 'C' source line config statements

#include <xc.h>

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

// CONFIG
#pragma config FOSC = INTOSCIO  // Oscillator Selection bits (INTOSC oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
#pragma config WDTE = OFF       // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = OFF      // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD)
#pragma config BOREN = ON     // Brown-out Detect Enable bit (BOD disabled)
#pragma config LVP = ON       // Low-Voltage Programming Enable bit (RB4/PGM pin has PGM function, low-voltage programming enabled)
#pragma config CPD = OFF        // Data EE Memory Code Protection bit (Data memory code protection off)
#pragma config CP = OFF         // Flash Program Memory Code Protection bit (Code protection off)



libreria

Código: [Seleccionar]
Serial communication library for PIC16F series MCUs.

 Compiler: Microchip XC8 v1.12 (http://www.microchip.com/xc)

 Version: 1.0 (21 July 2013)

 MCU: PIC16F877A
 Frequency: 4MHz

                                     NOTICE

NO PART OF THIS WORK CAN BE COPIED, DISTRIBUTED OR PUBLISHED WITHOUT A
WRITTEN PERMISSION FROM EXTREME ELECTRONICS INDIA. THE LIBRARY, NOR ANY PART
OF IT CAN BE USED IN COMMERCIAL APPLICATIONS. IT IS INTENDED TO BE USED FOR
HOBBY, LEARNING AND EDUCATIONAL PURPOSE ONLY. IF YOU WANT TO USE THEM IN
COMMERCIAL APPLICATION PLEASE WRITE TO THE AUTHOR.


WRITTEN BY:
AVINASH GUPTA
me@avinashgupta.com

*******************************************************************************/
#include <stdint.h>
#include <xc.h>

#include "usart_pic16.h"

void USARTInit(uint16_t baud_rate)
{
    //Setup queue
    UQFront=UQEnd=-1;
        
    //SPBRG
    switch(baud_rate)
    {
     case 9600:
        SPBRG=25; //datasheets pagina 76 pic16f628
        break;
     case 19200:
        SPBRG=12;
        break;
     case 28800:
        SPBRG=42;
        break;
     case 33600:
        SPBRG=36;
        break;
    }
    //TXSTA
    TXSTAbits.CSRC=1;
    TXSTAbits.TX9=0;  //8 bit ttsransmission
    TXSTAbits.TXEN=1; //Transmit enable
    TXSTAbits.SYNC=0; //Async mode
    TXSTAbits.BRGH=1; //High speed baud rate

    //RCSTA
    RCSTAbits.SPEN=1;   //Serial port enabled
    RCSTAbits.RX9=0;    //8 bit mode
    RCSTAbits.CREN=1;   //Enable receive
    RCSTAbits.ADDEN=0;  //Disable address detection

    //Receive interrupt
    RCIE=1;
    PEIE=1;

    ei();
}

void USARTWriteChar(char ch)
{
  while(!PIR1bits.TXIF);

  TXREG=ch;
}

void USARTWriteString(const char *str)
{
  while(*str!='\0')
  {
      USARTWriteChar(*str);
      str++;
  }
}

void USARTWriteLine(const char *str)
{
    USARTWriteChar('\r');//CR
    USARTWriteChar('\n');//LF

    USARTWriteString(str);
}

void USARTHandleRxInt()
{
  if(RB1==1)
    RB1=0;
  else
    RB1=1;
  
    //Read the data
    char data=RCREG;

    //Now add it to q
    if(((UQEnd==RECEIVE_BUFF_SIZE-1) && UQFront==0) || ((UQEnd+1)==UQFront))
    {
        //Q Full
UQFront++;
if(UQFront==RECEIVE_BUFF_SIZE) UQFront=0;
    }

    if(UQEnd==RECEIVE_BUFF_SIZE-1)
        UQEnd=0;
    else
UQEnd++;

    URBuff[UQEnd]=data;

    if(UQFront==-1) UQFront=0;
    
}

char USARTReadData()
{
    char data;

    //Check if q is empty
    if(UQFront==-1)
return 0;

    data=URBuff[UQFront];

    if(UQFront==UQEnd)
    {
        //If single data is left
//So empty q
UQFront=UQEnd=-1;
    }
    else
    {
UQFront++;

if(UQFront==RECEIVE_BUFF_SIZE)
            UQFront=0;
    }

    return data;
}

uint8_t USARTDataAvailable()
{
    if(UQFront==-1) return 0;
    if(UQFront<UQEnd)
return(UQEnd-UQFront+1);
    else if(UQFront>UQEnd)
return (RECEIVE_BUFF_SIZE-UQFront+UQEnd+1);
    else
return 1;
}

void USARTWriteInt(int16_t val, int8_t field_length)
{
    char str[5]={0,0,0,0,0};
    int8_t i=4,j=0;

    //Handle negative integers
    if(val<0)
    {
        USARTWriteChar('-');   //Write Negative sign
        val=val*-1;     //convert to positive
    }
    else
    {
        USARTWriteChar(' ');
    }

    if(val==0 && field_length<1)
    {
        USARTWriteChar('0');
        return;
    }
    while(val)
    {
        str[i]=val%10;
        val=val/10;
        i--;
    }

    if(field_length==-1)
        while(str[j]==0) j++;
    else
        j=5-field_length;


    for(i=j;i<5;i++)
    {
        USARTWriteChar('0'+str[i]);
    }
}

void USARTGotoNewLine()
{
    USARTWriteChar('\r');//CR
    USARTWriteChar('\n');//LF
}

void USARTReadBuffer(char *buff,uint16_t len)
{
uint16_t i;
for(i=0;i<len;i++)
{
buff[i]=USARTReadData();
}
}
void USARTFlushBuffer()
{
while(USARTDataAvailable()>0)
{
USARTReadData();
}
}

Código: [Seleccionar]
/******************************************************************************

 Serial communication library for PIC16F series MCUs.

 Compiler: Microchip XC8 v1.12 (http://www.microchip.com/xc)

 MCU: PIC16F877A
 Frequency: 4MHz

                                     NOTICE

NO PART OF THIS WORK CAN BE COPIED, DISTRIBUTED OR PUBLISHED WITHOUT A
WRITTEN PERMISSION FROM EXTREME ELECTRONICS INDIA. THE LIBRARY, NOR ANY PART
OF IT CAN BE USED IN COMMERCIAL APPLICATIONS. IT IS INTENDED TO BE USED FOR
HOBBY, LEARNING AND EDUCATIONAL PURPOSE ONLY. IF YOU WANT TO USE THEM IN
COMMERCIAL APPLICATION PLEASE WRITE TO THE AUTHOR.


WRITTEN BY:
AVINASH GUPTA
me@avinashgupta.com

*******************************************************************************/

#ifndef USART_PIC16_H
#define USART_PIC16_H

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

//Constants
#define RECEIVE_BUFF_SIZE 64

//Varriables
volatile char URBuff[RECEIVE_BUFF_SIZE]; //USART Receive Buffer
volatile int8_t UQFront;
volatile int8_t UQEnd;

void USARTInit(uint16_t baud_rate);
void USARTWriteChar(char ch);
void USARTWriteString(const char *str);
void USARTWriteLine(const char *str);
void USARTWriteInt(int16_t val, int8_t field_length);
void USARTHandleRxInt();
char USARTReadData();
uint8_t USARTDataAvailable();
void USARTGotoNewLine();
void USARTReadBuffer(char *buff,uint16_t len);
void USARTFlushBuffer();



#ifdef __cplusplus
}
#endif

#endif /* USART_PIC16_H */


Código: [Seleccionar]
#include <stdint.h>
#include <xc.h>

#include "usart_pic16.h"

void interrupt ISR(void)
{
    if (RCIE && RCIF) {
        USARTHandleRxInt();
        return;
    }
}

Código: [Seleccionar]
#define _XTAL_FREQ 4000000
#include <xc.h>
#include <pic16f628a.h>
#include <stdio.h>
#include <stdlib.h>
#include "confbits.h"
#include "lcd.h"
#include "usart_pic16.h"
 

/* defino headers */


#define boton PORTBbits.RB4

//************************** defino funciones main *************************
void lcdout (int x , int y , char *b);
void led (void);
void init (void);
void web (void);
char data ;

unsigned char teclado (void);

//**************************************************************************
 unsigned char resultado = 0;


void main(void)
{
       init (); // inicializo el up
       Lcd_Init();
       Lcd_Clear();
       lcdout(4,1,"Programa"); // escribo lcd con datos de copyrights
       lcdout(2,2,"Copyrights 2015");
      
      
       USARTInit(9600);

     while(1)
      

   {
    
       //    if (teclado() == 1)
      {
       //led(); // prendo y apago led
      // web(); //transmito los datos al esp8266
      
        uint8_t n= USARTDataAvailable();

            //si tengo datos
            if(n!=0)
             {
               //leo el serie
               char  data=USARTReadData();
             Lcd_Clear();
             lcdout(1,1,data); // recibo repuesta de esp8266
             }

      
      }
  }
      
    
}
 
// ******************** inicializacion cpu ***************************  
void init (void)
{
   PCONbits.OSCF ;// reloj en 4 mhz
   CMCON = 0X07 ; //apaga los comparadores y habilita los pines de I/O
  TRISA = 0x00;
  PORTA = 0X00;
  TRISBbits.TRISB3 = 0; // led como salida
  TRISBbits.TRISB4 = 1; // boton como entrada
  TRISBbits.TRISB1 = 1; //terminal rx como entrada
  TRISBbits.TRISB2 = 1;
  
     }
Título: Re: Pic16f628a USART problema para recibir
Publicado por: RodrigoAndres en 04 de Julio de 2015, 22:45:31
No soy para nada experto pero tratare de ayudarte.

creo qe el error es que estas leyendo el dato en la rutina del main, pero tambien estas recibiendo el dato en la rutina de interrupcion:

EN LA INTERRUPCION:
Código: [Seleccionar]
void interrupt ISR(void)
{
    if (RCIE && RCIF) {
        USARTHandleRxInt();
        return;
    }
}

Código: [Seleccionar]
void USARTHandleRxInt()
{
  if(RB1==1)
    RB1=0;
  else
    RB1=1;
  
    //Read the data
    char data=RCREG;

    //Now add it to q
    if(((UQEnd==RECEIVE_BUFF_SIZE-1) && UQFront==0) || ((UQEnd+1)==UQFront))
    {
        //Q Full
UQFront++;
if(UQFront==RECEIVE_BUFF_SIZE) UQFront=0;
    }

    if(UQEnd==RECEIVE_BUFF_SIZE-1)
        UQEnd=0;
    else
UQEnd++;

    URBuff[UQEnd]=data;

    if(UQFront==-1) UQFront=0;
    
}

EN EL MAIN:
Código: [Seleccionar]
uint8_t n= USARTDataAvailable();

            //si tengo datos
            if(n!=0)
             {
               //leo el serie
               char  data=USARTReadData();
             Lcd_Clear();
             lcdout(1,1,data); // recibo repuesta de esp8266
             }

prueba a desactivar la interrupcion asi:

Código: [Seleccionar]
USARTInit(9600);
RCIE=0;

Saludos
Título: Re: Pic16f628a USART problema para recibir
Publicado por: KILLERJC en 05 de Julio de 2015, 04:36:01
Para RodrigoAndres

Para mi que estas equivocado Rodrigo, al menos de lo que lei del codigo.

USARTHandleRxInt() lo que hace esa funcion es guardar el dato en el buffer que crea el archivo USART_PIC16.H
Esa variable se llama URBuff[] y de tamaño RECEIVE_BUFF_SIZE
Usa dos indices : UQEnd y UQFront, el primero indica la posicion del ultimo valor que llego al buffer, y el otro indica la posicion del caracter que va a ser leido , ejemplo recibi 10 caracteres y lei solo 3, UQFront=2 y UQEnd=9  (recorda que incluye el 0)

Basciamente crea un array y lo va llenando.

Las demas funciones:

USARTDataAvailable()
Simplemente ve si hay un dato en el buffer ese craedo, devuelve 0 si no hay nada o un valor que es el tamaño del buffer

USARTReadData()
Devuelve el dato recibido

Al menos las funciones esas parecen estar bien.,

Para Rseliman

Lo que si le quitaria es el return a la funcion de interrupcion, es decir:

Código: C
  1. void interrupt ISR(void)
  2. {
  3.     if (RCIE && RCIF) {
  4.         USARTHandleRxInt();
  5.     }
  6. }

Ademas en tu codigo, segun como estas haciendo el main, estaria enviando al 1,1 todas letras asi que irian apareciendo letra por letra lo que le estas enviando.
es decir si mandas "HOLA" imagino que verias solo la "A" en la posicion 1,1 del LCD.
La unica que te queda para probar si es esto, es que mandes 1 por 1 despacio los datos. Asi podes verlo.
Si aun asi despues de todo esto NO te funciona ya miraria la configuracion del UART.

Si quisieras recibir todo junto ya deberias modificar el codigo, usar otras funciones y por ahi hasta modificar algunas como la de la interrupcion.
Título: Re: Pic16f628a USART problema para recibir
Publicado por: Rseliman en 05 de Julio de 2015, 10:04:39
No soy para nada experto pero tratare de ayudarte.

creo qe el error es que estas leyendo el dato en la rutina del main, pero tambien estas recibiendo el dato en la rutina de interrupcion:


Muchas gracias por la respuesta Rodrigo , sin importar si es o no , muchas veces cualquier repuesta ayuda a abrir los ojos de los programadores ...Gracias
Título: Re: Pic16f628a USART problema para recibir
Publicado por: Rseliman en 05 de Julio de 2015, 10:12:12
Para RodrigoAndres

Para mi que estas equivocado Rodrigo, al menos de lo que lei del codigo.

USARTHandleRxInt() lo que hace esa funcion es guardar el dato en el buffer que crea el archivo USART_PIC16.H
Esa variable se llama URBuff[] y de tamaño RECEIVE_BUFF_SIZE
Usa dos indices : UQEnd y UQFront, el primero indica la posicion del ultimo valor que llego al buffer, y el otro indica la posicion del caracter que va a ser leido , ejemplo recibi 10 caracteres y lei solo 3, UQFront=2 y UQEnd=9  (recorda que incluye el 0)

Basciamente crea un array y lo va llenando.

Las demas funciones:

USARTDataAvailable()
Simplemente ve si hay un dato en el buffer ese craedo, devuelve 0 si no hay nada o un valor que es el tamaño del buffer

USARTReadData()
Devuelve el dato recibido

Al menos las funciones esas parecen estar bien.,

Para Rseliman

Lo que si le quitaria es el return a la funcion de interrupcion, es decir:

Código: C
  1. void interrupt ISR(void)
  2. {
  3.     if (RCIE && RCIF) {
  4.         USARTHandleRxInt();
  5.     }
  6. }

Ademas en tu codigo, segun como estas haciendo el main, estaria enviando al 1,1 todas letras asi que irian apareciendo letra por letra lo que le estas enviando.
es decir si mandas "HOLA" imagino que verias solo la "A" en la posicion 1,1 del LCD.
La unica que te queda para probar si es esto, es que mandes 1 por 1 despacio los datos. Asi podes verlo.
Si aun asi despues de todo esto NO te funciona ya miraria la configuracion del UART.

Si quisieras recibir todo junto ya deberias modificar el codigo, usar otras funciones y por ahi hasta modificar algunas como la de la interrupcion.


Muchas gracias por la respuesta KillerJc ...lo que me esta pasando es lo siguiente ....inicio el programa y la interrupcion espera una tecla ...al escribir una A por ejemplo , me tira una serie de caracteres ....es como si no tuviese en cuenta la cantidad que le envio ...y a veces me muestra codigo que esta escrito al final del programa ...me explico ?? o sea ..toco una tecla y me tira parte del codigo escrito a la ultimo del mismo ...o sea es como si  UQEnd y UQFront no tuviesen valores reales ...no se si me explico ..

Gracias

Título: Re: Pic16f628a USART problema para recibir
Publicado por: KILLERJC en 05 de Julio de 2015, 14:25:08
Hay 3 cosas que me preocupan.. Como dije las funciones de la libreria parecen funcionar perfectamente, no las use pero siguiendo la logica del programa parece que si funciona.

1 - es el main. Hay llaves por demas {} , imagino que son del if, pero veo que no las comentaste. No se ni como es que compilo eso.
2 - la funcion lcdout() segun como este programado puede fallar , por lo que parece envia un string, y  normalmente un string en C es una coleccion de char + un caracter nulo , es decir '\0'. Ese caracter nulo se usa para saber cuando termina el string, con lo cual aca:

lcdout(4,1,"Programa");

Funcionaria ya que "Programa" en realidad es array[9]={'P','r','o','g','r','a','m','a','\0'} y estarias apuntando a la P al comienzo, es decir se le envia la direccion de comienzo. Por que es mas facil hacerlo con punteros

Mientras que cuando vos usas

lcdout(1,1,data);

ocurren 2 cosas que pueden hacer que falle lo que vos queres hacer, envias el contenido y por otro lado envias un solo caracter.
Asi que aca podes probar otra cosa

Si lcdout() acepta 1 solo caracter sin el caracter nulo entonces:

Código: C
  1. lcdour(1,1,&data);

Si lcdout() NO acepta sin el caracter nulo, es decir espera un string, podes hacer algo asi para intentar remediarlo

Código: C
  1. while(1)
  2.         {
  3.                 //si tengo datos
  4.                 if(USARTDataAvailable())
  5.                 {
  6.                         char data[2];
  7.                         data[0]=USARTReadData();
  8.                         data[1]='\0'
  9.                         Lcd_Clear();
  10.                         lcdout(1,1,data); // recibo repuesta de esp8266
  11.                 }
  12.        
  13.         }

3 - tamaño del buffer, en el .h esta definido en 64, lo cual estas ocupando 64 espacios de memoria sin sentido, achicalo a 10/15 , eso va a depender que rapido estes leyendo los datos guardados, a no ser que tengas que recibir los 64 datos para asi luego trabajar.

Citar
.y a veces me muestra codigo que esta escrito al final del programa
Esto no deberia pasar ni queriendo, ya que seria un poco imposible, en las PC "si se puede" por que los datos/instrucciones (Von Neumann) estan juntos y ante un buffer/stack overflow podria ocurrir que se libere informacion que no se deba. Pero aca esta limitado los limites de los punteros del buffer. Y es una arquitectura diferente ( Hardvard ).
Si esta sucediendo me parece mas un problema del simulador/debugger si es que estas usando... Ademas los 16F no poseen memoria lineal y creo que tampoco tienen acceso como datos la memoria flash, aparte de todo esto, el programa en C no es lo que se guarda en el micro, ni tampoco en ASM ya que estos son nemonicos y lo que se guarda son los OPcodes que no tienen ninguna relacion con las letras ni de ASM, ni de C. Asi que aun lo veo muchisimo mas improbable que sea un problema del micro.

Lo que si puede estar mostrando basura por redireccionarlo a otro lado. Y hasta no encontrar un caracter nulo agarrar todos los datos posibles ( de la memoria de datos ) y mostrarlos en el LCD
Título: Re: Pic16f628a USART problema para recibir
Publicado por: Rseliman en 05 de Julio de 2015, 14:47:26
Muchas gracias por la repuesta ..

en cuanto a las llaves es porque estaba simplificando parte para determinar el problema ...las llaves se anulan entre si por eso compila ...o sea las ignora ...

Ya encontr el problema ....la funcion andaba bien cuando lo que se enviaba eran caracteres ...solo caracteres , pero tal como vos lo decis ..estaba mesclando caracteres con strings ...

lo que si no pude entender es porque me imprimia parte del codigo ...la verdad no se , lo hacia en Proteus y en el protoboard tambien ....

Ahora veo las palabras completas , solo que de a una letra por ves ...y tengo que detectar un OK que viene del esp8266 placa wifi ....ya vere como lo resuelvo ...

Mil gracias por tu tiempo ...estoy a tus ordenes si te puedo servir para algo ...

te mando un Abrazo y nuevamente gracias



Hay 3 cosas que me preocupan.. Como dije las funciones de la libreria parecen funcionar perfectamente, no las use pero siguiendo la logica del programa parece que si funciona.

1 - es el main. Hay llaves por demas {} , imagino que son del if, pero veo que no las comentaste. No se ni como es que compilo eso.
2 - la funcion lcdout() segun como este programado puede fallar , por lo que parece envia un string, y  normalmente un string en C es una coleccion de char + un caracter nulo , es decir '\0'. Ese caracter nulo se usa para saber cuando termina el string, con lo cual aca:

lcdout(4,1,"Programa");

Funcionaria ya que "Programa" en realidad es array[9]={'P','r','o','g','r','a','m','a','\0'} y estarias apuntando a la P al comienzo, es decir se le envia la direccion de comienzo. Por que es mas facil hacerlo con punteros

Mientras que cuando vos usas

lcdout(1,1,data);

ocurren 2 cosas que pueden hacer que falle lo que vos queres hacer, envias el contenido y por otro lado envias un solo caracter.
Asi que aca podes probar otra cosa

Si lcdout() acepta 1 solo caracter sin el caracter nulo entonces:

Código: C
  1. lcdour(1,1,&data);

Si lcdout() NO acepta sin el caracter nulo, es decir espera un string, podes hacer algo asi para intentar remediarlo

Código: C
  1. while(1)
  2.         {
  3.                 //si tengo datos
  4.                 if(USARTDataAvailable())
  5.                 {
  6.                         char data[2];
  7.                         data[0]=USARTReadData();
  8.                         data[1]='\0'
  9.                         Lcd_Clear();
  10.                         lcdout(1,1,data); // recibo repuesta de esp8266
  11.                 }
  12.        
  13.         }

3 - tamaño del buffer, en el .h esta definido en 64, lo cual estas ocupando 64 espacios de memoria sin sentido, achicalo a 10/15 , eso va a depender que rapido estes leyendo los datos guardados, a no ser que tengas que recibir los 64 datos para asi luego trabajar.

Citar
.y a veces me muestra codigo que esta escrito al final del programa
Esto no deberia pasar ni queriendo, ya que seria un poco imposible, en las PC "si se puede" por que los datos/instrucciones (Von Neumann) estan juntos y ante un buffer/stack overflow podria ocurrir que se libere informacion que no se deba. Pero aca esta limitado los limites de los punteros del buffer. Y es una arquitectura diferente ( Hardvard ).
Si esta sucediendo me parece mas un problema del simulador/debugger si es que estas usando... Ademas los 16F no poseen memoria lineal y creo que tampoco tienen acceso como datos la memoria flash, aparte de todo esto, el programa en C no es lo que se guarda en el micro, ni tampoco en ASM ya que estos son nemonicos y lo que se guarda son los OPcodes que no tienen ninguna relacion con las letras ni de ASM, ni de C. Asi que aun lo veo muchisimo mas improbable que sea un problema del micro.

Lo que si puede estar mostrando basura por redireccionarlo a otro lado. Y hasta no encontrar un caracter nulo agarrar todos los datos posibles ( de la memoria de datos ) y mostrarlos en el LCD
Título: Re: Pic16f628a USART problema para recibir
Publicado por: KILLERJC en 05 de Julio de 2015, 15:08:21
lo que si no pude entender es porque me imprimia parte del codigo ...la verdad no se , lo hacia en Proteus y en el protoboard tambien ....

Estas seguro que era parte del codigo o solo eran los datos ?, por ejemplo "Copyrights 2015" o "Programa" , etc

Ahora veo las palabras completas , solo que de a una letra por ves ...y tengo que detectar un OK que viene del esp8266 placa wifi ....ya vere como lo resuelvo ...

Eso lo podes solucionar, imagino que el ESP8266 te envia un retorno de carro y salto a nueva linea no? es decir un \r\n al final. o aunque sea un \n o un \r solo.
En tu rutina de interrupcion podrias hacer un:

Código: C
  1. // Aca arriba utilizo el handler
  2. if ( URBuff[UQEnd)=='\n')                                // Leo el ultimo valor que llego, UQEnd no deberia ser nunca -1 por que ya supuestamente llego un dato.
  3. {
  4.     g_cantidad_datos=USARTDataAvailable();     //Guardo la cantidad de datos hasta '\n', variable global
  5. }

Y luego cuando lees haces un:

Código: C
  1. while(1)
  2.                 if(g_cantidad_datos)    // Hay algo? es decir se completo una palabra?, recordar iniciarlo en 0 a esa variable global.
  3.                 {
  4.                         char data[20];                                                   // Esto es para guardarlo en otro lugar, recordar que tiene un tamaño maximo de 19 caracteres por ser 20.
  5.                         USARTReadBuffer(data,g_cantidad_datos);            // Leo por la cantidad de datos que hubo
  6.                         g_cantidad_datos=0;                                         // Pongo a 0 para que no entre mas hasta que llegue algo
  7.                         Lcd_Clear();                                                        // Limpio y envio al LCD
  8.                         lcdout(1,1,data); // recibo repuesta de esp8266
  9.                 }
  10.        
  11.         }

Todo eso si es que se envia algun caracter de finalizacion desde el ESP8266, sino tendrias que buscar otra forma.
Ademas tambien existe la posibilidad de que pueda perderse un dato, si es asi deberias implementar un timeout con algun timer y sin necesidad de interrupcion.
Y los datos deberian leerse y pasarse al array data, antes que llegue otro '\n'
Título: Re: Pic16f628a USART problema para recibir
Publicado por: RodrigoAndres en 05 de Julio de 2015, 17:06:56
si es verdad el tiene razon con eso, pero es muy raro qe funcione sin qe borres la bandera de interrupcion RCIF, como ases para que funcione asi??
Título: Re: Pic16f628a USART problema para recibir
Publicado por: KILLERJC en 05 de Julio de 2015, 18:13:24
si es verdad el tiene razon con eso, pero es muy raro qe funcione sin qe borres la bandera de interrupcion RCIF, como ases para que funcione asi??

Cuando se lee el RCREG se borra automaticamente la bandera

Usando el datasheet de un PIC16F887:

Sobre el flag:
Citar
RCIF: EUSART Receive Interrupt Flag bit
1 = The EUSART receive buffer is full (cleared by reading RCREG)
y
Citar
The RCIF interrupt flag bit is read-only, it cannot be set or cleared by software.
Yo tambien por ahi me olvido de esto xD.
Título: Re: Pic16f628a USART problema para recibir
Publicado por: Rseliman en 05 de Julio de 2015, 20:08:35
lo que si no pude entender es porque me imprimia parte del codigo ...la verdad no se , lo hacia en Proteus y en el protoboard tambien ....

Estas seguro que era parte del codigo o solo eran los datos ?, por ejemplo "Copyrights 2015" o "Programa" , etc

Ahora veo las palabras completas , solo que de a una letra por ves ...y tengo que detectar un OK que viene del esp8266 placa wifi ....ya vere como lo resuelvo ...
Era parte del codigo , pero claro otra ves tenes razon ...eran caracteres asschi , ya que estaban entre comillas , uso el esp8266 para enviar datos a una pagina web ..y lo que se veia eran los datos que direccion web ...de todas maneras es raro , pero bueno ...desp te voy a preguntar de nuevo por el tema de reconocer el OK que me devuelve el 8266 ...yo le transmito comandos AT ..y el me contesta con OK ...pero en el ultimo caso tengo que detectar la respuesta de la pagina ..que es un numero de 3 cifras ...el tema es que viene con mucho texto ...lo que hago es un GET a un PHP ...a una base de datos y cuando me contesta tengo que tomar ese numero ...

Gracias Muchas gracias
Título: Re: Pic16f628a USART problema para recibir
Publicado por: KILLERJC en 05 de Julio de 2015, 23:05:53
Lo que necesitarias es un parser de la respuesta que te da.

Basicamente cuando generas una peticion HTTP enviandole el header, el server te responde con otro header+pagina

Citar
HTTP/1.x 200 OK
Transfer-Encoding: chunked
Date: Sat, 28 Nov 2009 04:36:25 GMT
Server: LiteSpeed
Connection: close
X-Powered-By: W3 Total Cache/0.8
Pragma: public
Expires: Sat, 28 Nov 2009 05:36:25 GMT
Etag: "pub1259380237;gz"
Cache-Control: max-age=3600, public
Content-Type: text/html; charset=UTF-8
Last-Modified: Sat, 28 Nov 2009 03:50:37 GMT
X-Pingback: http://net.tutsplus.com/xmlrpc.php
Content-Encoding: gzip
Vary: Accept-Encoding, Cookie, User-Agent
 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Top 20+ MySQL Best Practices - Nettuts+</title>
<!-- ... rest of the html ... -->

De ahi imagino que queres obtener el status unicamente, que es el numero ahi (en negrita), mas que el OK.

Lo cual cuando envias vas a tener que recibir linea por linea en tu buffer.. la primera linea podes buscar hasta encontrar la posicion de los espacios ' ' y luego retirar el numero. Sabiendo que la primer linea del protocolo es esa, el protocolo + status
De ahi en mas te llegaria todo lo demas, que puede o no servirte.. lo que sigue.

Ahora si esto es una pagina o algo que necesitas obtener de una pagina que VOS creaste tal ves pueda sacar los datos en otro formato en otra pagina/direccion, como un txt/json/csv o algo asi para tener menor cantidad de texto y ahorrarte la llegada de todos los tags HTML.  Si ya es una pagina que no hiciste vos entonces vas a tener que renegar un poco con el tema de un parser, ya que encontrar el contenido de una pagina en todo el HTML es medio complejo, especialmente cuando se les ocurre cambiar una cosita chiquita de la pagina y ya deja de andar todo.
Título: Re: Pic16f628a USART problema para recibir
Publicado por: Rseliman en 26 de Septiembre de 2015, 12:34:22
Hola a todos :

Parece mentira pero no puedo solucionar lo siguiente ...estoy leyendo de la uart una pagina html ..lo que me da el siguiente resultado

+IPD,175:HTTP/1.1 200 OK
Server: nginx
Date: Sat, 26 Sep 2015 14:03:28 GMT
Content-Type: text/html
Connection: close
X-Powered-By: PHP/5.3.29
X-Proxy-Cache: BYPASS

(CONECTADO)CLOSED


y quiero extraer de ahi solo el texto (conectado) ...le puse los parentesis para poder parsearlo ...

hago lo siguiente

Código: [Seleccionar]
void respuesta(void)
 {
     while(1)
     {
         //Get the amount of data waiting in USART queue
         uint8_t n= USARTDataAvailable();
         char data[];
              //If we have some data
          if(n!=0)
            {
              //Read it)
              USARTReadBuffer(&data,n);
              sprintf(salida,"%s",&data);
              Lcd_Clear();
              Lcd_Set_Cursor(2,1);
              Lcd_Write_String(salida);
            }
     }
 }

de esta manera imprimo el total de datos en el buffer , en el lcd ...que es 2x16 ..asi que solo veo lo ultimo ...

pero quiero solamente ver el conectado y no me doy cuenta como sacarlo de una manera prolija ..

Gracias por la ayuda

mplabx xc8 pic 16f628
Título: Re: Pic16f628a USART problema para recibir
Publicado por: KILLERJC en 26 de Septiembre de 2015, 13:17:40
podrias buscar por un doble salto de linea \n\n (si es que solamente son \n y no \r\n ), sino buscar por 2 \r\n

Título: Re: Pic16f628a USART problema para recibir
Publicado por: RALF2 en 26 de Septiembre de 2015, 14:30:54
Para buscar la plabra "conectado" dentro del buffer, tendras que utilizar una rutina de busqueda quisas utilizando ,if, anidados para ello y usar punteros.

Saludos
Título: Re: Pic16f628a USART problema para recibir
Publicado por: dino60 en 04 de Octubre de 2015, 01:29:59
Fjgkgkfkg
Título: Re: Pic16f628a USART problema para recibir
Publicado por: Rseliman en 16 de Octubre de 2015, 19:45:15
Hola a todos .. alguien me puede dar una mano ?? tengo el siguiente problema

leo caracteres de una uart , de a uno, dentro de el void interrupt  de esta manera:

//Read the data
    char data=RCREG; // valores que ingresan por la uart

        if (cone[a] == data)
          {
           conect[a] = data ;
           a++ ;
          }

por la uart ingresa la palabra (CONECTADO)CLOSED ....al final

las variables son las sig

char cone[] = "(CONECTADO)"; y

char conect[11];

desp que terminan de entrar los datos por la uart hago esto

if (0 == strcmp(conect, "(CONECTADO)"))
                  Lcd_Write_String("conexion exitosa");

pero el if no se valida ...me estoy confundiendo con los strings pero no me doy cuenta donde ...

cundo escribo  Lcd_Write_String("conect");

en el display veo (CONECTADO)CONEC

en lugar de solamente (CONECTADO)

Gracias

espero haberme explicado bien


Título: Re:Pic16f628a USART problema para recibir
Publicado por: RALF2 en 16 de Octubre de 2015, 20:18:27
Hola Rseliman.
Cambia esto: char conect[11] por esto char conect[12]
Y nos comentas.
Otra cosa prueba el programa paso a paso en el proteus si lo tienes a mano.  :mrgreen:

Saludos
Título: Re:Pic16f628a USART problema para recibir
Publicado por: Rseliman en 16 de Octubre de 2015, 20:23:51
Gracias RALF2 ...ya probe pero sigo con lo mismo ...evidentemente lo que estoy comparando no es lo mismo ...pero no entiendo porque





Hola Rseliman.
Cambia esto: char conect[11] por esto char conect[12]
Y nos comentas.
Otra cosa prueba el programa paso a paso en el proteus si lo tienes a mano.  :mrgreen:

Saludos
Título: Re:Pic16f628a USART problema para recibir
Publicado por: RALF2 en 16 de Octubre de 2015, 20:28:09
Veamos, si estas enviando solo los siguentes caracteres: "(CONECTADO)", al realizar la comparacion deberia funcionarte bien, pero si envias otros caracteres distintos alli abra problemas.
Lo estas probando en fisico o con el simulador?
Otra cosa que me parece que podria estar probocando el problema es aqui:
if (0 == strcmp(conect, "(CONECTADO)"))
debria ser asi:
if (0 == strcmp(conect, cone)

Saludos
Título: Re:Pic16f628a USART problema para recibir
Publicado por: Rseliman en 16 de Octubre de 2015, 20:34:21
Listo RALF2 mil gracias ...si si al parecer era 12 en lugar de 11 en conect...recien lo probe nuevamente y anduvo , el tema es que es la devolucion de un esp8266 y cuando no se conecta no devuelve (CONECTADO) ..y creo recien se corto un seg internet por eso pense que no andaba , pero bueno ya se soluciono ...mil gracias nuevamente ...si si estoy con xc8 ..y probando en fisico ....

ahora me tocan otras comparaciones para estar seguro y tener una indicacion visual de que el esp8266 se conecto ...


Abrazo y gracias


Veamos, si estas enviando solo los siguentes caracteres: "(CONECTADO)", al realizar la comparacion deberia funcionarte bien, pero si envias otros caracteres distintos alli abra problemas.
Lo estas probando en fisico o con el simulador?
Y el compilador que estas utilizando es el XC8?

Saludos
Título: Re:Pic16f628a USART problema para recibir
Publicado por: KILLERJC en 16 de Octubre de 2015, 20:36:57
No me gusta la forma de obtener el dato. Realmente tenes un  "(CONECTADO)" ? Y siempre es asi ? Yo pense que era una respuesta de HTTP, y si la palabra que buscabas estaba ubicada en el lugar que decis te indicaba desde donde tenias que tomar los datos.

Código: [Seleccionar]
+IPD,175:HTTP/1.1 200 OK
Server: nginx
Date: Sat, 26 Sep 2015 14:03:28 GMT
Content-Type: text/html
Connection: close
X-Powered-By: PHP/5.3.29
X-Proxy-Cache: BYPASS

(CONECTADO)CLOSED

Como que primero debes SI o SI saber si la respuesta fue correcta por lo cual analizar y encontrar el 200 al comienzo ( 1era linea ) es fundamental, luego analizas la respuesta de la pagina que creo que es ese "(CONECTADO)" que esperas.

Si es una pagina tuya entonces ni te compliques ponerle parentesis ya que son 2 caracteres mas a comparar, a no ser que quieras asegurarte. Sabes que la respuesta del HTTP, viene seguido de un doble salto y sabes CUAL es la respuesta si o si del HTTP.

Entonces:
- Para obtener el codigo de respuesta, tenes que parsear la primera linea, una maquina de estado que lo haga y listo. que guarde el string de la primer linea ( hasta el \n ) Luego podes buscar los 2 espacios en blancos " " y lo que esta entre medio de eso es.. tu codigo de respuesta. Te aseguras que sea 200.
- Finalmente seguis recibiendo, si era 200 te va a importar obviamente, sino omitis todo no guardas nada y das aviso que un problema ocurrio , de tener un 200 cuando detectas un doble salto, comenzas nuevamente a guardar la linea. Aca Creo que hay 2 opciones:
Si es tu codigo (el del PHP), sabes exactamente la respuesta que te va a dar, lo cual podes tratar de encontrar el "(CONECTADO)" Ya que va a tener la respuesta exacta a tu codigo .
Si no es tu codigo ( el de PHP), podes restringir a que guarde solo algunos caracteres ( digamos unos 15 ) o hasta que encuentre un nuevo salto de linea. Y nuevamente comparar.

Al menos es lo que haria yo. Me aseguro de una falla de conexcion, de cualquier otra respuesta del servidor buscando el 200, y luego busco la respuesta, que se que va a comenzar luego del doble salto.

Con respecto a tu codigo:

char cone[] = "(CONECTADO)"; Eso, en realidad es esto '(','C','O','N','E','C','T','A','D','O',')','\0'  (son 12, no 11)

En una respuesta asi:

(CONECTADO)CLOSED

Y no tenes ese caracter nulo, Entonces veamos por parte:

Código: [Seleccionar]
        if (cone[a] == data)
          {
           conect[a] = data ;
           a++ ;
          }

hacer eso, si a termina siendo 11 al final del if, indica que realmente la palabra esta ahi, y no volver a "chequear" con el strcmp, es redundante.
Por otra parte tu codigo no distinguiria de esto:

a(ewqClalaOewqNerrEtgCdTasAetDyhOm)eC3L123O5SasEgDwq

Lo cual nuevamente no es correcto :P.
Y otro problema MAS!
Una ves que "a" supera 10 que es el limite del array "conect" estarias ESCRIBIENDO las posiciones de memoria siguientes que tal ves responden a data u otra variable, o tal ves por suerte no exista nada alli

Me explico, si tenes los datos asi en memoria:

conect[0]   -- a = 0
conect[1]
....
conect[10] -- a = 10
otra variable         -- a = 11
Sabra dios que hay aca -- a = 12 y asi... ( Lo cual NUNCA termina! )

Para C terminar una string necesita un 0x00, asi que va a continuar grabando hacia abajo hasta que "a" tenga un overflow o dejes de meterle datos, y cuando vos haces un printf, va a enviar todos los valores hasta que encuentre el primer 0x00 ( '\0' )

Entonces Podes hacer una cosa simple y tenerlo funcionando pero no evita los errores anteriores:

Reformar a conect haciendolo de 12 lugares

char conect[12];

Y luego el codigo:
Código: [Seleccionar]
        if (cone[a] == data)
          {
           conect[a] = data ;
           a++ ;
          }
if (a==11)
{
// Encontre la palabra
conect[a] = '\0';
a=0; // Asi no molesta y esta listo a recibir otra ves
Lcd_Write_String("conect");
}

Nuevamente te repito, esto NO evita otros problemas que puedas tener y que nombre antes. Solamente es un "fix" a tu programa.

PD: 3 respuestas mientras que escribi esto e.e
Título: Re:Pic16f628a USART problema para recibir
Publicado por: RALF2 en 16 de Octubre de 2015, 20:37:16
Ah perfecto de todas formas modifique el post, para ver otra opcion que me parecio que podria dar problemas pero si te funciono pos dejalo asi!  :mrgreen:

Saludos
Título: Re:Pic16f628a USART problema para recibir
Publicado por: Rseliman en 16 de Octubre de 2015, 20:54:01
Gracias KILLERJC  ..te respondo sobre tus preguntas



No me gusta la forma de obtener el dato. Realmente tenes un  "(CONECTADO)" ? Y siempre es asi ?


Si tengo siempre un (CONECTADO) , simpre que tenga internet ,,y que el esp8266 logre conectarse antes de esto




Yo pense que era una respuesta de HTTP, y si la palabra que buscabas estaba ubicada en el lugar que decis te indicaba desde donde tenias que tomar los datos.

Código: [Seleccionar]
+IPD,175:HTTP/1.1 200 OK
Server: nginx
Date: Sat, 26 Sep 2015 14:03:28 GMT
Content-Type: text/html
Connection: close
X-Powered-By: PHP/5.3.29
X-Proxy-Cache: BYPASS

(CONECTADO)CLOSED



Si si asi es esa es la pagina que me tira el conectado , la cual es propia y esta escrita en PHP por mi



Como que primero debes SI o SI saber si la respuesta fue correcta por lo cual analizar y encontrar el 200 al comienzo ( 1era linea ) es fundamental, luego analizas la respuesta de la pagina que creo que es ese "(CONECTADO)" que esperas.


el tema es que el (CONECTADO) aparece porque vailda datos en una base de datos ...o sea que el 200 podria aparecer igual y no asi el conectado ...por eso me aseguro que esta todo bien si tengo el conectado ...



Si es una pagina tuya entonces ni te compliques ponerle parentesis ya que son 2 caracteres mas a comparar, a no ser que quieras asegurarte. Sabes que la respuesta del HTTP, viene seguido de un doble salto y sabes CUAL es la respuesta si o si del HTTP.

Entonces:
- Para obtener el codigo de respuesta, tenes que parsear la primera linea, una maquina de estado que lo haga y listo. que guarde el string de la primer linea ( hasta el \n ) Luego podes buscar los 2 espacios en blancos " " y lo que esta entre medio de eso es.. tu codigo de respuesta. Te aseguras que sea 200.
- Finalmente seguis recibiendo, si era 200 te va a importar obviamente, sino omitis todo no guardas nada y das aviso que un problema ocurrio , de tener un 200 cuando detectas un doble salto, comenzas nuevamente a guardar la linea. Aca Creo que hay 2 opciones:
Si es tu codigo (el del PHP), sabes exactamente la respuesta que te va a dar, lo cual podes tratar de encontrar el "(CONECTADO)" Ya que va a tener la respuesta exacta a tu codigo .
Si no es tu codigo ( el de PHP), podes restringir a que guarde solo algunos caracteres ( digamos unos 15 ) o hasta que encuentre un nuevo salto de linea. Y nuevamente comparar.

Al menos es lo que haria yo. Me aseguro de una falla de conexcion, de cualquier otra respuesta del servidor buscando el 200, y luego busco la respuesta, que se que va a comenzar luego del doble salto.

Con respecto a tu codigo:

char cone[] = "(CONECTADO)"; Eso, en realidad es esto '(','C','O','N','E','C','T','A','D','O',')','\0'  (son 12, no 11)


si si de acuerdo con eto me comi el \0



En una respuesta asi:

(CONECTADO)CLOSED

Y no tenes ese caracter nulo, Entonces veamos por parte:

Código: [Seleccionar]
        if (cone[a] == data)
          {
           conect[a] = data ;
           a++ ;
          }

hacer eso, si a termina siendo 11 al final del if, indica que realmente la palabra esta ahi, y no volver a "chequear" con el strcmp, es redundante.
Por otra parte tu codigo no distinguiria de esto:

a(ewqClalaOewqNerrEtgCdTasAetDyhOm)eC3L123O5SasEgDwq

Lo cual nuevamente no es correcto :P.
Y otro problema MAS!
Una ves que "a" supera 10 que es el limite del array "conect" estarias ESCRIBIENDO las posiciones de memoria siguientes que tal ves responden a data u otra variable, o tal ves por suerte no exista nada alli

Me explico, si tenes los datos asi en memoria:

conect[0]   -- a = 0
conect[1]
....
conect[10] -- a = 10
otra variable         -- a = 11
Sabra dios que hay aca -- a = 12 y asi... ( Lo cual NUNCA termina! )



habia contemplado el que no se pase de 11 y se lo saque pero si me doy cuenta de lo que pasa ...muchas gracias !!!

Para C terminar una string necesita un 0x00, asi que va a continuar grabando hacia abajo hasta que "a" tenga un overflow o dejes de meterle datos, y cuando vos haces un printf, va a enviar todos los valores hasta que encuentre el primer 0x00 ( '\0' )

Entonces Podes hacer una cosa simple y tenerlo funcionando pero no evita los errores anteriores:

Reformar a conect haciendolo de 12 lugares

char conect[12];

Y luego el codigo:
Código: [Seleccionar]
        if (cone[a] == data)
          {
           conect[a] = data ;
           a++ ;
          }
if (a==11)
{
// Encontre la palabra
conect[a] = '\0';
a=0; // Asi no molesta y esta listo a recibir otra ves
Lcd_Write_String("conect");
}

Nuevamente te repito, esto NO evita otros problemas que puedas tener y que nombre antes. Solamente es un "fix" a tu programa.

PD: 3 respuestas mientras que escribi esto e.e



Mil gracias ....voy a seguir programando otro rato ...es un proyecto largo y lo agarro de vez en cuando