El código del receptor aún tiene un error.
for(int j=0;j<=100;j++)
{
data[j] = serial_Rx();
uart_put(data[j]);
}
En este bucle, todavía está sobreindexando la matriz data
, que solo tiene un tamaño de 2. Debe aumentar su tamaño a 101 para que coincida con su bucle for
. Probablemente un valor más pequeño también será suficiente, pero el tamaño de la matriz debe coincidir con el bucle for
.
Como veo en el terminal, el Eco local está deshabilitado en su módulo, por lo que responderá a la mayoría de los comandos con "\r\nOK\r\n"
o "\r\nERROR\r\n"
. (Con Local Echo habilitado, también devolvería el comando). Por lo tanto, el mensaje más largo que podría recibir es el mensaje de error que tiene 9 caracteres de longitud.
char data[10]; //9 for data 1 for terminating null character
for(int j=0;j<9;j++)
{
data[j] = serial_Rx();
}
data[9] = ' if(strstr(data,"OK") != NULL)
{
// it contains "OK"
// do stuff
}
'; // close string with a terminating null character
Ahora, la respuesta se presenta en la matriz como una cadena adecuada. Está listo para ser procesado por sus propias funciones o por la biblioteca de cadenas C estándar ( #include <string.h>
).
O aún puede enviar la cadena completa al hiperterminal y también a serial_Tx(data)
.
Procese el resultado del código anterior con la función strstr () de string.h
void serial_Init()
{
UCSRB |= (1<<TXEN)|(1<<RXEN)|(1<<RXCIE); // enable receive interrupts
UCSRC |= (1<<UCSZ1)|(1<<UCSZ0)|(1<<URSEL);
UBRRL = 51;
}
void serial_Tx(char *str)
{
for (unsigned int i=0;str[i]!=0;i++)
{
UDR=str[i];
while(!(UCSRA&(1<<UDRE)));
}
}
char serial_Rx()
{
while(!(UCSRA & (1<<RXC)));
return UDR;
}
void uart_put(char data)
{
UDR=data;
while(!(UCSRA&(1<<UDRE)));
}
///////////////////////////////////
// global variables for UART rx
///////////////////////////////////
int buffer_index = 0, started = 0;
unsigned char buffer[250];
unsigned char k;
ISR(USART_RXC_vect)
{
k = UDR;
if(k == '\r' && started == 1) // stop if is has already started and "\r" received
{
started = 2; // finished, ready for further processing
buffer[buffer_index] = 'for(int j=0;j<=100;j++)
{
data[j] = serial_Rx();
uart_put(data[j]);
}
'; // terminate string
}
else if(started == 1) // if started save data
{
buffer[buffer_index++] = k;
}
else if(k == '\n') // start saving data at first "\n"
{
started = 1; // set process started
}
}
int main(void)
{
DDRA = 0x00;
DDRC = 0xFF;
PORTA = 0xFF;
serial_Init();
sei();
while(1)
{
if(PINA==0xFE)
{
buffer_index = 0;
started = 0;
serial_Tx("ATD<number>;\r\n");
}
if(started == 2) // check if rx is finished
{
// check if OK
serial_Tx(buffer);
}
}
}
Una forma más precisa de recibir datos en serie es habilitar UART recibir interrupciones completas estableciendo RXCIE
bit en el registro UCSRB
: UCSRB |= (1<<RXCIE);
Si observa las posibles respuestas, la información efectiva se incluye entre los caracteres '\n'
y '\r'
, lo que hace que las condiciones de inicio y final sean excelentes al analizar la respuesta del GSM en la rutina de servicio de interrupción.
El código completo es el siguiente:
char data[10]; //9 for data 1 for terminating null character
Explicación ISR:
Entonces, la estructura de los mensajes que estamos esperando es la siguiente: <\r><\n><data><\r><\n>
. En base a esto, queremos comenzar a guardar los datos entrantes después de que se detectó el primer \n
y mantenerlo hasta que alcancemos un \r
.
Ahora los roles de las variables utilizadas:
-
k
es una variable temporal en la que se cargan los caracteres recibidos, luego podemos verificar si es un \n
, \r
o datos de carácter y manejamos en consecuencia.
-
started
es para rastrear las diferentes fases:
started = 0
significa que no hemos recibido el primer \n
hasta ahora, por lo que seguimos esperando ( else if(k == '\n')
rama). Una vez que llega \n
, lo establecemos en 1
, lo que indica que podemos comenzar a cargar los caracteres recibidos ( k
) en nuestra matriz.
started = 1
significa que se ha cumplido la condición de inicio, los datos se pueden almacenar en la matriz.
started = 2
cuando se inició el procesamiento, por lo tanto, si el valor anterior era 1
y recibimos un \r
(rama if(k == '\r' && started == 1)
). El valor 2
detiene la carga de la matriz e indica a la función principal que los datos completos se presentan en la matriz.
También tengo un módulo GSM conectado a un AVR, así que probé el código del ISR y obtengo el siguiente resultado:
Deestamanera,data
contendrá"OK"
o "ERROR"
.