TODOPIC

Microcontroladores PIC => Todo en microcontroladores PIC => Mensaje iniciado por: cvargcal en 06 de Mayo de 2015, 03:21:38

Título: Funcion SendAT y confirmar respuesta
Publicado por: cvargcal en 06 de Mayo de 2015, 03:21:38
Encontré este código para arduino.

Código: [Seleccionar]
int8_t sendATcommand(char* ATcommand, char* expected_answer, unsigned int timeout){

    uint8_t x=0,  answer=0;
    char response[100];
    unsigned long previous;

    memset(response, '\0', 100);    // Initialice the string
    delay(100);
    while( Serial.available() > 0) Serial.read();    // Clean the input buffer
   
    if (ATcommand[0] != '\0')
    {
        Serial.println(ATcommand);    // Send the AT command
    }


    x = 0;
    previous = millis();

    // this loop waits for the answer
    do{
        if(Serial.available() != 0){    // if there are data in the UART input buffer, reads it and checks for the asnwer
            response[x] = Serial.read();
            //Serial.print(response[x]);
            x++;
            if (strstr(response, expected_answer) != NULL)    // check if the desired answer (OK) is in the response of the module
            {
                answer = 1;
            }
        }
    }while((answer == 0) && ((millis() - previous) < timeout));    // Waits for the asnwer with time out

    return answer;
}



y se utiliza así:
sendATcommand("AT+*****=****", "OK", 2000);


Alguien tiene alguna idea de como cambiarlo para hacer lo mismo en CCS?

Título: Re: Funcion SendAT y confirmar respuesta
Publicado por: KILLERJC en 06 de Mayo de 2015, 09:51:11
es simple, empeza a reemplazar funciones que no son de CCS.

- memset(response, '\0', 100);

Esa funcion es de C, de alguna libreria, basicamente pone en los 100 lugares ese valor, o equivalente a hacer:

for(i=0;i<100;i++) {response[ i ]='\0';}

sigue el delay que no lo voy a pasar.

- while( Serial.available() > 0) Serial.read();

Eso limpiar el buffer de lectura, lo que podes hacer es leer varias veces, todo depende de tu PIC que tan grnade el buffer que tenga.

while( !kbhit() ) getc();

- Serial.println(ATcommand);

Por puts(ATcommand);

- if(Serial.available() != 0)
if(!kbhit())

- response[ x ] = Serial.read();

response[ x ] = getc();


- if (strstr(response, expected_answer) != NULL)  

Esa funcion es de C , string.h

- previous = millis();
- while((answer == 0) && ((millis() - previous) < timeout))

Esto lo podes implementar de varias formas, si quisieras un control preciso seria con un timer y se reemplazaria algo asi (obviamente antes configurar el timer):

previus = milis();
por
set_timer0(0);

y el while por algo asi, en este codigo estarias limitado por pasos del desbordamiento del timer0:

j=0;
while(answer == 0)
{
 if(interrupt_active(TMR0))
 {
  if(j++ > timeout) break;
 }
}

TIMEOUT necesita ser calculado, va a ser dependiente de tu frecuencia/tu configuracion del timer, etc. Una formula que lo defina al comienzo y listo. O tambien si te da el tiempo podes simplmente preguntar por si se activo el flag y que se produzca el break; Eso quitaria una opcion de "timeout" ya que estaria siendo fija.

La otra pero que ya NO es tan precisa pero que te debe importar poco, seria reemplazar esas 2 instrucciones por:

j=0;
while((answer == 0) && (++j < timeuot))

Donde nuevamente timeout debe calcularse
Esto hace que cada ves que pase por esta condicion aumente j en 1, cuando se cumple supere el timeout sale de la funcion.
Título: Re: Funcion SendAT y confirmar respuesta
Publicado por: cvargcal en 06 de Mayo de 2015, 13:05:20
es simple, empeza a reemplazar funciones que no son de CCS.
......


Gracias , llevo el código así , pero no se como implementar el tiempo de respuesta.

Código: [Seleccionar]
#include <18F26K22.h>
#Device  PASS_STRINGS=IN_RAM 
#ZERO_RAM     
#FUSES INTRC_IO, NOWDT, BROWNOUT, PUT, NOPBADEN, NOHFOFST,NOPLLEN ,PROTECT
#use delay(clock=4M)
#use rs232(baud=9600,bits=8,parity=N,xmit=PIN_C6,rcv=PIN_C7,ERRORS,bits=8,stream=uart1)  // Configuración UART1 (Hardware)
#use rs232(baud=9600,bits=8,parity=N,xmit=PIN_B6,rcv=PIN_B7,ERRORS,bits=8,stream=uart2)  // Configuración UART2 (Hardware)
#define FASTER_BUT_MORE_ROM                                                              // Variables en memoria
#include <string.h>                                                                      // Librerias para manejo de strings
#include <stdlib.h>
int8 SendATcommand();
int cont=0,seg=0,min=0;
int ban_1seg=0;                // Variables

