Senden von Batterieinformationen, die mit GSM per SMS verbunden sind

Ich schreibe einen C-Code für den Batterieempfang mit dem GSM-Modem SIM 800E. Ich verwende AtMega16 uC. Hier habe ich AT-Befehle verwendet, um Batterieinformationen zu erhalten.

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
}

Wenn ich den Code ausführe, bleibt er in der bat()-Funktion (bei "AT+CBC") hängen, er zeigt die Batterieinformationen auf dem LCD und dem Terminal an, sendet sie aber nicht per SMS und das Programm fährt nicht fort. Bitte schlagen Sie mir vor, wie ich die Informationen per SMS erhalten kann.

Bearbeiten

Zu Kommentaren von Loongcat

Ich erhalte 20 Zeichen nach dem Komman "AT+CBC", dann sollte es das erhalten. das ist die Schleifefor(int x = 0;x<20;x++)

Welche Art von GSM-Modul verwenden Sie?
Ich verwende das GSM-Modul SIM800E

Antworten (2)

1) AT+CMGS muss vor dem SMS-Text stehen (platzieren Sie bat() nach transmit())

2) Sie erkennen das Ende der Antwort auf den AT + CBC-Befehl nicht, das ist ein schlechter Weg. Sie müssen Symbole erhalten, bis Sie "OK" erhalten

Ich erhalte 20 Zeichen nach dem Komman "AT+CBC", dann sollte es das erhalten. das ist die Schleife für(int x = 0;x<20;x++)
Ich denke, es wird Probleme geben, wenn er eine sendet , AT+CMGSdann AT+CBCwird das Senden der Nachricht möglicherweise wegen des neuen AT-Befehls unterbrochen.
@BenceKaulics du hast Recht, das verpasst. Er muss zuerst eine +CBC-Antwort erhalten und dann mit der SMS-Eingabe mit +CMGS beginnen

Ich sehe folgende Probleme in deinem Code:

  1. In der bat()Funktion speichern Sie die Batterieinformationen in einem lokalen String ( char battery[16];)
    • Die Größe dieses Arrays beträgt 16 , aber Sie speichern 20 Zeichen ( for(int x = 0;x<20;x++)) darin. Wenn Sie 20 Zeichen erwarten, sollten Sie ein Array mit einer Größe von 20 + 1 verwenden , plus eins für das abschließende Nullzeichen: \0.
    • Eine lokale Variable wird auf dem Stapel zugewiesen und ist daher nicht verfügbar, sobald die Ausführung der Funktion beendet ist. Möglicherweise können Sie den gespeicherten Wert noch erreichen, aber dafür gibt es keine Garantie, da er als freier Speicherplatz markiert wird und möglicherweise von einer anderen Funktion überschrieben wird.
    • Ihre uart_sendFunktion erwartet unsigned charals Parameter, also ist dieser Aufruf falsch: uart_send(*battery);es sollte seinuart_send(battery[x]);

Im aktuellen Zustand Ihres Programms wird es kein Problem geben, da Sie diesen String in der bat()Funktion übertragen, aber Sie sollten ihn nach dem AT+CMGSBefehl übertragen, wo dieser String nicht verfügbar ist.

bat()Wenn Sie die Funktion einfach nach dem aufrufen AT+CMGS, wird es Probleme geben, da der AT+CBCBefehl an das Modul gesendet wird, das darauf antwortet. Ich denke, es wird die Ausführung des AT+CMGSBefehls unterbrechen.

Daher schlage ich vor, dass Sie die Batterieinformationen zuerst in einer Variablen speichern, die nicht verloren geht, und sie dann zur richtigen Zeit senden. Eine korrekte Nachrichten-Sendesequenz sollte etwa so aussehen:

  1. Holen Sie sich die Batterieinformationen vom Modul und speichern Sie sie zur späteren Verwendung.
  2. Senden Sie den AT+CMGS="+9195xxxxxxxx"Befehl.
  3. Warten Sie, bis das Modul antwortet mit: >, das bedeutet, dass das Modul die Telefonnummer verarbeitet hat und nun bereit ist, den SMS-Text zu empfangen, [Batterieinfo].
  4. Wenn Sie das >Zeichen erhalten haben, können Sie die Batterieinformationen an das Modul senden.
  5. Senden Sie nun die Nachricht mit dem <CTRL>-<Z>Zeichen 0x26in ASCII.
  6. Bei erfolgreicher Zustellung gibt das Modul eine Nachrichten-ID wie folgt zurück:+CMGS: 62
oder *(Batterie+x), dieselben Dinge
Tatsächlich funktioniert der auch.