Envío de información de batería adjunta con GSM a través de SMS

Estoy escribiendo un código C para recibir la batería usando el módem GSM SIM 800E. Estoy usando AtMega16 uC. Aquí he usado comandos AT para obtener información sobre la batería.

void uart_send(unsigned char ch)     //Function to send via UART
{
    while(!(UCSRA &(1<<UDRE)));
    UDR=ch;
}

void bat()                         //Function to get battery info and send SMS via UART
{   
    int x;
    char battery[16];
    UCSRB &= ~(1<<UDRIE);
    writecommand("AT+CBC");        //AT command to get battery status(My program stuck here)
    for(int x = 0;x<20;x++)        //Reading 20 characters by the response of AT+CBS
    {
        while(!(UCSRA & (1<<RXC)));
        battery[x] = UDR;
    }

    UCSRB |= (1<<RXCIE);

    for(int x=1;x<20;x++)          //sending 20 characters to UART
    {
       uart_send(*battery);
    }
}

int main()
{

    DDRB=0xff;                     //PORT as output port for LCD
    uart_init();                   //initializing UART
    _delay_ms(1000);
    writecommand("AT");
    writecommand("AT+CMGF=1");      //setting GSM to Text Mode
    writecommand("AT+CNMI=2,0,2,0,0");

    while(1)
    {
        bat();
        transmit("AT+CMGS=\"+9195xxxxxxxx\"\r");  //Sending SMS with values in UART buffer
        _delay_ms(10);
        uart_send(26);    // command to send SMS
}

Cuando ejecuto el código, se atasca en la función bat () (en "AT + CBC"), muestra la información de la batería en la pantalla LCD y en el terminal, pero no la envía por sms y el programa no continúa. Sugiérame formas de obtener la información a través de SMS.

Editar

Con respecto a los comentarios de Loongcat

Recibo 20 caracteres después del comando "AT+CBC", entonces debería recibir eso. este es el buclefor(int x = 0;x<20;x++)

¿Qué tipo de módulo GSM utiliza?
Estoy usando el módulo SIM800E GSM

Respuestas (2)

1) AT+CMGS debe ir antes del cuerpo del sms (colocar bat() después de transmitir())

2) No está detectando el final de la respuesta al comando AT + CBC, esa es una mala manera. Debes recibir símbolos hasta que obtengas "OK"

Recibo 20 caracteres después del comando "AT+CBC", entonces debería recibir eso. este es el bucle for(int x = 0;x<20;x++)
Creo que causará problemas si envía un AT+CMGSmensaje AT+CBC, el envío del mensaje puede verse interrumpido debido al nuevo comando AT.
@BenceKaulics tienes razón, me lo perdí. Primero necesita obtener la respuesta +CBC, luego comenzar a escribir sms con +CMGS

Veo los siguientes problemas en tu código:

  1. En la bat()función, almacena la información de la batería en una cadena local ( char battery[16];)
    • El tamaño de esta matriz es 16 pero está guardando 20 caracteres ( for(int x = 0;x<20;x++)) en ella. Si espera 20 caracteres, debe usar una matriz con un tamaño de 20 + 1 , más uno para el carácter nulo de terminación: \0.
    • Una variable local se asigna en la pila y, por lo tanto, no está disponible una vez que la función termina de ejecutarse. Es posible que aún pueda alcanzar el valor almacenado, pero no hay garantía de ello, ya que se marcará como espacio libre en la memoria y es posible que se sobrescriba alguna otra función.
    • Su uart_sendfunción espera unsigned charcomo parámetro, por lo que esta llamada es incorrecta: uart_send(*battery);debería seruart_send(battery[x]);

En el estado actual de su programa no habrá ningún problema ya que transmite esta cadena en la bat()función, pero debe transmitirla después del AT+CMGScomando, donde esta cadena no estará disponible.

Si solo llama a la bat()función después de AT+CMGS, causará problemas, porque el AT+CBCcomando se enviará al módulo, que responderá. Creo que interrumpirá la ejecución del AT+CMGScomando.

Por lo tanto, le sugiero que primero guarde la información de la batería en una variable que no se pierda y la envíe en el momento correcto. Una secuencia correcta de envío de mensajes debería verse así:

  1. Obtenga la información de la batería del módulo y guárdela para su uso posterior.
  2. Envía el AT+CMGS="+9195xxxxxxxx"comando.
  3. Espere a que el módulo responda con: >, esto significa que el módulo ha procesado el número de teléfono y ahora está listo para recibir el cuerpo del SMS, [información de la batería].
  4. Cuando recibió el >personaje, puede enviar la información de la batería al módulo.
  5. Ahora, envíe el mensaje usando el <CTRL>-<Z>carácter, 0x26en ASCII.
  6. En la entrega exitosa, el módulo devolverá un ID de mensaje como:+CMGS: 62
o *(batería+x), lo mismo
De hecho, ese también funciona.