/// Timer
#int_TIMER1                           
void TIMER1_isr(void){                              //                         
   cont++;                                          //                                   
   if(cont == 2){                                   // 0,5*1=1 segundo
        ban_1seg = 1;cont = 0;                      //                                     
   }                                                //
   set_timer1(3036);                                // 0.5=4/4000000*8(65536-x),x=3036 >> Tiempo de desbordamiento es 0.5 segundos
}

// Programa Principal
void main(){   
//-------------- Configuración ----------           //
     setup_timer_1 (T1_INTERNAL | T1_DIV_BY_8);     // Configuración  Timer1
     set_timer1 (3036);                             // 0.5=4/4000000*8(65536-x),x=3036 >> Tiempo de desbordamiento es 0.5 segundos
     enable_interrupts(GLOBAL);                     // Habilitar Interrupción Global
     enable_interrupts(int_timer1);                 // Habilitar Interrupción Timer1       
//--------------- Subprograma ---------------                                     
   while(true){
   
   sendATcommand("AT+CMGF=1","OK", 2000);
   
   
}

//sendATcommand("AT+*****=****", "OK", 2000);

int8 sendATcommand(char* ATcommand, char* expected_answer, unsigned int timeout){
    char*ATcommand;
    int x=0,answer=0,i;
    char response[100];
    unsigned long previous;

// Limpiar buffer de Respuesta
    for(i=0;i<100;i++)
    {response[i]='\0';}     
    delay_ms(100);
   
    /*
     if(kbhit(uart1)){                       // Si hay algo pendiente de recibir ...
         a=getc(uart1); 
         buffer2[xbuff2++]=b;                // Añade caracter recibido al Buffer
           if(xbuff2==lenbuff) xbuff2=0x00;  // Si buffer esta lleno se resetea
      }
*/
   
   
    while(!kbhit(uart1))
          if (ATcommand[0]!= '\0')
            {
               puts(ATcommand);               // Enviar Comando AT
            }
   
     x = 0;
    previous = set_timer1(0);                 // iempo de espera

 // Esperar Respuesta
    do{
        if(!kbhit()){               // if there are data in the UART input buffer, reads it and checks for the asnwer
            response[x]=getc();
            x++;
       
            if (strstr(response, expected_answer)!= '\0')    // check if the desired answer (OK) is in the response of the module
            {
             answer = 1;
            }
        }
    }while((answer == 0) && ((millis() - previous) < timeout));    // Waits for the asnwer with time out

    return answer;    //

}



Título: Re: Funcion SendAT y confirmar respuesta
Publicado por: KILLERJC en 06 de Mayo de 2015, 14:17:47
Veo que esta comentado:

Código: [Seleccionar]
   /*
     if(kbhit(uart1)){                       // Si hay algo pendiente de recibir ...
         a=getc(uart1);  
         buffer2[xbuff2++]=b;                // Añade caracter recibido al Buffer
           if(xbuff2==lenbuff) xbuff2=0x00;  // Si buffer esta lleno se resetea
      }
*/
pero la idea de  ejecutar eso es para limpiar el buffer (leerlo y desechar lo que este ahi), ese pic posee solo 1 nivel de stack asi que con un simple:

getc(uart1);

deberia bastar, como dije si hay algo esperando, por que llego por equivocacion o lo que sea, esto lo limpia, preparando para el nuevo dato.

Con respecto a la demora, es configurar el timer0 (el timer0 siempre esta corriendo). Suponete el timer 0 sin preescaler, es de 8 bits.
Tu oscilador es de 4Mhz

Periodo de entrada al timer' : 4/4Mhz = 1us
Tiempo para que se desborde: 256 * 1us = 256us

Asi que comienzo con esto:

Código: [Seleccionar]
int16 numero_de_intr=0;

if(!timeout)
{
numero_de_intr = (int32)(timeout *1000) /256;  // Lo que hago es dividir el tiempo en milisegundos que pasaste en el tiempo que tarda el TMR0 en desbordarse o timeout(ms)/256us
                                                        // Asi encuentro la cantidad de veces que debe ocurrir el overflow, ademas me aseguro que se paso un numero y que no sea cero
}                                                       // Como maximo deberia permitirte unos 16 segundos, lo cual es una asquerosidad de tiempo para un timeout

set_timer0(0); //Pongo a 0
clear_interrupt(INT_RCC); //Limpia mi flag TMR0
i=0;               // Uso el mismo i del for como contador

do
{
 if(!kbhit())
  {
   ....
   }
 if(interrupt_active(INT_RTCC))
  {
    if (++i > cantidad_de_intr) { break; }      // en la misma sentencia sumo 1 a i cada ves que entra, y comparo con la cantidad de veces que tiene que entrar, si se supero ejecuto el break; para salir del do..while
   }
} while (answer == 0)

seguro que la variable "i" sea de 16bits tambien.
O podes crear otra variable para eso.

Espero que me entiendas lo que quiero hacer con esto.
Título: Re: Funcion SendAT y confirmar respuesta
Publicado por: cvargcal en 06 de Mayo de 2015, 18:20:12
Veo que esta comentado:
.....


Muchas gracias por responder y brindar tu conocimiento :)
Cuando intento compilar me da un error de "Expecting a close  paren". no tiendo porque si la función esta definida nombre(AT,respuesta,tiempo)...
Nuevamente gracias. :-/



