У меня есть RPI 3 и модуль LoRa USB, и я пишу код на C ++ для подключения порта к устройству. Я могу подключиться к порту (который назначен как ttyUSBPort1 в правиле udev). Однако, когда я отправляю данные в порт, я получаю сообщение об ошибке. Я просто недостаточно знаю термин ios и связь через порт, чтобы определить, в этом ли проблема (да, я прочитал справочную страницу).
Модуль LoRa - это устройство RN2903, и ниже приведено Инструкции по интерфейсу UART на справочном листе:
Все настройки и команды модуля RN2903 передаются по UART с использованием интерфейса ASCII. Все команды должны быть завершены с помощью (пробелы добавлены для форматирования) , и любые генерируемые ими ответы также будут завершаться в той же последовательности. Настройки по умолчанию для интерфейса UART: 57600 бит / с, 8 бит, без контроля четности, 1 стоп-бит, без контроля потока.
При отправке команд я вижу, что устройство отвечает «invalid_parameter» контролируя порт с помощью
sudo cat /dev/ttyUSBPort1
Я предполагаю, что некоторые из флагов термина ios установлены неправильно, или команда записи установлена неправильно. Вот код, который у меня есть, который устанавливает порт:
int openPort(void) {
struct termios tty;
memset(&tty, 0, sizeof tty);
if ((usb_port = open(device, O_RDWR))>=0) {// | O_NOCTTY | O_SYNC
std::cout << "DEVICE OPENED: " << device << " handle number: " << usb_port << std::endl;
} else {
fprintf(stderr, "unable to open serial device");
return -1;
}
if(tcgetattr(usb_port, &tty) != 0) {
printf("Error %i \n", errno);
}
cfsetispeed(&tty, B57600);
cfsetospeed(&tty, B57600);
tty.c_cflag &= ~PARENB; // Make 8n1
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8;
tty.c_cflag &= ~CRTSCTS; // no flow control
tty.c_cc[VMIN] = 0; // read doesn't block
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
tcflush( usb_port, TCIFLUSH );
if (tcsetattr(usb_port, TCSANOW, &tty) != 0) {
printf("Error %i\n", errno);
}
return usb_port;
}
А вот команда вызова для получения информации о версии с устройства:
void radioCMD(string tmp) {
string tmp2 = tmp + "\r\n";
int n = tmp2.length();
char cmd[n];
strcpy(cmd, tmp2.c_str());
std::cout << write(usb_port, cmd, sizeof(cmd)) << " " << cmd << "Writing to " << usb_port << " Delay: " << delay << " Command Size: " << sizeof(cmd) << std::endl;
}
void setupRadio() {
radioCMD("sys get ver");
usleep(delay);
}
При записи в консоль std: : cout, я вижу это:
13 sys get ver
Writing to 3 Delay: 200000 Command Size: 13
, показывающий, что сообщение действительно пишется правильно.
Вывод cat из устройства должен отвечать примерно так (из таблицы данных) :
2.3.6.1 sys get ver Ответ: RN2903 XYZ MMM ДД ГГГГ ЧЧ: ММ: СС, где XYZ - версия прошивки, МММ - месяц, ДД - день, ЧЧ: ММ: СС - час, минуты, секунды (формат: [HW] [FW] [Date] [Time]). [Дата] и [Время] относятся к выпуску прошивки. Эта команда возвращает информацию, относящуюся к аппаратной платформе, версии прошивки, дате выпуска и отметке времени при создании прошивки. Пример: sys get ver
На самом деле я получаю "invalid_param \ r \ n", который является соответствующим ответом от устройства, если в вызове что-то не так.
Есть идеи, где я могу ошибаться?
РЕДАКТИРОВАТЬ
благодаря Теду, который указал мне правильное направление и упростил мой код. Было два пропущенных флага ios. После того, как я установил эти (последние два), он работает нормально.
tty.c_cflag &= ~PARENB; // Make 8n1
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8;
tty.c_cflag &= ~CRTSCTS; // no flow control
tty.c_cc[VMIN] = 0; // read doesn't block
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
***ADDITIONAL TWO FLAGS THAT FIXED IT****
tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed
tty.c_oflag &= ~OCRNL; // Prevent conversion of newline to carriage return/line feed
Новая функция записи вызова:
void radioCMD(string cmd) {
cmd += "\r\n";
write(usb_port, cmd.c_str(), cmd.size());
}