В настоящее время я пытаюсь отправить шестнадцатеричную команду радиомодулю xbee (режим API).
Вот мой код:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <unistd.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
int main()
{
int fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);if (fd < 0 ){
cout << "Error " << errno << " opening /dev/ttyUSB0: " << strerror(errno) << endl;
}
else
{
struct termios tty;
struct termios tty_old;
memset (&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0){
cout << "Error " << errno << " from tcgetattr: " << strerror (errno) << endl;
}
tty_old = tty;
cfsetispeed(&tty, B57600);
cfsetospeed(&tty, B57600);
tty.c_cflag &= ~PARENB;
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8;
tty.c_cflag &= ~CRTSCTS;
tty.c_lflag = 0;
tty.c_oflag = 0;
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 50;
tty.c_cflag |= CREAD | CLOCAL;
cfmakeraw(&tty);
tcflush(fd, TCIFLUSH);
if (tcsetattr(fd, TCSANOW, &tty) != 0) {
cout << "Error " << errno << " from tcsetattr" << endl;
}
unsigned char cmd1[] = {"\0x7E\0x00\0x04\0x08\0x69\0x43\0x54\0xF7"};
sleep(1);
int wr1 = write(fd, cmd1, 8);
sleep(1);
int rd;
int spot = 0;
char buff = '\0';char resp[128];
memset(resp, '\0', sizeof(resp));
do {
rd = read(fd, &buff, 1);
sprintf(&resp[spot], "%c", buff);
spot += rd;
} while (buff != '\r' && rd > 0);
if (rd<0){
cout << "Error reading: " << strerror(errno) << endl;
}
else if (rd==0) {
cout << "Read nothing!" << endl;
}
else {
cout << "Read: " << resp << endl;
}
close(fd);
}
return 0;
}
Я тоже попробовал вот так:
unsigned char cmd1[8];
cmd1[0] = 0X7E;
cmd1[1] = 0X00;
cmd1[2] = 0X04;
cmd1[3] = 0X08;
cmd1[4] = 0X69;
cmd1[5] = 0X43;
cmd1[6] = 0X54;
cmd1[7] = 0XF7;sleep(1);
int wr1 = write(fd, cmd1, 8);
Когда я использую командный режим AT, он прекрасно работает, вот код, который делает то же самое в командном режиме AT (спросите пчелу, как долго он длится в командном режиме после «+++»):
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <unistd.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
int main()
{
int fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);if (fd < 0 ){
cout << "Error " << errno << " opening /dev/ttyUSB0: " << strerror(errno) << endl;
}
else
{
struct termios tty;
struct termios tty_old;
memset (&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0){
cout << "Error " << errno << " from tcgetattr: " << strerror (errno) << endl;
}
tty_old = tty;
cfsetispeed(&tty, B57600);
cfsetospeed(&tty, B57600);
tty.c_cflag &= ~PARENB;
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8;
tty.c_cflag &= ~CRTSCTS;
tty.c_lflag = 0;
tty.c_oflag = 0;
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 50;
tty.c_cflag |= CREAD | CLOCAL;
cfmakeraw(&tty);
tcflush(fd, TCIFLUSH);
if (tcsetattr(fd, TCSANOW, &tty) != 0) {
cout << "Error " << errno << " from tcsetattr" << endl;
}
unsigned char cmd1[] = {"+++"};
sleep(1);
int wr1 = write(fd, cmd1, sizeof(cmd1) -1);
sleep(1);
//printf("%d \n", wr1);
unsigned char cmd2[] = {"ATCT\r"};
int rd;
int spot = 0;
char buff = '\0';
char resp[32];
memset(resp, '\0', sizeof(resp));
do {
rd = read(fd, &buff, 1);
sprintf(&resp[spot], "%c", buff);
spot += rd;
} while (buff != '\r' && rd > 0);
if (rd<0){
cout << "Error reading: " << strerror(errno) << endl;
}
else if (rd==0) {
cout << "Read nothing!" << endl;
}
else {
cout << "Read: " << resp << endl;
}int wr2 = write(fd, cmd2, sizeof(cmd2) -1);
//printf("%d \n", wr2);
spot = 0;
buff = '\0';sleep(1);
do {
rd = read(fd, &buff, 1);
sprintf(&resp[spot], "%c", buff);
spot += rd;
} while (buff != '\r' && rd > 0);
if (rd<0){
cout << "Error reading: " << strerror(errno) << endl;
}
else if (rd==0) {
cout << "Read nothing!" << endl;
}
else {
cout << "Read: " << resp << endl;
}
close(fd);
}
return 0;
}
Я получаю ошибку
Msgstr «Ошибка чтения: ресурс временно недоступен».
Я уверен, что устройство не используется чем-то другим, потому что код, который использует команду AT, работает нормально … Это как если бы Xbee не смог понять шестнадцатеричный код …
Я надеюсь, что кто-то еще уже сталкивался с этой проблемой …
Хорошо, так что это было немного адиот …
Я пытался прочитать ответ, заканчивающийся на \ r, но реальный ответ не заканчивался …
Я изменяю с:
do {
rd = read(fd, &buff, 1);
sprintf(&resp[spot], "%c", buff);
spot += rd;
} while (buff != 0x13 && rd > 0);
И теперь работает нормально. Это просто попытка прочитать несуществующие символы.
РЕДАКТИРОВАТЬ :
@VenushkaT задал мне вопрос о некоторых проблемах в этом коде. Так как сейчас я сделал что-то, что хорошо работает, я публикую свой новый код:
void R1logger::listenPort()
{
// Creation of a buffer to store data from radio module
fill_n(buff, 2048, '\0');
this->ind = 0;
while(this->fd > 0)
{
// Creation of a buffer that stores data from serial port
char mes[1024];
fill_n(mes, 1024, '0');
// read is a blocking call so this function will not return until it effectively reads some data or if there is a problem
int rd = read(this->fd, &mes, sizeof(mes));
/*struct timeval tv;
gettimeofday(&tv, NULL);
unsigned long long check1 = (unsigned long long)(tv.tv_sec) * 1000 + (unsigned long long)(tv.tv_usec) / 1000;*/
if (rd > 0)
{
storeInBuff(mes, rd);
fill_n(mes, 1024, '0');
// If some data are read, we can have only a part of the frame so we call "poll" to wait for the rest of the data with a 10ms timeout
struct pollfd fds;
fds.fd = this->fd;
fds.events = POLLIN | POLLPRI;
int slct = 1;
while (slct > 0)
{
slct = poll(&fds, 1, 10);
if (slct > 0)
{
rd = read(this->fd, &mes, sizeof(mes));
if (rd > 0)
{
storeInBuff(mes, rd);
}
else
{
close(this->fd);
serialConfig();
}
}
}
/*gettimeofday(&tv, NULL);
unsigned long long check2 = (unsigned long long)(tv.tv_sec) * 1000 + (unsigned long long)(tv.tv_usec) / 1000;
unsigned long tmps = check2 - check1;
cout << "Temps de lecture : " << tmps << endl;*/
/*gettimeofday(&tv, NULL);
check1 = (unsigned long long)(tv.tv_sec) * 1000 + (unsigned long long)(tv.tv_usec) / 1000;*/
// Once the message is entirely read, we extract the radio frames
findFrame(0);
/*gettimeofday(&tv, NULL);
check2 = (unsigned long long)(tv.tv_sec) * 1000 + (unsigned long long)(tv.tv_usec) / 1000;
tmps = check2 - check1;
cout << "Temps calcul + ecriture sur disque : " << tmps << endl;*/this->ind = 0;
fill_n(buff, 2048, '\0');
}
else
{
close(this->fd);
serialConfig();
}
}
}
Этот код использует меньше CPu, поскольку есть блокирующий вызов (чтение, выбор) и не установлена опция O_NONBLOCKING.
Я также рассматриваю случай, когда чтение не удается.
В другом посте некоторые люди разыгрывают мне советы по настройке последовательного порта (были некоторые ошибки в некоторых опциях, и они дали мне совет быть более совместимыми с POSIX, так что вот оно:
void R1logger::serialConfig()
{
// Open Serial Port
this->fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY);
if (this->fd < 0 )
{
cout << "Error " << errno << " opening /dev/ttyUSB0: " << strerror(errno) << endl;
}
else
{
//Configure Serial Port
struct termios tty;
if (tcgetattr (this->fd, &tty) != 0)
{
cout << "Error " << errno << " from tcgetattr: " << strerror (errno) << endl;
}
cfsetispeed(&tty, B57600);
cfsetospeed(&tty, B57600);
tty.c_cflag &= ~PARENB;
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8;
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 50;
tty.c_cflag |= CREAD | CLOCAL;
cfmakeraw(&tty);
tcflush(this->fd, TCIFLUSH);
if (tcsetattr(this->fd, TCSANOW, &tty) != 0)
{
cout << "Error " << errno << " from tcsetattr" << endl;
}
}
}
Других решений пока нет …