Error al comunicarse con GSM SIM900 con AVR.

0

Estoy intentando conectar la interfaz GSM SIM900 con el controlador AVR. Hasta ahora tengo Programación hecha que transmite el comando ATD y hace una Llama a mi celular. Respuesta GSM a este comando enviando OK. quiero Hacer un programa que también reciba esta respuesta OK y para hacer eso tengo Escrito mi código pero no funciona como debería. Estoy adjuntando mi código, por favor, dime dónde estoy haciendo mal.

CÓDIGO:

void serial_Init()
{
    UCSRB = (1<<TXEN)|(1<<RXEN);
    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()
 {
    //Wait untill a data is available

    while(!(UCSRA & (1<<RXC)))
    {
         //Do nothing
    }

     //Now USART has got data from host
    //and is available is buffer

    return UDR;
 }

 void uart_put(char data)
 {
     UDR=data;
     while(!(UCSRA&(1<<UDRE)));
 }

int main(void)
{
    DDRA = 0x00;
    DDRC = 0xFF;
    PORTA = 0xFF;
    serial_Init();
    char data[2];
    while(1)
    {
        if(PINA==0xFE)
        {
            serial_Tx("ATD<number>;\r\n");
            for(int j=0;j<=100;j++)
            {
                data[j] = serial_Rx();
                uart_put(data[j]);  
            }
        }
    }
}

Upate Resultado actual en hiperterminal:

    
pregunta anna carolina

1 respuesta

1

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" .

    
respondido por el Bence Kaulics

Lea otras preguntas en las etiquetas