#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
, ни отправка после каждой команды ничего не меняют.