Código: [Seleccionar]

#include <18F26K22.h>
#Device  PASS_STRINGS=IN_RAM 
#ZERO_RAM     
#FUSES INTRC_IO, NOWDT, BROWNOUT, PUT, NOPBADEN, NOHFOFST,NOPLLEN ,PROTECT
#use delay(clock=4M)
#use rs232(baud=9600,bits=8,parity=N,xmit=PIN_C6,rcv=PIN_C7,ERRORS,bits=8,stream=uart1)  // Configuración UART1 (Hardware)
#use rs232(baud=9600,bits=8,parity=N,xmit=PIN_B6,rcv=PIN_B7,ERRORS,bits=8,stream=uart2)  // Configuración UART2 (Hardware)
#define FASTER_BUT_MORE_ROM                                                              // Variables en memoria
#include <string.h>                                                                      // Librerias para manejo de strings
#include <stdlib.h>
int8 SendATcommand();
int cont=0,seg=0,min=0;
int ban_1seg=0;                // Variables

/// Timer
#int_TIMER1                           
void TIMER1_isr(void){                              //                         
   cont++;                                          //                                   
   if(cont == 2){                                   // 0,5*1=1 segundo
        ban_1seg = 1;cont = 0;                      //                                     
   }                                                //
   set_timer1(3036);                                // 0.5=4/4000000*8(65536-x),x=3036 >> Tiempo de desbordamiento es 0.5 segundos
}

// Programa Principal
void main(){   
//-------------- Configuración ----------           //
     
     setup_timer_1 (T1_INTERNAL | T1_DIV_BY_8);     // Configuración  Timer1
     set_timer1 (3036);                             // 0.5=4/4000000*8(65536-x),x=3036 >> Tiempo de desbordamiento es 0.5 segundos
     enable_interrupts(GLOBAL);                     // Habilitar Interrupción Global
     enable_interrupts(int_timer1);                 // Habilitar Interrupción Timer1   
     enable_interrupts(INT_RTCC);
//--------------- Subprograma ---------------                                     
   while(true){
   sendATcommand("AT+CMGF=1","OK", 2000);
   
}
}
//sendATcommand("AT+*****=****", "OK", 2000);

int8 sendATcommand(char*ATcommand, char*expected_answer, unsigned int timeout){
    int x=0,answer=0,i;
    int cantidad_de_intr;
    char response[100];
    unsigned long previous;

// Limpiar buffer de Respuesta
    for(i=0;i<100;i++)
    {response[i]='\0';}     
    delay_ms(100);
   
int16 numero_de_intr=0;

if(!timeout)
{
numero_de_intr = (int32)(timeout *1000) /256;  // Lo que hago es dividir el tiempo en milisegundos que pasaste en el tiempo que tarda el TMR0 en desbordarse o timeout(ms)/256us
                                                        // Asi encuentro la cantidad de veces que debe ocurrir el overflow, ademas me aseguro que se paso un numero y que no sea cero
}                                                       // Como maximo deberia permitirte unos 16 segundos, lo cual es una asquerosidad de tiempo para un timeout

set_timer0(0);             //Pongo a 0
clear_interrupt(INT_RTCC); //Limpia mi flag TMR0
i=0;                       // Uso el mismo i del for como contador

do{
 if(!kbhit(uart1))
  {
            response[x]=getc();
            x++;
       
            if (strstr(response, expected_answer)!= '\0')    // check if the desired answer (OK) is in the response of the module
            {
             answer = 1;
            }
   }
 if(interrupt_active(INT_RTCC))
  {
    if (++i > cantidad_de_intr) { break; }      // en la misma sentencia sumo 1 a i cada ves que entra, y comparo con la cantidad de veces que tiene que entrar, si se supero ejecuto el break; para salir del do..while
   }
} while (answer==0);
}

