Ciao vinper,
ti passo una classe che funzionava, però è un pò incasinata, nel senso che è scritta con delle compilazioni condizionali per funzionare sia sotto Windows che Qnx. Se tagli via tutte le parti per Qnx potrebbe servirti almeno come spunto.:
class SerialPort: public Object
{
public:
SerialPort();
~SerialPort();
void Close();
bool Open(UInt32 id, UInt32 baudRate);
bool Open(const char* name, UInt32 baudRate);
bool Read(UInt8&);
bool ReadWithTimeout(UInt8& result, UInt32 timeoutMs);
bool Write(UInt8);
bool Write(UInt8* buffer, UInt32 bufferSize);
UInt32 m_baudRate;
private:
#ifdef __POSIX__
int m_serial;
#endif
#ifdef WIN32
void* m_serial;
#endif
};
// SerialPort
SerialPort::SerialPort()
{
m_baudRate = 0;
#ifdef WIN32
m_serial = INVALID_HANDLE_VALUE;
#endif
#ifdef __POSIX__
m_serial = 0;
#endif
}
SerialPort::~SerialPort()
{
}
void SerialPort::Close()
{
#ifdef WIN32
if( m_serial == INVALID_HANDLE_VALUE)
return;
CloseHandle(m_serial);
m_serial = INVALID_HANDLE_VALUE;
#endif
#ifdef __POSIX__
close(m_serial);
m_serial = 0;
#endif
}
bool SerialPort::Open(UInt32 id, UInt32 baudRate)
{
// sotto QNX il nome è "/dev/ser1" per COM1 ecc.
// sotto Linux il nome è: "/dev/ttyS0" (per la prima COM1, ttyS1 per la COM2)
// sotto Windows il nome è "COM1" per COM1 ecc.
string name;
#ifdef __QNX__
name = string("/dev/ser") + Utility::ToString(id);
#else
#ifdef __POSIX__
name = string("/dev/ttyS") + Utility::ToString(id - 1);
#endif
#endif
#ifdef WIN32
name = string("COM") + Utility::ToString(id);
#endif
return Open(name.c_str(), baudRate);
}
bool SerialPort::Open(const char* name, UInt32 baudRate)
{
#ifdef __QNX__
m_serial = open(name, O_RDWR| O_NONBLOCK);
if (m_serial == -1)
return false;
struct termios options;
speed_t speed = baudRate;
tcgetattr( m_serial, &options);
cfsetispeed(&options, speed);
cfsetospeed(&options, speed);
tcsetattr( m_serial, TCSAFLUSH, &options);
#endif
#ifdef WIN32
m_serial = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if( m_serial == INVALID_HANDLE_VALUE)
return false;
#endif
return true;
}
bool SerialPort::Read(UInt8& result)
{
#ifdef __QNX__
int bytesRead = read (m_serial, &result, 1);
if (bytesRead != 1)
return false;
#endif
#ifdef WIN32
DWORD bytesRead = 0;
if( ! ReadFile(m_serial, &result, 1, &bytesRead, NULL) )
return false;
if (bytesRead != 1)
return false;
#endif
return true;
}
bool SerialPort::ReadWithTimeout(UInt8& result, UInt32 timeoutMs)
{
const int retry = 10;
int wait = timeoutMs / retry;
if (wait == 0)
wait = 1;
for(int i = 0; i < retry; ++i)
{
if (Read(result))
return true;
DelayMs(wait);
}
return false;
}
bool SerialPort::Write(UInt8 writeValue)
{
#ifdef __QNX__
int bytesWritten = write(m_serial, &writeValue, 1 );
if (bytesWritten != 1)
return false;
#endif
#ifdef WIN32
DWORD bytesWritten = 0;
if( ! WriteFile(m_serial, &writeValue, 1, &bytesWritten, NULL) )
return false;
#endif
return true;
}
bool SerialPort::Write(UInt8* buffer, UInt32 bufferSize)
{
#ifdef __QNX__
int bytesWritten = write(m_serial, buffer, bufferSize );
if ((UInt32)bytesWritten != bufferSize)
return false;
#endif
#ifdef WIN32
DWORD bytesWritten = 0;
if( ! WriteFile(m_serial, buffer, bufferSize, &bytesWritten, NULL) )
return false;
return bytesWritten == bufferSize;
#endif
return true;
}
Alla fine vedrai che la parte Windows è piuttosto semplice.
Se cerci un poco in rete troverai degli esempi migliori.