Работа с COM-портом в compact framework C#
Работа с COM-портом в C# очень проста, для реализации используется класс System.IO.Ports.SerialPort. Как всегда в начале надо проинициализировать COM-порт вызовом конструктора
System.IO.Ports.SerialPort("COM1",9600,System.IO.Ports.Parity.None,
8,System.IO.Ports.StopBits.One);
Этой функцией задаем COM1 первый ком порт, скорость обмена 9600, отсутствие паритета, 8 бит в посылке, один стоп бит, т.е. наиболее популярные значения.
Затем порт готов к использованию.
public class RsExchange
{
System.IO.Ports.SerialPort rs_port;
public void InitRs()
{
rs_port = new System.IO.Ports.SerialPort("COM1", 9600,
System.IO.Ports.Parity.None,
8,
System.IO.Ports.StopBits.One);
if (rs_port.IsOpen == true)
rs_port.Close();
rs_port.Open();
}
}
Функция запрос-ответ
// Отправка команды управления (выставление дискретных выходов)
public int SetCmd (int num)
{
byte[] data = new byte[4];
data[0] = 64; // '@'
data[1] = 90;
data[2] = (byte)num;
data[3] = crc8(data, 3);
rs_port.Write(data, 0, 4);
// Отправляем запрос, ждем 100 мс и смотрим что пришло в ответ
System.Threading.Thread.Sleep(100);
if (rs_port.BytesToRead > 0)
{
byte[] answer = new byte[(int)rs_port.BytesToRead];
// Читаем буфер для анализа ответа на команду управления
rs_port.Read(answer, 0, rs_port.BytesToRead);
return 0;
}
return -1;
// Если не пришло вообще никакого ответа,
// возвращаем отрицательное значение
}
В этой функции представлен пример отправки-приема данных из одного проекта. Сначала мы отправляем запрос на девайс, затем получаем ответ (аналогично с modbus, только проще).
byte[] data = new byte[4]; - заготовка для отправки данных на девайс
Заполняем массив данными.
data[0] = 64; // '@'
data[1] = 90;
data[2] = (byte)num;
Последний байт - crc8 от посылки, функция crc8 описана в программе. CRC8 часто используется в работе с COM-портом, она позволяет исключать неправильные посылки на линии, часто возникающие из-за помех.
data[3] = crc8(data, 3);
Теперь отправляем данные на девайс
rs_port.Write(data, 0, 4);
Ждем какое-то время пока сформируется ответ
System.Threading.Thread.Sleep(100);
И смотрим, пришел ли ответ (может не быть ответа совсем, если девайс, например, не подключен)
if (rs_port.BytesToRead > 0)
Если ответ пришел, то считываем все данные с порта в массив и возвращаем 0. Если ничего не пришло, возвращаем -1.
byte[] answer = new byte[(int)rs_port.BytesToRead];
return 0;
Вобщем-то в C# нет никаких проблем реализовать работу с COM-портом, если не требует сверхбыстродействия и моментальной реакции на приходящие по порту элементы. В своей программе я использовал 100 мс задержку до получения ответа, предполагая что ответ либо придет полностью, либо нет. В этом случае девайс должен точно отвечать за время, меньшее 100мс, иначе система не будет работать вообще. С другой стороны, если неизвестно время ответа девайса или нужно быстродействие, то можно использовать получение данных по событию "пришел новый символ" и каждый раз пополнять массив данных. Реализация этого метода немного сложнее, но незначительно. В любом случае я бы не рекомендовал использовать COM-порт (как и все производные UART-интерфейса) стационарного компьютера для синхронизации по времени чего-либо, хороших результатов это не даст, т.к. сама операционная система в большинстве случае не real-time, что не дает возможности прогнозирования времени отклика COM-порта на команду, да и сам язык C# не самый лучший выбор для быстродействующих приложений (в сравнении даже с C++ и уж тем более классическим C). Но у C# есть определенный плюс - сборка exe-файла является кроссплатформенной, т.е. это исполняемый файл я запускал и на win64, и на win32, и даже на WinCE 6.0. Проект даже не надо пересобирать, что логично. Но приятно, когда создается код для встраиваемой платформы на основе WinCE, а отлаживать возможно на стационарном x86, не переделывая потом даже exe-файл под другую архитектуру, что необходимо Qt.
Ссылка на файл с программой