Título: Re: Funcion SendAT y confirmar respuesta
Publicado por: KILLERJC en 06 de Mayo de 2015, 18:25:31
proba definiendolo como

int8 sendATcommand(char *ATcommand, char *expected_answer, unsigned int timeout);

Sino fijate en la linea que te da error, no tengo la menor idea cual puede ser ese error, ni donde puede estar.
Título: Re: Funcion SendAT y confirmar respuesta
Publicado por: cvargcal en 07 de Mayo de 2015, 12:05:11
proba definiendolo como

int8 sendATcommand(char *ATcommand, char *expected_answer, unsigned int timeout);

Sino fijate en la linea que te da error, no tengo la menor idea cual puede ser ese error, ni donde puede estar.

Si compilo, pero no funciona... nuca entra en el segundo  do { if(!kbhit(uart1))...}  (se supone que es cuando no hay datos pendientes por recibir?)

Pero, lo hice de esta forma:



// Interrupcion int_RDA

#int_RDA                               // Interrupción por recepción de datos UART1
void RDA_isr1(void) {              // Interrupción recepción serie USART
   c=0x00;                             // Inicializo caracter recibido                   
   if(kbhit(uart1)){                  // Si hay algo pendiente de recibir ...
      c=getc(uart1);                 // lo descargo y ...
     
      buffer1[xbuff1++]=c;      // Añade carácter recibido al Buffer
             
      }

   }


// Función de envío del comando

int8 sendATcommand(char *ATcommand, char *expected_answer)
{
    int answer=0,i;
    clear_buffer1(); 
   
    do{
      fprintf(uart1,"%s",ATcommand);               // Enviar Comando AT
      if (strstr(buffer1, expected_answer)>0){    // Verifica la respuesta que debe tener
       answer=1;
       clear_buffer1();
    }
} while (!answer);

return answer;
}


//******* Borrar Buffer1 ****************
void clear_buffer1(void){              // Inicia a \0 buffer1
   int i;                                       //
   for(i=0;i<30;i++){                  // Bucle que pone a 0 todos los caracteres en el buffer
      buffer1=0x00;                  //
   }                                           //
   xbuff1=0x00;                          // Inicializo el indice de siguiente carácter
}


Será necesario el timeout?, porque pienso que bastaría con un retardo después de enviar el comando para esperar la respuesta.
Título: Re: Funcion SendAT y confirmar respuesta
Publicado por: KILLERJC en 07 de Mayo de 2015, 13:26:33
el kbhit avisa cuando hay un dato presente.., es decir si el flag de la UART se activo. Si no entra es por que no llego nada.

Tu rutina de interrupciones esta mal. puede llegar a ocurrir en algun momento que jamas se reinicie xbuff1, con lo que estarias provocando un overflow.

El timeout esta por algo.. es por si no recibiste nada, pero durante el timeout el micro sigue corriendo, si lo haces con un delay, vas a tener el problema que mas que un timeout sea algo que te bloquee la comunicacion por ese tiempo.

La funcion de sendATcommand va a estar continuamente enviando lso comandos AT, no dandole tiempo para que reciba algo, por ende quedaria encerrado en el do while
Título: Re: Funcion SendAT y confirmar respuesta
Publicado por: cvargcal en 07 de Mayo de 2015, 13:55:44
el kbhit avisa cuando hay un dato presente.., es decir si el flag de la UART se activo. Si no entra es por que no llego nada.

Tu rutina de interrupciones esta mal. puede llegar a ocurrir en algun momento que jamas se reinicie xbuff1, con lo que estarias provocando un overflow.

El timeout esta por algo.. es por si no recibiste nada, pero durante el timeout el micro sigue corriendo, si lo haces con un delay, vas a tener el problema que mas que un timeout sea algo que te bloquee la comunicación por ese tiempo.

La funcion de sendATcommand va a estar continuamente enviando lso comandos AT, no dandole tiempo para que reciba algo, por ende quedaria encerrado en el do while

Solo es una muestra del codigo, por su puesto que se debe reiniciar el buffer cuando alcanza el valor máximo, bien... pensaré entonces en implementar el timer out.
Gracias.

Título: Re: Funcion SendAT y confirmar respuesta
Publicado por: jeremylf en 08 de Mayo de 2015, 02:00:26
No tiene nada que ver pero porque no lo corres a 64Mhz?  :lol:
Título: Re: Funcion SendAT y confirmar respuesta
Publicado por: cvargcal en 08 de Mayo de 2015, 14:19:32
el kbhit avisa cuando hay un dato presente.., es decir si el flag de la UART se activo. Si no entra es por que no llego nada.



Así va el código, funciona simulado, pero no entiendo porque tiene que tener la función del timer0, (si la quito no funciona)

