#c #linux #serial-port
#c #linux #последовательный порт
Вопрос:
Я успешно пишу код в Windows и выполняю обмен данными через последовательный порт. Но пока не в Linux.
Вот код, который я написал: я использовал Picocom
для проверки того, что я могу обмениваться данными через последовательные порты через мой кабель (USB-модем с НУЛЬ-модемом на USB).
Установка кода на None blocking приводит к « errno: 11 Resource temporarily unavailable
» как на клиенте, так и на сервере.»
Когда я устанавливаю блокировку, она зависает в коде при методе чтения файла. Если я прокомментирую эту строку, она запустится… но не получение данных.
Server sends packets continuous.
Client receives packets continuous.
Problem seems to be bytes aren't received at the client. They are sent, however at the server.
CLIENT:
RECV(1611912): NumChars: 0 String:
RECV(1611913): NumChars: 0 String:
RECV(1611918): NumChars: 0 String:
RECV(1611919): NumChars: 0 String:
RECV(1611920): NumChars: 0 String:
SERVER:
SENT(106775): NumChars: 10 String: 0123456789
SENT(106776): NumChars: 10 String: 0123456789
SENT(106777): NumChars: 10 String: 0123456789
SENT(106778): NumChars: 10 String: 0123456789
SENT(106779): NumChars: 10 String: 0123456789
to run:
g -o sp serialport.cpp
client: ./sp /dev/ttyS0 c
server: ./sp /dev/ttyS4 s
#include <sys/ioctl.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
class C_SerialPort
{
private:
int giFD;
char gpcDevice[100] = {0};
public:
//------------------------------------------------
//
//------------------------------------------------
int GetError(char* pcMessage = (char*)"")
{
char pcError[100] = {0};
sprintf(pcError, " (%s): errno: %d %sn", pcMessage, errno, strerror(errno));
if(errno > 0)
{
printf("%s", pcError);
}
return errno;
}
//------------------------------------------------
//
//------------------------------------------------
int Connect()
{
return Connect((char*)"/dev/ttyS0");
//return Connect((char*)"/dev/ttyUSB0");
}
//------------------------------------------------
//
//------------------------------------------------
int Connect(char *pcDevice)
{
strcpy(gpcDevice, pcDevice);
struct termios s_TA;
// Open the serial port
giFD = open(gpcDevice, O_RDWR | O_NOCTTY | O_NDELAY | O_FSYNC );
if(giFD < 0)
{
printf("open_port: Unable to open %sn%s", gpcDevice, strerror(errno));
printf("EXITING...n");
return 1;
}
else
{
printf("Connect Device: %sn", gpcDevice);
}
// get attributes
if(tcgetattr(giFD, amp;s_TA) != 0)
{
GetError((char*)"tcgetattr");
printf("EXITING...n");
return 1;
}
// clear terminalAttributes data
//memset(amp;s_TA, 0, sizeof(struct termios));
if(0)
{
// 57600 bauds; 8 bits per word; Ignore modem control lines; Enable receiver.
s_TA.c_cflag = B57600 | CS8 | CLOCAL | CREAD;
// Ignore framing errors and parity errors.
s_TA.c_iflag = IGNPAR | ONLCR;
//Enable implementation-defined output processing.
s_TA.c_oflag = OPOST;
// min time; min bytes to read
s_TA.c_cc[VTIME] = 1;
s_TA.c_cc[VMIN] = 1;// none zero blocks
}
else
{
cfsetospeed(amp;s_TA, B9600);
cfsetispeed(amp;s_TA, B9600);
s_TA.c_cflag |= (CLOCAL | CREAD); /* ignore modem controls */
s_TA.c_cflag amp;= ~CSIZE;
s_TA.c_cflag |= CS8; /* 8-bit characters */
s_TA.c_cflag amp;= ~PARENB; /* no parity bit */
s_TA.c_cflag amp;= ~CSTOPB; /* only need 1 stop bit */
s_TA.c_cflag amp;= ~CRTSCTS; /* no hardware flowcontrol */
/* setup for non-canonical mode */
s_TA.c_iflag amp;= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
s_TA.c_lflag amp;= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
s_TA.c_oflag amp;= ~OPOST;
/* fetch bytes as they become available */
s_TA.c_cc[VMIN] = 1; // 0 1
s_TA.c_cc[VTIME] = 1; // 0 1
}
//int iVal = fcntl(giFD, F_SETFL, 0); // set blocking?
//printf("file status = 0x%xn", iVal);
//GetError((char*)"fcntl");
// Set the port to our state
if (tcsetattr(giFD, TCSANOW, amp;s_TA) != 0)
{
GetError((char*)"tcsetattr");
printf("EXITING...n");
return 1;
}
// flushes data written but not transmitted.
// flushes data received but not read.
tcflush(giFD, TCOFLUSH);
tcflush(giFD, TCIFLUSH);
printf("CONNECTION OKn");
//return giFD;
return 0;
}
//------------------------------------------------
//
//------------------------------------------------
void Disconnect(void)
{
close(giFD);
printf("nPort 1 has been CLOSED and %d is the file descriptionn", giFD);
GetError((char*)"Disconnect");
}
//------------------------------------------------
//
//------------------------------------------------
int SendArray(unsigned char *buffer, int len)
{
int n = write(giFD, buffer, len);
// error catch
if(n < 0)
GetError((char*)"write");
return n;
}
//------------------------------------------------
//
//------------------------------------------------
int GetArray (unsigned char *buffer, int len)
{
int n = 0;
int len2 = BytesToRead();
n = read(giFD, buffer, len2); // this line is an issue? with settings?
// error catch
//if(n < 0)
// GetError((char*)"read");
return n;
}
//------------------------------------------------
//
//------------------------------------------------
void Clear()
{
tcflush(giFD, TCIFLUSH);
tcflush(giFD, TCOFLUSH);
}
//------------------------------------------------
//
//------------------------------------------------
int BytesToRead()
{
int iBytes = 0;
ioctl(giFD, FIONREAD, amp;iBytes);
//printf("Byte2Read: %dn", iBytes);
// error catch
GetError((char*)"BytesToRead");
return iBytes;
}
};
//------------------------------------------------
//
//------------------------------------------------
int main(int argc, char const *argv[])
{
// device
char *pcDevice = (char*)argv[1];
printf("init:device:%sn", pcDevice);
// connection type
char cConnType = argv[2][0];
printf("ConnectionType:%cn", cConnType);
// instantiate SerialPort
C_SerialPort c_SP;
// connect
int iReturn = c_SP.Connect(pcDevice);
if(iReturn != 0)
{
printf("EXITING...n");
return 1;
}
// clear buffer
c_SP.Clear();
printf("clearn");
printf("prior...n");
// main loop
while(1)
{
int iSleep_ms = 200;
usleep(iSleep_ms);
char pcArray[100] = {0};
int iNumChars = 0;
if(cConnType == 's')
{
static long lCount = 0;
// Send
strcpy(pcArray, "0123456789");
iNumChars = c_SP.SendArray((unsigned char*)pcArray, 10);
if(iNumChars > 0)
{
printf("SENT(%ld): NumChars: %d String: %sn", lCount, iNumChars, pcArray);
}
lCount ;
}
if(cConnType == 'c')
{
static long lCount = 0;
// Receive
iNumChars = c_SP.GetArray((unsigned char*)pcArray, sizeof(pcArray));
if(iNumChars > 0)
{
printf("RECV(%ld): NumChars: %d String: %sn", lCount, iNumChars, pcArray);
}
else
{
//printf("RECV: NumChars: %d String: %sn", iNumChars, pcArray);
}
lCount ;
}
}
c_SP.Disconnect();
return 0;
}
Комментарии:
1. Проблема, похоже, в том, что байты не принимаются клиентом. Однако они отправляются на сервер.
2. Сколько данных вы хотите
GetArray
получать при каждом вызове?3. Он получает то, что находится в буфере, и должен возвращать это количество.
4. А если буфер пуст?
5. результаты показаны выше
Ответ №1:
У вас есть четыре основные ошибки:
- Ваша
GetArray
функция игнорирует возвращаемое значениеBytesToRead
. Он должен считывать меньший размер буфера или количество доступных байтов. - Ваш код не способен разумно обрабатывать случай, когда
BytesToRead
возвращает ноль. - Вы игнорируете возвращаемое значение
GetArray
. При печати выpcArray
не указываетеprintf
, сколько символов выводить. Итак, как он должен знать, что печатать? - Вы перезаписываете возвращаемые значения с
tcgetattr
помощью вызоваmemset
.
Комментарии:
1. Я удалил memset в tcgetattr. Хороший показатель количества байтов для чтения. Но NumberOfBytes2Read всегда равно 0… тем не менее.
2. @jdl В этом случае вам нужно сделать что-то разумное. Что вы хотите сделать, если нет байтов для чтения? (Это ошибка номер 2.)
3. Я решил проблему … спасибо за вашу помощь
Ответ №2:
Проблема заключается в последовательном порту для обмена данными.
/dev/ttyS0
И /dev/ttyS4
— это последовательные порты после подключения USB к НУЛЬ-модемному кабелю. Но для связи мне пришлось использовать /dev/ttyUSB0
и /dev/ttyUSB1