COM-порт в Windows (программирование): различия между версиями

Содержимое удалено Содержимое добавлено
Нет описания правки
Строка 1:
Написать программу, управляющую устройством через [[COM-порт]], для [[MS-DOS]] не так сложно.
С платформой Win32 дело обстоит сложнее. Но только на первый взгляд. Конечно напрямую работать с [[регистр|регистрами]] портов нельзя, [[Windows]] это не позволяет, зато можно не обращать внимания на тонкости различных [[реализация|реализаций]] (i8055, 16450, 16550A) и не возиться с обработкой [[прерывание|прерываний]].
 
{{Wikify}}
 
== Открытие порта ==
Строка 263 ⟶ 265 :
 
== Пример настройки порта и выполнения чтения/записи данных. ==
 
----
 
{{Wikify}}
 
Приветствую.
Это может быть ценным: код для работы с COM-портом. Многострадальный, соответственно относительно простой и понятный (имхо), при этом обходит основные подводные камни. Надеюсь, может быть полезен. [[Участник:Dmitry Korolev|Dmitry Korolev]] 11:49, 16 марта 2007 (UTC)
 
*tty.h
 
#ifndef TTY_H
#define TTY_H
 
#include <windows.h>
 
#include <vector>
#include <string>
 
using namespace std;
 
struct TTY {
 
TTY();
virtual ~TTY();
 
bool IsOK() const;
void Connect(const string& port, int baudrate);
void Disconnect();
 
virtual void Write(const vector<uint8_t>& data);
virtual void Read(vector<uint8_t>& data);
HANDLE m_Handle;
 
};
 
struct TTYException {
};
 
#endif
 
*tty.cpp
 
#include "tty.h"
 
#include <windows.h>
 
using namespace std;
 
static int TIMEOUT = 1000;
 
TTY::TTY() {
m_Handle = 0;
}
 
TTY::~TTY() {
Disconnect();
}
 
void TTY::Connect(const string& port, int baudrate) {
 
Disconnect();
m_Handle =
CreateFile(
port.c_str(),
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(m_Handle == (HANDLE)-1) {
m_Handle = 0;
throw TTYException();
}
SetCommMask(m_Handle, EV_RXCHAR);
SetupComm(m_Handle, 1500, 1500);
 
COMMTIMEOUTS CommTimeOuts;
CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
CommTimeOuts.ReadTotalTimeoutConstant = TIMEOUT;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant = TIMEOUT;
 
if(!SetCommTimeouts(m_Handle, &CommTimeOuts)) {
m_Handle = 0;
throw TTYException();
}
DCB ComDCM;
memset(&ComDCM,0,sizeof(ComDCM));
ComDCM.DCBlength = sizeof(DCB);
GetCommState(m_Handle, &ComDCM);
ComDCM.BaudRate = DWORD(baudrate);
ComDCM.ByteSize = 8;
ComDCM.Parity = NOPARITY;
ComDCM.StopBits = ONESTOPBIT;
ComDCM.fAbortOnError = TRUE;
ComDCM.fDtrControl = DTR_CONTROL_DISABLE;
ComDCM.fRtsControl = RTS_CONTROL_DISABLE;
ComDCM.fBinary = TRUE;
ComDCM.fParity = FALSE;
ComDCM.fInX = ComDCM.fOutX = FALSE;
ComDCM.XonChar = 0;
ComDCM.XoffChar = uint8_t(0xff);
ComDCM.fErrorChar = FALSE;
ComDCM.fNull = FALSE;
ComDCM.fOutxCtsFlow = FALSE;
ComDCM.fOutxDsrFlow = FALSE;
ComDCM.XonLim = 128;
ComDCM.XoffLim = 128;
 
if(!SetCommState(m_Handle, &ComDCM)) {
CloseHandle(m_Handle);
m_Handle = 0;
throw TTYException();
}
 
}
 
void TTY::Disconnect() {
 
if(m_Handle != 0) {
CloseHandle(m_Handle);
m_Handle = 0;
}
 
}
 
void TTY::Write(const vector<uint8_t>& data) {
 
if(m_Handle == 0) {
throw TTYException();
}
 
DWORD feedback;
if(!WriteFile(m_Handle, &data[0], int(data.size()), &feedback, 0) || feedback != int(data.size())) {
CloseHandle(m_Handle);
m_Handle = 0;
throw TTYException();
}
 
// In some cases it's worth uncommenting
//FlushFileBuffers(m_Handle);
 
}
 
void TTY::Read(vector<uint8_t>& data) {
 
if(m_Handle == 0) {
throw TTYException();
}
 
DWORD begin = GetTickCount();
DWORD feedback = 0;
 
uint8_t* buf = &data[0];
DWORD len = int(data.size());
int attempts = 3;
while(len && (attempts || (GetTickCount()-begin) < DWORD(TIMEOUT/3))) {
 
if(attempts) attempts--;
 
if(!ReadFile(m_Handle, buf, len, &feedback, NULL)) {
CloseHandle(m_Handle);
m_Handle = 0;
throw TTYException();
}
 
assert(feedback <= len);
len -= feedback;
buf += feedback;
}
 
if(len) {
CloseHandle(m_Handle);
m_Handle = 0;
throw TTYException();
}
 
}