Código: [Seleccionar]

#include <18F26K22.h>
#Device  PASS_STRINGS=IN_RAM 
#ZERO_RAM     
#FUSES INTRC_IO, NOWDT, BROWNOUT, NOPUT , NOPBADEN, NOHFOFST,NOPLLEN ,PROTECT
#use delay(clock=4M)
#use rs232(baud=9600,bits=8,parity=N,xmit=PIN_C6,rcv=PIN_C7,ERRORS,bits=8,stream=uart1)  // Configuración UART1 (Hardware)
#use rs232(baud=9600,bits=8,parity=N,xmit=PIN_B6,rcv=PIN_B7,ERRORS,bits=8,stream=uart2)  // Configuración UART2 (Hardware)
#define FASTER_BUT_MORE_ROM                                                              // Variables en memoria
#include <string.h>                                                                      // Librerias para manejo de strings
#include <stdlib.h>
void clear_buffer1();
int8 sendATcommand(char *ATcommand, char *expected_answer,unsigned int timeout);
char c;
char buffer1[30];
int xbuff1=30;
int1  flagTimeOut = 0x00;     // Flag quea indica timeout completo, inicializado a 0
//------- Modulo GPRG------
#int_RDA                                  // Interrupción por recepción de datos UART1
void RDA_isr1(void) {                  // Interrupción recepción serie USART
   c=0x00;                                // Inicializo caracter recibido                   
   if(kbhit(uart1)){                     // Si hay algo pendiente de recibir ...
      c=getc(uart1);                    // lo descargo y ...
      buffer1[xbuff1++]=c;          // Añade caracter recibido al Buffer   
      if(xbuff1==30) xbuff1=0x00;   // Si buffer esta lleno se resetea
      }
   }


#int_timer0
void timer0_isr() {          // Interrupción por desbordamiento de timer0
 
   flagTimeOut = 1;
 
}
// Programa Principal
void main(){   
//-------------- Configuración ----------           //
    enable_interrupts(GLOBAL);                     // Habilitar Interrupción Global
    setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1|RTCC_8_bit);      //256 us overflow
    enable_interrupts(INT_RTCC);
    enable_interrupts(int_rda);                    // Habilita Interrupción RDA UART1
     
//--------------- Subprograma ---------------                                     
   while(true)
   {
   if  (sendATcommand("AT+CGPSPWR=1\r\n", "OK",5000))
       {
       fprintf(uart1,"\r\nListo...\r\n");}
   else
      {
   fprintf(uart1,"\r\nError...\r\n");
   }
   }
}

int8 sendATcommand(char *ATcommand, char *expected_answer,unsigned int timeout)
{
    int16 numero_de_intr=0;
    int answer=0,i=0;                                     //
    clear_buffer1();                                         //
    numero_de_intr = (int32)(timeout *1000) /256;   
    set_timer0(0);                                          //Pongo a 0
    clear_interrupt(INT_RTCC);                          //Limpia mi flag TMR0


    do{
      fprintf(uart1,"%s",ATcommand);               // Enviar Comando AT
      delay_ms(300);                                      // Tiempo de espera para RX
      if (strstr(buffer1, expected_answer)>0)     // Busca la respuesta que debe ser
        {   
         answer=1;  clear_buffer1();                 // Respuesta Correcta    y  Limpiar buffer1                 
        }
      if (++i > numero_de_intr) { break; }        // en la misma sentencia sumo 1 a i cada ves que entra, y comparo con la cantidad de veces que tiene que entrar
      } while (answer == 0);                           // Hasta que la Respuesta sea correcta

   return answer;
}

//******* Borrar Buffer1 ****************
void clear_buffer1(void){                       // Inicia a \0 buffer1
   int i;                                                //
   for(i=0;i<30;i++){                           // Bucle que pone a 0 todos los caracteres en el buffer
      buffer1[i]=0x00;                           //
   }                                                    //
   xbuff1=0x00;                                  // Inicializo el indice de siguiente caracter
}




Si claro, la idea es 64MHz :)  pero por ahora solo es  para pruebas.
Título: Re: Funcion SendAT y confirmar respuesta
Publicado por: KILLERJC en 08 de Mayo de 2015, 17:05:55
Tenes que entender que es el timeout.

El timeout es una "espera" si dentro de ese tiempo NO llega la informacion esperada eso quiere decir, que no recibiste lo que querias o que no hubo ninguna devolucion. Eso en el caso de la funcion que pasate al principio.

Ahora como implementar ese timeout?
Y depende. podes simplemente contar, como ya propuse, cada ves que pase la condicion y no se cumpla seguira en ese loop. hasta que ese contador lo saque o coincida
Si observas aca sigue preguntando sobre la llegada o si coincide con la respuesta esperada

