UART всегда повторяет отправленную команду (малина с SIM800)

#uart #raspberry-pi4 #sim800

Вопрос:

Я пытаюсь подключить модуль SIM800L к Raspberry Pi 4 через UART, используя следующий код:

 #include <iostream>
#include <stdio.h>
#include <unistd.h>         //Used for UART
#include <fcntl.h>          //Used for UART
#include <termios.h>        //Used for UART


using namespace std;

//-------------------------
//----- SETUP USART 0 -----
//-------------------------
//At bootup, pins 8 and 10 are already set to UART0_TXD, UART0_RXD (ie the alt0 function) respectively
int uart0_filestream = -1;

//************************************
//************************************
//********** UART TX STRING **********
//************************************
//************************************
void uart_tx_string (string tx_string)
{
    if (uart0_filestream != -1)
    {
        int count = write(uart0_filestream, (char*)tx_string.c_str(), tx_string.length());      //Filestream, bytes to write, number of bytes to write
        if (count < 0)
        {
            printf("UART TX errorn");
        }
        else
        {
            cout << "sent " << count << " bytes" << endl;
        }
    }
}

void read()
{
    //----- CHECK FOR ANY RX BYTES -----
    if (uart0_filestream != -1)
    {
        int t = 0;
        int rx_length = 0;
        do
        {
            // Read up to 255 characters from the port if they are there
            unsigned char rx_buffer[256];
            rx_length = read(uart0_filestream, (void*)rx_buffer, 255);      //Filestream, buffer to store in, number of bytes to read (max)
            if (rx_length < 0)
            {
                //An error occured (will occur if there are no bytes)
                printf("errorn");
            }
            else if (rx_length == 0)
            {
                //No data waiting
                printf("no datan");
            }
            else
            {
                //Bytes received
                rx_buffer[rx_length] = '';
                printf("[%i] %i bytes read : %sn", t, rx_length, rx_buffer);
            }
        }while(rx_length >= 255 amp;amp; t   < 10);
    }
    else
    {
        printf("steam closedn");
    }
}

void setupUart()
{
    
    //OPEN THE UART
    //The flags (defined in fcntl.h):
    //  Access modes (use 1 of these):
    //      O_RDONLY - Open for reading only.
    //      O_RDWR - Open for reading and writing.
    //      O_WRONLY - Open for writing only.
    //
    //  O_NDELAY / O_NONBLOCK (same function) - Enables nonblocking mode. When set read requests on the file can return immediately with a failure status
    //                                          if there is no input immediately available (instead of blocking). Likewise, write requests can also return
    //                                          immediately with a failure status if the output can't be written immediately.
    //
    //  O_NOCTTY - When set and path identifies a terminal device, open() shall not cause the terminal device to become the controlling terminal for the process.
    
    uart0_filestream = open("/dev/serial0", O_RDWR | O_NOCTTY | O_NDELAY);      //Open in non blocking read/write mode
    if (uart0_filestream == -1)
    {
        //ERROR - CAN'T OPEN SERIAL PORT
        printf("Error - Unable to open UART.  Ensure it is not in use by another applicationn");
    }
    
    //CONFIGURE THE UART
    //The flags (defined in /usr/include/termios.h - see http://pubs.opengroup.org/onlinepubs/007908799/xsh/termios.h.html):
    //  Baud rate:- B1200, B2400, B4800, B9600, B19200, B38400, B57600, B115200, B230400, B460800, B500000, B576000, B921600, B1000000, B1152000, B1500000, B2000000, B2500000, B3000000, B3500000, B4000000
    //  CSIZE:- CS5, CS6, CS7, CS8
    //  CLOCAL - Ignore modem status lines
    //  CREAD - Enable receiver
    //  IGNPAR = Ignore characters with parity errors
    //  ICRNL - Map CR to NL on input (Use for ASCII comms where you want to auto correct end of line characters - don't use for bianry comms!)
    //  PARENB - Parity enable
    //  PARODD - Odd parity (else even)
    struct termios options;
    tcgetattr(uart0_filestream, amp;options);
    options.c_cflag = B9600 | CS8 | CREAD | CLOCAL;     //<Set baud rate     B9600 B115200 CLOCAL
    options.c_iflag = IGNPAR;
    options.c_oflag = 0;
    options.c_lflag = 0;
    tcflush(uart0_filestream, TCIFLUSH);
    tcsetattr(uart0_filestream, TCSANOW, amp;options);
}

int main(int argc, char *argv[])
{
    cout << "sending..." << endl;
    setupUart();
    
    uart_tx_string("ATrn");
    uart_tx_string("AT CSQrn");
    uart_tx_string("AT CREG?rn");
    uart_tx_string("AT ATE0rn");
    uart_tx_string("AT ECHO?rn");
    uart_tx_string("AT ECHO=?rn");
    uart_tx_string("ATrn");

    
    cout << "reading..." << endl;
    sleep(1);
    read();
    
    cout << "done" << endl;
    
    close(uart0_filestream);
    
    return 0;
}
 

Код должен вывести какой-то разумный ответ от модуля, однако он всегда печатается ПО команде, которую я пытаюсь отправить.

 sending...
sent 4 bytes
sent 8 bytes
sent 10 bytes
sent 9 bytes
sent 10 bytes
sent 11 bytes
sent 4 bytes
reading...
[0] 56 bytes read : AT
AT CSQ
AT CREG?
AT ATE0
AT ECHO?
AT ECHO=?
AT

done
 

Электропроводка выглядит следующим образом:

  • Raspberry Tx -> SIM Rx
  • Raspberry Rx -> SIM TX

Проводка кажется правильной, когда я отсоединяю SIM-модуль от платы прототипа, ничего не получено.

Мой /boot/cmdline.txt выглядит следующим образом:

 root=/dev/mmcb root=PARTUUID=57509151-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles
 

Комментарии:

1. Скопированный вами код (без подтверждения) низкого качества. См.раздел Правильная настройка режимов клемм и Руководство по последовательному программированию для операционных систем POSIX . Ваша программа использует неблокирующий режим, который, вероятно, не должен использоваться, так как в вашем коде нет ничего, что в этом нуждается. Ваша программа использует неканонический режим, чего, вероятно, не должно быть, так как она, вероятно, читает строки. Вероятно, вашей программе следует использовать канонический режим блокировки для доступа к последовательному терминалу.

2. ЭХО отключено для c_iflag (параметры.c_iflag = IGNPAR;) и c_oflag (параметры.c_oflag = 0;), команда AT ATE0 должна отключить эхо на стороне устройства, но я все еще получаю эхо.

3. «Команда AT ATE0 должна отключить эхо на стороне устройства» — Неверно, это поддельная команда модема. Ваша программа также передает модему команды, не дожидаясь ответа/запроса между каждой командой. Ваша программа отправляет неверную последовательность символов завершения командной строки.

4. Ни отправка ATE0 , ни отправка после каждой команды ничего не меняют.