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,datacontendrá"OK" o "ERROR" .