TODOPIC
Microcontroladores PIC => Todo en microcontroladores PIC => Mensaje iniciado por: cvargcal en 06 de Mayo de 2015, 03:21:38
-
Encontré este código para arduino.
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?
-
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.
-
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.
#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; //
}
-
Veo que esta comentado:
/*
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:
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.
-
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. :-/
#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);
}
-
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.
-
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.
-
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
-
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.
-
No tiene nada que ver pero porque no lo corres a 64Mhz? :lol:
-
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)
#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.
-
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.
-
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:
#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.
-
Lo mas seguro que es por esto:
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
-
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 :)!
-
- 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.
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:
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.
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
}
-
......
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.
#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.
-
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.
-
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:
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256|RTCC_8_bit); //4,0 ms overflow
pero nunca entra en :
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?
-
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.
-
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.
-
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
-
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)