Yo lo hice con el timer, utilizo el timer para medir el tiempo, en ves de un contador como en el caso anterior que es mas invariable por que depende de la cantidad de instrucciones que se ejecuten, cuento cuantas veces se produce el overflow del timer.

Si uso un delay, dejo al micro esperando, esto hace que no pueda salir de ese lugar hasta que se termine el delay, asi que no puedo usarlo.
Título: Re: Funcion SendAT y confirmar respuesta
Publicado por: cvargcal en 08 de Mayo de 2015, 19:17:02
Tenes que entender que es el timeout.


Aja, ya se lo que es... de hecho esta funcionando como debe ser, lo curioso es que si quito esto:

Código: [Seleccionar]
#int_timer0
void timer0_isr() {          // Interrupción por desbordamiento de timer0
 
 //  flagTimeOut = 1;
 
}
Que no se esta usando... el micro no corre en la simulación... no se si es error del compilador.
El timer out lo uso como lo expusiste anteriormente y funciona tal cual como quiero...
Gracias.
Título: Re: Funcion SendAT y confirmar respuesta
Publicado por: KILLERJC en 08 de Mayo de 2015, 21:29:20
Lo mas seguro que es por esto:

Código: [Seleccionar]
enable_interrupts(INT_RTCC);
Estas habilitando la interrupcion, pero no estas definiendo una funcion para esa interrupcion.

Con respecto al programa, sigo pensando y estoy segurisimo que esta mal la funcion que tenes, por lo siguiente:

- Tenes el ENVIO del comando AT dentro de un do..while
- Tenes un delay
- Hiciste lo que dije del timer0 pero solo en partes, ya que tu implementacion del timeout es atraves de otra cosa, y no tiene sentido usar el timer0 como lo estas usando vos actualmente en tu programa

Título: Re: Funcion SendAT y confirmar respuesta
Publicado por: cvargcal en 08 de Mayo de 2015, 22:38:37
Lo mas seguro que es por esto:


- Si, quiero que este en un do.. while, porque quiero que lo envié forzando hasta tener la respuesta., si lo dices por el do del main es solo para hacerlo correr.
- el delay solo lo puse para tener tiempo de poner el "OK" en la simulación y así ver que el código trabaja.
- No sé porque funciona, pero en la simulación arroja el resultado que quiero.
que básicamente es enviar el  comando constantemente  hasta obtener la respuesta deseada.

la simulación corre bien, envía comando... cuenta las interrupciones dependiendo del timerout ingresado, si no se recibe lo correcto antes del superar las interrupciones, sale del ciclo y devuelve un 0, lo cual me dice que no obtuvo la respuesta deseada, en caso contrario devuelve un 1 y confirma que la respuesta es correcta.

¿Es así como debe funcionar no?

Bueno, mi conocimiento es limitado, así que te agradezco cualquier sugerencia o arreglo que quieras agregar.
Muchas gracias y éxitos :)!
Título: Re: Funcion SendAT y confirmar respuesta
Publicado por: KILLERJC en 08 de Mayo de 2015, 22:59:22
Citar
- Si, quiero que este en un do.. while, porque quiero que lo envié forzando hasta tener la respuesta., si lo dices por el do del main es solo para hacerlo correr.

Vos me pediste que funcione como el de arduino, lo que estas haciendo no me parece correcto pero bueno. Para mi deberias enviar una sola ves y esperar la respuesta y fin.

Citar
cuenta las interrupciones dependiendo del timerout ingresado

Esto es un error, por que el codigo que tenes ( o que pasaste al ultimo ) no hace eso, sino que calcula la cantidad de interrupciones, pero no luego no compara eso, sino que tenes una variable que se incrementa cada vez que se compara y compara con lo calculado, pero jamas compara con las veces que entro a la interrupcion.

Esta es la linea en cuestion:

Citar
if (++i > numero_de_intr) { break; }

Antes de comparar eso, incrementa i, y luego compara. pero para entrar ahi no hay nada que lo limite. Por eso yo lo habia puesto dentro de un if, pero mi codigo no tengo activo el interrupt del tmr0, solo leo el flag.

Código: [Seleccionar]
if(interrupt_active(INT_RTCC))
  {
    if (++i > cantidad_de_intr) { break; }      // en la misma sentencia sumo 1 a i cada ves que entra, y comparo con la cantidad de veces que tiene que entrar, si se supero ejecuto el break; para salir del do..while
   }
Título: Re: Funcion SendAT y confirmar respuesta
Publicado por: cvargcal en 10 de Mayo de 2015, 13:49:50
......

Ok, entonces así queda, igual me gusta como trabaja:
Una ultima cosa, ¿Por qué no seria bueno enviar el comando varias veces? ¿Quién garantiza que llegue bien? es por eso que lo hago.


