Отправка информации о батарее, прикрепленной к GSM, через SMS

Я пишу код C для получения батареи с помощью GSM-модема SIM 800E. Я использую AtMega16 uC. Здесь я использовал AT-команды для получения информации о батарее.

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
}

Когда я запускаю код, он застревает в функции bat () (в «AT + CBC»), он отображает информацию о батарее на ЖК-дисплее и терминале, но не отправляет ее по смс, и программа не продолжается дальше. Подскажите, пожалуйста, как получить информацию через смс.

Редактировать

Относительно комментариев Loongcat

Я получаю 20 символов после команды «AT + CBC», тогда он должен это получить. это петляfor(int x = 0;x<20;x++)

Какой тип GSM модуля вы используете?
Я использую GSM модуль SIM800E.

Ответы (2)

1) AT+CMGS должен идти перед телом смс (поместите bat() после передачи())

2) Вы не определяете конец ответа на команду AT+CBC, это плохой способ. Вы должны получать символы, пока не получите «ОК».

Я получаю 20 символов после команды «AT + CBC», тогда он должен это получить. это цикл for(int x = 0;x<20;x++)
Я думаю, что это вызовет проблемы, если он отправит AT+CMGSзатем сообщение AT+CBC, отправка сообщения может быть прервана из-за новой AT-команды.
@BenceKaulics, ты прав, пропустил это. Ему нужно сначала получить ответ +CBC, а затем начать печатать смс с помощью +CMGS

Я вижу следующие проблемы в вашем коде:

  1. В bat()функции вы сохраняете информацию о батарее в локальной строке ( char battery[16];)
    • Размер этого массива равен 16 , но вы сохраняете в нем 20 символов ( ). for(int x = 0;x<20;x++)Если вы ожидаете 20 символов, вы должны использовать массив размером 20 + 1 плюс один для завершающего нулевого символа: \0.
    • Локальная переменная размещена в стеке и поэтому недоступна после завершения выполнения функции. Вы все еще можете получить сохраненное значение, но это не гарантируется, потому что оно будет помечено как свободное место в памяти, и некоторые другие функции могут перезаписать его.
    • Ваша uart_sendфункция ожидает unsigned charв качестве параметра, поэтому этот вызов неверен: uart_send(*battery);он должен бытьuart_send(battery[x]);

В текущем состоянии вашей программы не будет никаких проблем, так как вы передаете эту строку в функции bat(), но вы должны передавать ее после AT+CMGSкоманды, где эта строка не будет доступна.

Если просто вызывать bat()функцию после AT+CMGS, это вызовет проблемы, потому что AT+CBCкоманда будет отправлена ​​в модуль, который за нее будет отвечать. Я думаю, что это прервет выполнение команды AT+CMGS.

Поэтому я предлагаю вам сначала сохранить информацию о батарее в переменную, которая не потеряется, и отправить ее в нужное время. Правильная последовательность отправки сообщения должна выглядеть примерно так:

  1. Получите информацию о батарее из модуля и сохраните ее для последующего использования.
  2. Отправить AT+CMGS="+9195xxxxxxxx"команду.
  3. Подождите, пока модуль ответит: >, это означает, что модуль обработал номер телефона и теперь готов принять тело SMS, [информация о батарее].
  4. Когда вы получили >персонажа, вы можете отправить информацию о батарее в модуль.
  5. Теперь отправьте сообщение <CTRL>-<Z>, используя символ 0x26в ASCII.
  6. При успешной доставке модуль вернет идентификатор сообщения, например:+CMGS: 62
или *(батарея+x), то же самое
Действительно, этот тоже работает.