Я пытаюсь изменить код, написанный здесь: Чтение/запись в последовательном порту Linux C, чтобы я мог управлять светодиодной вспышкой через последовательный (с адаптером USB-адаптер). Однако, когда я пытаюсь записать команду 12 на устройство, а затем я проверяю состояние светодиода с помощью GTKterm и осциллографа, кажется, что устройство получает только первый член, то есть получает команду ( "10000000000"). Я считаю, что настройки порта верны (хотя я мог быть совершенно не прав) и правильно подключили следующий образ команд, запущенных в GTKterm! http://oi59.tinypic.com/27wrexx.jpg. Кто-нибудь может понять, почему это может произойти? Большое спасибо Сэму
Мой код:
int flasher::allon(){
int USB = open( "/dev/ttyUSB0", O_RDWR| O_NOCTTY );
struct termios tty;
struct termios tty_old;
memset (&tty, 0, sizeof tty);
/* Error Handling */
if ( tcgetattr ( USB, &tty ) != 0 )
{
cout << "Error " << errno << " from tcgetattr: " << strerror(errno) << endl;
}
/* Save old tty parameters */
tty_old = tty;
/* Set Baud Rate */
cfsetospeed (&tty, (speed_t)B9600);
cfsetispeed (&tty, (speed_t)B9600);
/* Setting other Port Stuff */
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] = 1; // read doesn't block
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
tty.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
/* Make raw */
cfmakeraw(&tty);
/* Flush Port, then applies attributes */
tcflush( USB, TCIFLUSH );
if ( tcsetattr ( USB, TCSANOW, &tty ) != 0)
{
cout << "Error " << errno << " from tcsetattr" << endl;
}
unsigned char cmd[] = "111111111111 \r\n";
int n_written = 0;
do {
n_written += write( USB, &cmd[n_written], 1 );
}
while (cmd[n_written-1] != '\r' && n_written > 0);
int n = 0;
char buf = '\0';
/* Whole response*/
std::string response;
do
{
n = read( USB, &buf, 1 );
response.append( &buf );
}
while( buf != '\r' && n > 0);
if (n < 0)
{
cout << "Error reading: " << strerror(errno) << endl;
}
else if (n == 0)
{
cout << "Read nothing!" << endl;
}
else
{
cout << "Response: " << response<<endl;
}
return 0;
}
По этой причине ваш код не будет работать наверняка
string
имеет функцию append, которая принимает char *, но ожидает строку с нулевым завершением. Ваш buf - это всего лишь один символ, поэтому, если read() помещает в него символ, нет гарантии, что следует за ним в памяти, поэтому у вас нет нулевой строки с завершающим нулем, но неопределенного поведения.
Вероятно, вы должны предоставить буфер с более чем 1 символом, а затем использовать версию append
которая занимает длину, передавая n.
В противном случае замените
response.append( &buf );
с
response.push_back( buf );
который может работать, но, вероятно, менее эффективен, чем использование многосимвольного буфера. Вероятно, вы должны проверить результат read
прежде чем добавлять его. Поскольку код стоит, если read
не выполняется, вы добавите его в любом случае.
Это утверждение, если оно вообще действует, должно переключать порядок предложений while
while (cmd[n_written-1] != '\r' && n_written > 0);
если n_written не> 0, то LHS является неопределенным поведением. Так
while ( n_written > 0 && cmd[n_written-1] != '\r');
Вы уверены, что это правильное условие для завершения цикла? Я предполагаю, что \r
- это своего рода символ "сообщение поверх".
Если write()
возвратил -1, это не обязательно будет нажимать n_written
до или ниже 0.