Código: [Seleccionar]
#include <18F26K22.h>
#Device  PASS_STRINGS=IN_RAM 
#ZERO_RAM     
#FUSES INTRC_IO, NOWDT, BROWNOUT, NOPUT , NOPBADEN, NOHFOFST,NOPLLEN ,PROTECT
#use delay(clock=4M)
#use rs232(baud=9600,bits=8,parity=N,xmit=PIN_C6,rcv=PIN_C7,ERRORS,bits=8,stream=uart1)  // Configuración UART1 (Hardware)
#use rs232(baud=9600,bits=8,parity=N,xmit=PIN_B6,rcv=PIN_B7,ERRORS,bits=8,stream=uart2)  // Configuración UART2 (Hardware)
#define FASTER_BUT_MORE_ROM                                                              // Variables en memoria
#include <string.h>                                                                      // Librerias para manejo de strings
#include <stdlib.h>
void clear_buffer1();
int8 sendATcommand(char *ATcommand, char *expected_answer,unsigned int timeout);
char c;
char buffer1[30];
int xbuff1=30;


#int_RDA                               // Interrupción por recepción de datos UART1
void RDA_isr1(void) {                  // Interrupción recepción serie USART
   c=0x00;                             // Inicializo caracter recibido                   
   if(kbhit(uart1)){                   // Si hay algo pendiente de recibir ...
      c=getc(uart1);                   // lo descargo y ...
      buffer1[xbuff1++]=c;             // Añade caracter recibido al Buffer   
      if(xbuff1==30) xbuff1=0x00;      // Si buffer esta lleno se resetea
      }
   }


#int_timer0
void timer0_isr() {          // Interrupción por desbordamiento de timer0
}

// Programa Principal
void main(){   
//-------------- Configuración ----------                //
    enable_interrupts(GLOBAL);                           // Habilitar Interrupción Global
    setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1|RTCC_8_bit);  // 256 us overflow
    enable_interrupts(INT_RTCC);
    enable_interrupts(int_rda);                          // Habilita Interrupción RDA UART1
     
//--------------- Subprograma ---------------                                     
 while(true){
 
   if  (sendATcommand("AT+CGPSPWR=1\r\n", "OK",5000)){
       fprintf(uart1,"\r\nListo...\r\n");}
   else {
        fprintf(uart1,"\r\nError...\r\n");}
   }
}

//******* Enviar AT  ********************
int8 sendATcommand(char *ATcommand, char *expected_answer,unsigned int timeout)
{
    int16 numero_de_intr=0;                             // Variables       
    int answer=0,i=0;                                   // Variables
    clear_buffer1();                                    // Limpiar buffer
    numero_de_intr = (int32)(timeout *1000) /256;       // Numero de Interrupciones
    set_timer0(0);                                      // Pongo a 0
    clear_interrupt(INT_RTCC);                          // Limpia mi flag TMR0
    fprintf(uart1,"%s",ATcommand);                      // Enviar Comando AT Retardo 0.3 segundos   

    do{
      if (strstr(buffer1, expected_answer)>0)           // Busca la respuesta que debe ser
        { answer=1;  clear_buffer1();}                  // Respuesta Correcta    y  Limpiar buffer1       
     
      if(interrupt_active(INT_RTCC)){
        if (++i > numero_de_intr) { break; }            // en la misma sentencia sumo 1 a i cada ves que entra, y comparo con la cantidad de veces que tiene que entrar, si se supero ejecuto el break; para salir del do..while
      }
     } while (answer == 0);                             // mientras respuesta sea 0
   return answer;                                       // Retorna respuesta (1 o 0)
}
//******* Borrar Buffer1 ****************
void clear_buffer1(void){                              // Inicia a \0 buffer1
   int i;                                              //
   for(i=0;i<30;i++){                                  // Bucle que pone a 0 todos los caracteres en el buffer
      buffer1[i]=0x00;                                 //
   }                                                   //
   xbuff1=0x00;                                        // Inicializo el indice de siguiente caracter
}



Muchas gracias por tu tiempo y sugerencias.
Título: Re: Funcion SendAT y confirmar respuesta
Publicado por: KILLERJC en 10 de Mayo de 2015, 14:30:40
Es tiempo ocupado mandando datos, con lo cual 1 ves serviria. Si la respuesta fuera mas larga que el envio del comando, como actuaria el receptor? por ejemplo que la respuesta sea 30 caracteres y tu envio sea de 10, envias 10, el receptor comienza a devolver y cuando va por 10 de 30, le llega nuevamente otra peticion, deja de hacer lo que estaba haciendo ? e intenta responder a esta?.
En fin, no le veo nada bueno a eso. Ya que con que lo envies una sola ves ya estaria.

