Mam komunikacje po RS232 z zewnętrznym urządzeniem. Port obsługuję bezpośrednio za pomocą systemowych funkcji read() i write().
Kod: Zaznacz cały
int TLinuxCOM::Connect(char *DevName, TConnectionParameters ConnectionParameters)
{
if (Connected)
{
DisConnect();
}
this->BaudRate=BaudRate;
FileDescriptor=open(DevName, O_RDWR | O_NOCTTY); // O_NDELAY -> signal DCD is not active; O_NOCTTY -> program won't to be "controlling terminal"
if (FileDescriptor==-1)
{
Connected=0;
BaudRate=0;
return -1; // cannot open device with given DevName;
}
fcntl(FileDescriptor, F_SETFL, 0);
fcntl(FileDescriptor, F_SETFL, FNDELAY); // if input buffer is epmty, then read function returns -1;
// now we are set the port params;
memset(&ComControlStructure, 0x00, sizeof(ComControlStructure));
cfsetispeed(&ComControlStructure, ConnectionParameters.BaudRate); // transmission baud rate;
cfsetospeed(&ComControlStructure, ConnectionParameters.BaudRate); // transmission baud rate;
if (ConnectionParameters.ParityChecking==1)
{
ComControlStructure.c_cflag |= PARENB; // enable parity checking;
}
else
{
ComControlStructure.c_cflag &= ~PARENB; // disable parity checking;
}
if (ConnectionParameters.ParityODD==1)
{
ComControlStructure.c_cflag |= PARODD; // set odd parity (ustawianie nie parzystosci);
}
else
{
ComControlStructure.c_cflag &= ~PARODD; // set even parity (ustawianie parzystosci);
}
switch (ConnectionParameters.StopBits)
{
case 1: ComControlStructure.c_cflag &= ~CSTOP; // 1 stop bit;
break;
case 2: ComControlStructure.c_cflag |= CSTOP; // 2 stop bits;
break;
default: ComControlStructure.c_cflag |= CSTOP; // 2 stop bits;
}
switch (ConnectionParameters.DataBits)
{
case 5: ComControlStructure.c_cflag |= CS5; // 5 data bits;
break;
case 6: ComControlStructure.c_cflag |= CS6; // 6 data bits;
break;
case 7: ComControlStructure.c_cflag |= CS7; // 7 data bits;
break;
case 8: ComControlStructure.c_cflag |= CS8; // 8 data bits;
break;
default: ComControlStructure.c_cflag |= CS8; // 8 data bits;
}
ComControlStructure.c_cflag |= CREAD; // enable the receiver;
ComControlStructure.c_cflag |= CLOCAL; // set local mode;
ComControlStructure.c_iflag |= IGNBRK; // ignore BREAK condition on input;
ComControlStructure.c_cc[VMIN] = 1; // minimum number of characters for non-canonical read;
ComControlStructure.c_cc[VTIME] = 0; // minimum number of characters for non-canonical read;
tcsetattr(FileDescriptor, TCSANOW, &ComControlStructure); // set new port params;
ioctl(FileDescriptor, TIOCMGET, &ComStatus); // get the actual COM control settings;
if (ConnectionParameters.DTRSignal==1)
{
ComStatus |= TIOCM_DTR; // enable DTR signal;
}
else
{
ComStatus &= ~TIOCM_DTR; // disable DTR signal;
}
if (ConnectionParameters.CTSSignal==1)
{
ComStatus |= TIOCM_CTS; // enable CTS signal;
}
else
{
ComStatus &= ~TIOCM_CTS; // disable CTS signal;
}
if (ConnectionParameters.RTSSignal==1)
{
ComStatus |= TIOCM_RTS; // enable RTS signal;
}
else
{
ComStatus &= ~TIOCM_RTS; // disable RTS signal;
}
ioctl(FileDescriptor, TIOCMSET, &ComStatus); // set the new param of COM;
tcflush(FileDescriptor, TCIOFLUSH);
Connected=1;
return 0;
}
Niestety program musi również prawidłowo współpracować z urządzeniami używającymi konwersji odwróconej (stan wysoki określa logiczne zero, dane przesyłane są od najstarszego do najmłodszego bitu).
Program używa Qt i działa z Windows i Linux, o ile na win32API wszystko pracuje gładko, to pod Linuksem nie mam już za bardzo pomysłów gdzie szukać błędów. Wszystkie ustawienia specyficzne dla Linuksa to te poniżej:
Kod: Zaznacz cały
ComControlStructure.c_cflag |= CREAD; // enable the receiver;
ComControlStructure.c_cflag |= CLOCAL; // set local mode;
ComControlStructure.c_iflag |= IGNBRK; // ignore BREAK condition on input;
ComControlStructure.c_cc[VMIN] = 1; // minimum number of characters for non-canonical read;
ComControlStructure.c_cc[VTIME] = 0; // minimum number of characters for non-canonical read;
Port RS to przejściówka USB<->RS232 na pl2303.
Ma ktoś może jakiś pomysł dlaczego to nie współpracuje akurat z Linuksem?