Si tenes problemas sobre si tus cosas llegaron o no para eso tenes el timeout, obviamente en el codigo que trajiste no se separa entre timeout por que no llego nada, o timeout por que llego un resultado que no era el esperado.
Título: Re: Funcion SendAT y confirmar respuesta
Publicado por: cvargcal en 11 de Mayo de 2015, 17:11:27
Es tiempo ocupado mandando datos, con lo cual 1 ves serviria. Si la respuesta fuera mas larga que el envio del comando, como actuaria el receptor? por ejemplo que la respuesta sea 30 caracteres y tu envio sea de 10, envias 10, el receptor comienza a devolver y cuando va por 10 de 30, le llega nuevamente otra peticion, deja de hacer lo que estaba haciendo ? e intenta responder a esta?.
En fin, no le veo nada bueno a eso. Ya que con que lo envies una sola ves ya estaria.

Si tenes problemas sobre si tus cosas llegaron o no para eso tenes el timeout, obviamente en el codigo que trajiste no se separa entre timeout por que no llego nada, o timeout por que llego un resultado que no era el esperado.

Genial, gracias por la aclararon ahora entiendo algunos problemas que tuve anteriormente, precisamente la respuesta era mucho mas larga que el comando.

El código que estoy desarrollando lo  quiero trabajar en 64MHZ, lo que debo configurar el overflow asi:
Código: [Seleccionar]
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256|RTCC_8_bit); //4,0 ms overflow

pero nunca entra en :
Código: [Seleccionar]

if(interrupt_active(INT_RTCC)){
        if (++i > numero_de_intr) { break; }            // en la misma sentencia sumo 1 a i cada ves que entra, y comparo con la cantidad de veces que tiene que entrar, si se supero ejecuto el break; para salir del do..while
      }

¿Como debe ir configurado para que este mismo código trabaje a 64MHZ?

Título: Re: Funcion SendAT y confirmar respuesta
Publicado por: KILLERJC en 11 de Mayo de 2015, 21:46:22
La frecuencia pasa de 4 Mhz a 64Mhz, asi que vas a esperar ver el mismo incremento de pulsos en el timer. Antes habiamos usado un preescaler de 1.

64Mhz/4Mhz = 16

Pone un preescaler de 16 y vas a seguir teniendo el overflow a 256us, y no tenes que cambiar nada mas del codigo, me refiero a la formula y a la parte de la interrupcion.
Título: Re: Funcion SendAT y confirmar respuesta
Publicado por: cvargcal en 11 de Mayo de 2015, 23:25:33
La frecuencia pasa de 4 Mhz a 64Mhz, asi que vas a esperar ver el mismo incremento de pulsos en el timer. Antes habiamos usado un preescaler de 1.

64Mhz/4Mhz = 16

Pone un preescaler de 16 y vas a seguir teniendo el overflow a 256us, y no tenes que cambiar nada mas del codigo, me refiero a la formula y a la parte de la interrupcion.

Aja así lo hago, he intento con otros valores... lo curioso es que si funciona y a la ves no...
cuando hago un debug, veo que  "i "no incrementa, y es como si no entrará a la interrupción.
pero, cuando lo corro de seguido si funciona,  como se muestra en la imagen, arroja el mensaje error si no se encuentra el dato esperado.

(http://www.todopic.com.ar/foros/imgtiny/hur968.png)


Bueno, igual así como esta me sirve, espero que tambien funcione en la practica... pero pienso que algo debe estar mal.
con 4M en el debug si muestra el incremento de "i"... pero solo si el proteus tiene 4M, entonces puede que sea problemas del simulador.

Muchas gracias.
Título: Re: Funcion SendAT y confirmar respuesta
Publicado por: KILLERJC en 11 de Mayo de 2015, 23:44:15
Puede ser que que se reciba la respuesta antes del que entre a una interrupcion.

Podes fijarte en el registro del TMR0 si es que se rebalsa o no
Título: Re: Funcion SendAT y confirmar respuesta
Publicado por: cvargcal en 13 de Mayo de 2015, 01:46:12
Puede ser que que se reciba la respuesta antes del que entre a una interrupcion.

Podes fijarte en el registro del TMR0 si es que se rebalsa o no

según el debug, justo cuando llega algo  el timer0 se dispara... mmm es raro. pero bueno, almenos puedo obtener una respuesta... dejaré así.
Muchas gracias!

PD: Hice un hilo sobre otro tema de comandos AT donde expongo  dos funciones para extraer datos de un string, por favor regalanos tus sugerencias.
http://www.todopic.com.ar/foros/index.php?topic=44517.0 (http://www.todopic.com.ar/foros/index.php?topic=44517.0)