Все технические форумы на одном сайте Удобный поиск информации с популярных форумов в одном месте
Вопрос: Найти к какому COM порту подключено устройство

Добрый день. Подскажите пожалуйста, как можно получить список активных COM портов в винде(тот что я вижу в диспетчере устройств). Задачу у меня следующая: на ардуино собрал простенькую схему и написал простенькую прогу которая считывает с COM порта символы. COM порт задан фиксировано, а я хочу сделать так, чтобы порт выбирался автоматом. Подскажите в какую сторону рыть?
Ответ:
Вопрос: Изменение скорости работы COM порта

Приветствую всех. Занялся я, значит, созданием программы для работы с физическим устройством. Сие устройство "общается" по ГОСТ IEC 61107-2011 в режиме С. Если кто-то не знает процедуру обмена информацией по этому ГОСТ, то вкратце расскажу о ней применительно к моему устройству.

В моем устройстве обмен происходит через виртуальный COM порт. Все настройки порта, кроме скорости, остаются одни и те же на всем протяжении процедуры обмена. Вначале программа отправляет устройству запрос определенного формата на скорости 300 бод (первый блок сверху на рисунке) и ждет ответ от устройства на той же скорости (второй блок на рисунке). Далее отправляется любой из 2-х запросов (чтение или программирование), определяющих дальнейший режим работы, так же на скорости 300 бод (запрос а) или б) на рисунке). Кроме этого, в этом же запросе определяется выбор дальнейшей скорости обмена (переключение скорости работы интерфейса устройства). Ответ на этот запрос устройство присылает уже на выбранной скорости (часть рисунка Z бод).

Проблема следующая. Если я не меняю скорость интерфейса устройства, то все работает хорошо. Если же меняю, и одновременно меняю скорость работы COM порта, то ответ от устройства не приходит. Вернее он точно приходит, но я не могу получить его в COM порту. Может я не правильно изменяю скорость COM порта?
C++
1
2
3
4
5
6
7
8
9
10
/* Здесь происходит отправка данных в COM порт */
 
/* НАСТРОЙКА СКОРОСТИ ПРИЕМА */
 if(RxSpeed != dcb.BaudRate)
  {
   dcb.BaudRate = RxSpeed;
   SetCommState(COMPort, &dcb));
  }
 
/* Здесь происходит чтение данных из COM порта */
Ответ: Может быть для изменения скорости порта без его закрытия необходимо чтобы он был открыт в асинхронном режиме? Сейчас он открывается в синхронном.

Добавлено через 19 часов 39 минут
Для моего устройства есть заводская программа. Я запустил монитор COM порта и выполнил обмен с помощью заводской программы. Как я и описывал, второй запрос идет на скорости 300, а ответ на этот запрос уже на скорости 9600. То есть устройство дает ответ (я уж начал в этом сомневаться).
Далее по монитору COM порта я сравнил процесс обмена и настройки COM порта при работе заводской программы и моей поделки. Логи оказались идентичными!

Вот лог COM порта при работе заводской программы:
Кликните здесь для просмотра всего текста
<2016.10.16 10:39:50.431 SYS>
COM открыт
<2016.10.16 10:39:50.431 SYS>
Unable to add string #8

<2016.10.16 10:39:50.431 SYS>
Скорость передачи 300
<2016.10.16 10:39:50.447 SYS>
RTS включен
<2016.10.16 10:39:50.447 SYS>
DTR включен
<2016.10.16 10:39:50.447 SYS>
Биты данных=7, Стоповые биты=1, Четность=Even
<2016.10.16 10:39:50.447 SYS>
Служ. символы: Eof=0x00, Error=0x00, Break=0x00, Event=0x00, Xon=0x11, Xoff=0x13
<2016.10.16 10:39:50.447 SYS>
Контроль передачи: ControlHandShake=(DTR_CONTROL), Замена=(TRANSMIT_TOGGLE, RTS_CONTROL), Лимит Xon=2048, Лимит Xoff=512
<2016.10.16 10:39:50.447 SYS>
RTS включен
<2016.10.16 10:39:56.894 SYS>
Очистка порта: RXCLEAR
<2016.10.16 10:39:56.894 TX>
2F 3F 21 0D 0A
<2016.10.16 10:39:57.316 RX>
2F 45 4B 54 35 43 45 33 30 31 76 37 0D 0A
<2016.10.16 10:39:57.785 SYS>
Очистка порта: RXCLEAR
<2016.10.16 10:39:57.785 TX>
06 30 35 31 0D 0A
<2016.10.16 10:39:58.019 SYS>
Очистка порта: RXCLEAR

<2016.10.16 10:39:58.019 SYS>
Скорость передачи 9600
<2016.10.16 10:39:58.019 SYS>
RTS включен
<2016.10.16 10:39:58.019 SYS>
DTR включен
<2016.10.16 10:39:58.019 SYS>
Биты данных=7, Стоповые биты=1, Четность=Even
<2016.10.16 10:39:58.019 SYS>
Служ. символы: Eof=0x00, Error=0x00, Break=0x00, Event=0x00, Xon=0x11, Xoff=0x13
<2016.10.16 10:39:58.019 SYS>
Контроль передачи: ControlHandShake=(DTR_CONTROL), Замена=(TRANSMIT_TOGGLE, RTS_CONTROL), Лимит Xon=2048, Лимит Xoff=512
<2016.10.16 10:39:58.019 SYS>
DTR включен
<2016.10.16 10:39:58.457 RX>
01 50 30 02 28 54 45 53 54 49 4E 47 5F 43 4F 55 4E 54 45 52 29 03 73
<2016.10.16 10:39:58.519 SYS>
Очистка порта: RXCLEAR
<2016.10.16 10:39:58.519 TX>
01 52 31 02 53 4E 55 4D 42 28 29 03 5E
<2016.10.16 10:39:58.738 RX>
02 53 4E 55 4D 42 28 30 30 38 38 34 30 30 33 38 30 30 30 30 30 32 29 0D 0A 03 61
<2016.10.16 10:39:58.835 SYS>
Очистка порта: RXCLEAR
<2016.10.16 10:39:58.835 TX>
01 42 30 03 75
<2016.10.16 10:39:59.053 SYS>
Очистка порта: RXCLEAR
COM закрыт


Теперь для меня вообще загадка почему я после переключения скорости не получаю ответ от устройства
Вопрос: Возможно ли получить данные с COM порта без физического устройства к нему подключенного?

Добрый день!
Возможно ли получить данные с COM порта без физического устройства к нему подключенного ?
Если да то как.
Пробовал, написал две программы: одна пишет данные в порт, другая с них читает. Данные вроде пишутся но при прочтении тишина.
После записи данных в порт, первая программа закрывается, другая программа запускается и читает. Разве данные не остаются в буфере порта?
Ответ: И ещё можно специальными программами создать виртуальный кабель RS-232 и к нему подключить две разные программы, с разных сторон.
Вопрос: Нет доступа к COM порту

Есть вот такой код программы:
vb.net
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
If SerialPort1.IsOpen Then
            SerialPort1.RtsEnable = False
            SerialPort1.DtrEnable = False
            SerialPort1.Close()
 
            Application.DoEvents()
        End If
 
 
        SerialPort1.PortName = My.Settings.COM
        SerialPort1.BaudRate = 9600
        SerialPort1.DataBits = 8
        SerialPort1.Parity = 0
        SerialPort1.StopBits = IO.Ports.StopBits.One
        SerialPort1.Encoding = ASCIIEncoding.Default
        SerialPort1.Open()
В программе несколько форм. В других формах всё работает на ура, но вот именно в одной форме пишет, что доступ к КОМ порту закрыт. Вообще не понимаю почему. В других формах программы-то от свободен. Подскажите куда рыть. Спасибо.
Ответ:

Не по теме:

Сообщение от Rius
Потому что могут пострадать люди.
Та рождается нечеловеческий ИИ. Он поработит людей!!! И заставит САМИХ работать на станках!

Вопрос: Не работает поток чтения из COM порта

Программа открывает COM порт и шлет в него 8-ми битное значение. Поток передачи работает: на TX повесил светодиод - вспыхивает, а вот поток передачи молчит. При его выполнении должен появляться MessageBox, но его нет. Т.к. не знаю в чем проблема привожу код и main и com
main:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
#include <tchar.h>      //для поддержки кодировки Unicode
#include "com.h"
#define ID_BUTTON_1 3000     //идентификатор кнопки
#define ID_BUTTON_2 3001     //идентификатор кнопки
#define ID_BUTTON_3 3002     //идентификатор кнопки
#define ID_BUTTON_4 3003     //идентификатор кнопки
#define ID_COMBOCOM 1003     //идентификатор меню-списка 
 
 
HWND hBtn1;         // хендл  кнопки 1
HWND hBtn2;         // хендл  кнопки 2
HWND hBtn3;         // хендл  кнопки 3
HWND hBtn4;         // хендл  кнопки 4
HWND hComboPort;    // хендл  меню  ComboBox портов
HINSTANCE hInstance;
HBRUSH hbrush;      //создаём объект-кисть
PAINTSTRUCT ps;     //структура рисования
HDC hdc;            //создаём контекст устройства
HDC memdc;          //создаём контекст устройства 
char ComNameBuf[5]; //имя порта (например, "COM1", "COM2" и т.д.)
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
 
 
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
 
    HWND hMainWnd;  // Дескриптор будущего главного окна
    char szClassName[] = "MyClass";
    MSG msg;        // Структура для хранения сообщения
    WNDCLASSEX wc;  // Класс окна
 
    // Заполняем структуру класса окна
    wc.cbSize = sizeof(wc);
    wc.style = CS_HREDRAW | CS_VREDRAW;// Стили класса, в данном случае - окна этого класса будут перерисовываться при изменении размеров по вертикали и горизонтали
    wc.lpfnWndProc = WndProc; // Указатель на функцию, обрабатывающую оконные сообщения
    wc.cbClsExtra = 0;        // Нет дополнительных данных класса 
    wc.cbWndExtra = 0;        // Нет дополнительных данных окна
    wc.hInstance = hInstance; // дескриптор приложения, который регистрирует класс
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); // Стандартная иконка
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);   // Стандартный курсор
    wc.hbrBackground = (HBRUSH)GetStockObject(DKGRAY_BRUSH);// Цвет фона рабочей области окна
    wc.lpszMenuName = NULL;   // Нет меню
    wc.lpszClassName = "MyClass"; // Имя класса окна
    wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
 
    // Регистрируем класс окна
    if (!RegisterClassEx(&wc)) {// Регистрация класса, в случае неудачи фукция вернет 0
        MessageBox(NULL, "Cannot register class", "Error", MB_OK);
        return 0;
    }
 
    // Создаем основное окно приложения
    hMainWnd = CreateWindow(szClassName, "Fluttershy is Present", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 330, 300, NULL, NULL, hInstance, NULL);
    if (!hMainWnd)
    {
        MessageBox(NULL, "Cannot create main window", "Error", MB_OK);
        return 0;
    }
    
    // Показываем окно
    ShowWindow(hMainWnd, nCmdShow);
    UpdateWindow(hMainWnd);
 
    // Выполняем цикл обработки сообщений до закрытия приложения
    while(GetMessage(&msg, NULL, 0, 0)) 
    {
        TranslateMessage(&msg);// Функция трансляции кодов нажатой клавиши
        DispatchMessage(&msg); // Посылает сообщение функции WndProc()
    }
 
    return msg.wParam;
}
 
LRESULT CALLBACK WndProc(HWND hMainWnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{
  int SelectedCom=1;
  int maxX=0, maxY=0; //максимальные координаты по х и по у
  HBITMAP hbit;       //объект изображение окна
  
    switch (msg) 
    {
        case WM_CREATE:
        {  
          hdc=GetDC(hMainWnd);                //получаем контекст изображения
          maxX=GetSystemMetrics(SM_CXSCREEN); //узнаём максимальные координаты по х  
          maxY=GetSystemMetrics(SM_CYSCREEN); //узнаём максимальные координаты по у
          //Создаем Combobox ;
          hComboPort=CreateWindow("Combobox",NULL,WS_CHILD|WS_VISIBLE|WS_VSCROLL|CBS_DROPDOWNLIST,170, 40, 120, 40,hMainWnd, (HMENU)ID_COMBOCOM,hInstance,NULL);
          //Создаем кнопки ;
          hBtn1 = CreateWindow("BUTTON", "Open COM port", BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | WS_TABSTOP, 40, 40, 120, 40, hMainWnd, (HMENU)ID_BUTTON_1, hInstance, NULL);
          hBtn2 = CreateWindow("BUTTON", "Close COM port", BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | WS_TABSTOP, 40, 100, 120, 40, hMainWnd, (HMENU)ID_BUTTON_2, hInstance, NULL);
          hBtn3 = CreateWindow("BUTTON", "Send", BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | WS_TABSTOP, 40, 160, 120, 40, hMainWnd, (HMENU)ID_BUTTON_3, hInstance, NULL);
          hBtn4 = CreateWindow("BUTTON", "Choose", BS_PUSHBUTTON | WS_VISIBLE | WS_CHILD | WS_TABSTOP, 170, 100, 120, 40, hMainWnd, (HMENU)ID_BUTTON_4, hInstance, NULL);
          //Заносим значения портов:
          SendMessage(hComboPort, CB_ADDSTRING, 1, (LPARAM)"COM1");
          SendMessage(hComboPort, CB_ADDSTRING, 1, (LPARAM)"COM2");
          SendMessage(hComboPort, CB_ADDSTRING, 1, (LPARAM)"COM3");
          SendMessage(hComboPort, CB_ADDSTRING, 1, (LPARAM)"COM4");
          SendMessage(hComboPort, CB_ADDSTRING, 1, (LPARAM)"COM5");
          SendMessage(hComboPort, CB_ADDSTRING, 1, (LPARAM)"COM6");
          SendMessage(hComboPort, CB_ADDSTRING, 1, (LPARAM)"COM7");
          SendMessage(hComboPort, CB_ADDSTRING, 1, (LPARAM)"COM8");
          SendMessage(hComboPort, CB_ADDSTRING, 1, (LPARAM)"COM9");
          SendMessage(hComboPort, CB_SETCURSEL, 0, 0L);  //Делаем текущим первую строчку
          memdc=CreateCompatibleDC(hdc);                 //создём в памяти контекст, совместимый с нашим
          hbit=CreateCompatibleBitmap(hdc, maxX, maxY);  //создаём картинку нашего окна
          SelectObject(memdc, hbit);                     //делаем её активной в области контекста памяти
          hbrush=CreateSolidBrush(RGB(255,255,255));     //создаём кисть
          SelectObject(memdc, hbrush);                   //делаем её активной
          PatBlt(memdc, 0,0,maxX, maxY, PATCOPY);        //копируем картинку из памяти в наше окно, растянув её на всё окно
          ReleaseDC(hMainWnd, hdc);                      //освобождаем контекст
          ComNameBuf[0]=0;  //изначально имя COM порта не выбрано
          
          reader =(HANDLE)_beginthreadex(NULL, 0, ReadThread, pCharRead, 0, NULL); //создаем поток чтения в запущеном состоянии, дескриптор преобразовывается явно в (HANDLE)
          writer =(HANDLE)_beginthreadex(NULL, 0, WriteThread, pCharWrite, CREATE_SUSPENDED, NULL);//создаем поток записи в остановленном состоянии, дескриптор преобразовывается явно в (HANDLE)
          return 0;
        }
        
         case WM_PAINT:
        {
          hdc=BeginPaint(hMainWnd, &ps); 
          //Заголовки над элементами управления
          SetTextColor(hdc, RGB(255,255,67));
          SetBkMode(hdc, TRANSPARENT);
          TextOut(hdc, 170, 70,"Выберите COM порт: ", 17); //выводим текст в окно
          //Перерисовка окна
          memdc=CreateCompatibleDC(hdc);
          BitBlt(hdc, 0, 0, maxX, maxY, memdc, 0, 0, SRCCOPY); //копирует в окно сохранённую картинку 
          EndPaint(hMainWnd, &ps);
          return 0;
        }
        
        case WM_COMMAND:
            switch(LOWORD(wParam))
            {
                case ID_BUTTON_1: //если нажата кнопка открытия порта
                    COMOpen(ComNameBuf);
                    return 0;
                break;
                
                
                case ID_BUTTON_2: //если нажата кнопка закрытия порта
                    COMClose(); 
                    return 0;                   
                break;
 
                
                case ID_BUTTON_3: //если нажата кнопка передачи
                {
                    CharWrite = (char)0b10101010;
                    
                    if(PrtOpen) //если порт открыт
                    { 
                      if(!reader) //если поток чтения не запущен
                      {
                        ResumeThread(reader); //пробуждаем поток чтения
                      }
                      if(!writer) //если поток записи не запущен
                      {
                        ResumeThread(writer); //пробуждаем поток записи
                      }
                      WriteThread(pCharWrite); //передаем в функцию потока записи указатель на передаваюмую переменную(char)
                    }
                    else
                    {
                      MessageBox(NULL, "Порт не открыт", "Error", MB_SYSTEMMODAL);
                    }
                    return 0;
                }
                break;
                
                case ID_BUTTON_4: //если нажата кнопка подтверждения выбора порта
                {
                  SelectedCom=SendMessage(hComboPort, CB_GETCURSEL, 0, 0L);//Получить из списка текст выделенной строки
                  //Сообщение CB_GETLBTEXT (Get ListBox Text) записывает в строку ComNameBuf текст строки с номером SelectedCom. Для этого она даже не должна быть выделена
                  SendMessage(hComboPort, CB_GETLBTEXT, (WPARAM)SelectedCom, (LPARAM)ComNameBuf);
                }
                break;
                
            }  
            break;
            
        case WM_CLOSE:
            COMClose();
            DestroyWindow(hMainWnd);
            return 0;
 
        case WM_DESTROY:
            COMClose();
            PostQuitMessage(0);
            return 0;   
            
        case WM_KEYDOWN:
            switch(wParam) 
            {
                case VK_ESCAPE:                 
                    SendMessage(hMainWnd, WM_CLOSE, 0, 0);
                    break;
            }
            break;
        
        case WM_SIZE: //при изменении размеров окна, взывается 
           InvalidateRect(hMainWnd, NULL, 1); //сообщение WM_PAINT
        break;
        
        default:return DefWindowProc(hMainWnd, msg, wParam, lParam);
    }
    return 0;
}
Ответ: com.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
#include <windows.h>
#include <stdint.h>     //uint8_t - 8 битный int
#include <process.h>    //для функций _beginthreadex
#include <string>       //для работы со строками
#include <io.h>         //для работы с файлами
#include <fcntl.h>      //для работы с файлами
#include <sys\stat.h>   //для работы с файлами
#include <thread>       //для работы с потоками
//using namespace std;
#define BUFSIZE 255 //размер приемного и передающего буферов
 
HANDLE hSerial;   //дескриптор com порта 
HANDLE reader;    //дескриптор потока чтения
HANDLE writer;    //дескриптор потока записи
int file;         //дескриптор для работы с файлом с помощью библиотеки <io.h>
bool fl=0;        //флаг, указывающий на успешность операций записи (1 - успешно, 0 - не успешно)
bool PrtOpen=0;   //флаг, указывающий на успешность открытия порта (1 - успешно, 0 - не успешно)
unsigned long counter = 0;  //счётчик принятых байтов, обнуляется при каждом открытии порта
char CharRead, CharWrite;   //приёмная и передающая переменные
char *pCharRead = &CharRead, *pCharWrite = &CharWrite;  //указатели на приёмную и передающую переменные
//эти структуры необходимо объявить глобально, иначе программа не будет работать правильно
OVERLAPPED overlappedread;   //будем использовать для операций чтения
OVERLAPPED overlappedwrite;  //будем использовать для операций записи             
unsigned __stdcall ReadThread(void* param);    //функция потока чтения в стиле C++
unsigned __stdcall WriteThread(void* param);   //функция потока записи в стиле C++
DWORD ResumeThread(HANDLE hThread); //функция запуска потока
DWORD SuspendThread(HANDLE hThread);//функция останова потока
void COMOpen(char ComNameBuf[]);    //открыть порт
void COMClose(void);                //закрыть порт
void ReadPrinting(void);
 
LPCTSTR WindowText = "Выберите COM порт: ";
 
//---------------------------------------------------------------------------
 
//функция открытия и инициализации порта
void COMOpen(char ComNameBuf[])
{
 std::string portname;       //имя порта (например, "COM1", "COM2" и т.д.)
 DCB dcb;                //структура для общей инициализации порта DCB
 COMMTIMEOUTS timeouts;  //структура для установки таймаутов
 if (ComNameBuf[0]==0)
 {
    MessageBox(NULL, "Выберите порт", "Error", MB_SYSTEMMODAL);
 }
 else
 {
    portname = ComNameBuf;  //получить имя выбранного порта
 }
 //открыть порт, для асинхронных операций обязательно нужно указать флаг FILE_FLAG_OVERLAPPED
 hSerial = CreateFile(portname.c_str(),GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
 //здесь:
 // - portname.c_str() - имя порта в качестве имени файла, c_str() преобразует строку типа String в строку в виде массива типа char, иначе функция не примет
 // - GENERIC_READ | GENERIC_WRITE - доступ к порту на чтение/записть
 // - 0 - порт не может быть общедоступным (shared)
 // - NULL - дескриптор порта не наследуется, используется дескриптор безопасности по умолчанию
 // - OPEN_EXISTING - порт должен открываться как уже существующий файл
 // - FILE_FLAG_OVERLAPPED - этот флаг указывает на использование асинхронных операций
 // - NULL - указатель на файл шаблона не используется при работе с портами
 
 if(hSerial == INVALID_HANDLE_VALUE)            //если ошибка открытия порта
  {
   MessageBox(NULL, "Не удалось открыть порт", "Error", MB_SYSTEMMODAL);       //вывести сообщение в строке состояния
   return;
  }
 
 //инициализация порта
 
 dcb.DCBlength = sizeof(DCB);   //в первое поле структуры DCB необходимо занести её длину, она будет использоваться функциями настройки порта для контроля корректности структуры
 
 //считать структуру DCB из порта
 if(!GetCommState(hSerial, &dcb))   //если не удалось - закрыть порт и вывести сообщение об ошибке в строке состояния
  {
   COMClose();
   MessageBox(NULL, "Не удалось считать DCB", "Error", MB_SYSTEMMODAL);
   return;
  }
 
 //инициализация структуры DCB
 dcb.BaudRate = 115200;       //задаём скорость передачи 115200 бод
 dcb.fBinary = TRUE;                                    //включаем двоичный режим обмена
 dcb.fOutxCtsFlow = FALSE;                              //выключаем режим слежения за сигналом CTS
 dcb.fOutxDsrFlow = FALSE;                              //выключаем режим слежения за сигналом DSR
 dcb.fDtrControl = DTR_CONTROL_DISABLE;                 //отключаем использование линии DTR
 dcb.fDsrSensitivity = FALSE;                           //отключаем восприимчивость драйвера к состоянию линии DSR
 dcb.fNull = FALSE;                                     //разрешить приём нулевых байтов
 dcb.fRtsControl = RTS_CONTROL_DISABLE;                 //отключаем использование линии RTS
 dcb.fAbortOnError = FALSE;                             //отключаем остановку всех операций чтения/записи при ошибке
 dcb.ByteSize = 8;                                      //задаём 8 бит в байте
 dcb.Parity = 0;                                        //отключаем проверку чётности
 dcb.StopBits = 0;                                      //задаём один стоп-бит
 
 //загрузить структуру DCB в порт
 if(!SetCommState(hSerial, &dcb))   //если не удалось - закрыть порт и вывести сообщение об ошибке в строке состояния
  {
   COMClose();
   MessageBox(NULL, "Не удалось установить DCB", "Error", MB_SYSTEMMODAL);
   return;
  }
 
 //установить таймауты
 timeouts.ReadIntervalTimeout = 0;      //таймаут между двумя символами
 timeouts.ReadTotalTimeoutMultiplier = 0;   //общий таймаут операции чтения
 timeouts.ReadTotalTimeoutConstant = 0;         //константа для общего таймаута операции чтения
 timeouts.WriteTotalTimeoutMultiplier = 0;      //общий таймаут операции записи
 timeouts.WriteTotalTimeoutConstant = 0;        //константа для общего таймаута операции записи
 
 //записать структуру таймаутов в порт
 if(!SetCommTimeouts(hSerial, &timeouts))   //если не удалось - закрыть порт и вывести сообщение об ошибке в строке состояния
  {
   COMClose();
   MessageBox(NULL, "Не удалось установить тайм-ауты", "Error", MB_SYSTEMMODAL);
   return;
  }
 
 //установить размеры очередей приёма и передачи
 SetupComm(hSerial,2000,2000);
 PrtOpen=1;
 //создать или открыть существующий файл для записи принимаемых данных
 file = open("test.txt", O_CREAT | O_APPEND | O_BINARY | O_WRONLY, S_IREAD | S_IWRITE);
 
 if(file==-1)       //если произошла ошибка открытия файла
 {
   MessageBox(NULL, "Ошибка открытия файла", "Error", MB_SYSTEMMODAL);  //вывести сообщение об этом в командной строке
 }
 
 MessageBox(NULL, "Порт открыт", "Notice", MB_SYSTEMMODAL); 
 PurgeComm(hSerial, PURGE_RXCLEAR); //очистить принимающий буфер порта
 PrtOpen=1;             //выставляем флаг в "порт открыт" 
 reader =(HANDLE)_beginthreadex(NULL, 0, ReadThread, pCharRead, CREATE_SUSPENDED, NULL); //создаем поток чтения в остановленном состоянии, дескриптор преобразовывается явно в (HANDLE)
 writer =(HANDLE)_beginthreadex(NULL, 0, WriteThread, pCharWrite, CREATE_SUSPENDED, NULL);//создаем поток записи в остановленном состоянии, дескриптор преобразовывается явно в (HANDLE)
 ResumeThread(reader); //пробуждаем поток чтения
}    
 
//---------------------------------------------------------------------------
 
//функция закрытия порта
void COMClose()
{
//Примечание: так как при прерывании потоков, созданных с помощью функций WinAPI, функцией TerminateThread
//        поток может быть прерван жёстко, в любом месте своего выполнения, то освобождать дескриптор
//        сигнального объекта-события, находящегося в структуре типа OVERLAPPED, связанной с потоком,
//        следует не внутри кода потока, а отдельно, после вызова функции TerminateThread.
//        После чего нужно освободить и сам дескриптор потока.
 
 if(writer)     //если поток записи работает, завершить его; проверка if(writer) обязательна, иначе возникают ошибки
  {TerminateThread(writer,0);
   CloseHandle(overlappedwrite.hEvent); //нужно закрыть объект-событие
   CloseHandle(writer);
  }
 if(reader)        //если поток чтения работает, завершить его; проверка if(reader) обязательна, иначе возникают ошибки
  {TerminateThread(reader,0);
   CloseHandle(overlappedread.hEvent);  //нужно закрыть объект-событие
   CloseHandle(reader);
  }
 
 CloseHandle(hSerial);  //закрыть порт
 hSerial=0;             //обнулить переменную для дескриптора порта
 close(file);           //закрыть файл, в который велась запись принимаемых данных
 file=0;                //обнулить переменную для дескриптора файла
 PrtOpen=0;             //выставляем флаг в "порт закрыт" 
 MessageBox(NULL, "Порт закрыт", "Notice", MB_SYSTEMMODAL);
}
 
//---------------------------------------------------------------------------
 
//главная функция потока, реализует приём байтов из COM-порта
unsigned __stdcall ReadThread(void* param)
{
 COMSTAT comstat;                                               //структура текущего состояния порта, в данной программе используется для определения количества принятых в порт байтов
 DWORD btr, temp, mask, signal;                                 //переменная temp используется в качестве заглушки
 overlappedread.hEvent = CreateEvent(NULL, true, true, NULL);   //создать сигнальный объект-событие для асинхронных операций
 SetCommMask(hSerial, EV_RXCHAR);                               //установить маску на срабатывание по событию приёма байта в порт
 while(1)                                                       //пока поток не будет прерван, выполняем цикл
  {
   WaitCommEvent(hSerial, &mask, &overlappedread);                  //ожидать события приёма байта (это и есть перекрываемая операция)
   signal = WaitForSingleObject(overlappedread.hEvent, INFINITE);   //приостановить поток до прихода байта
   if(signal == WAIT_OBJECT_0)                                      //если событие прихода байта произошло
    {
     if(GetOverlappedResult(hSerial, &overlappedread, &temp, true)) //проверяем, успешно ли завершилась перекрываемая операция WaitCommEvent
      if((mask & EV_RXCHAR)!=0)                                     //если произошло именно событие прихода байта
       {
        ClearCommError(hSerial, &temp, &comstat);           //нужно заполнить структуру COMSTAT
        btr = comstat.cbInQue;                              //и получить из неё количество принятых байтов
        if(btr)                                             //если действительно есть байты для чтения
        {
         ReadFile(hSerial, (TCHAR*)param, btr, &temp, &overlappedread);  //прочитать байты из порта в буфер программы
         counter+=btr;                                                   //увеличиваем счётчик байтов
         ReadPrinting();                                                 //вызываем функцию для вывода данных на экран и в файл
        }
       }
    }
  }
}
 
//---------------------------------------------------------------------------
 
//главная функция потока, выполняет передачу байтов из буфера в COM-порт 
unsigned __stdcall WriteThread(void* param)//param это и есть BufferWrite или CharWrite
{
 if(PrtOpen)    //если COM порт открыт
 {
   DWORD temp, signal;  //temp - переменная-заглушка
   bool CykleEnable = 1;
   overlappedwrite.hEvent = CreateEvent(NULL, true, true, NULL);      //создать событие
   while(CykleEnable) //если CykleEnable заменить на PrtOpen, то передача будет идти непрерывно
   {
     WriteFile(hSerial, (TCHAR*)param, strlen((TCHAR*)param), &temp, &overlappedwrite);  //записать байты в порт (перекрываемая операция!)
     signal = WaitForSingleObject(overlappedwrite.hEvent, INFINITE);      //приостановить поток, пока не завершится перекрываемая операция WriteFile
 
     if((signal == WAIT_OBJECT_0) && (GetOverlappedResult(hSerial, &overlappedwrite, &temp, true))) //если операция завершилась успешно
     {
        //MessageBox(NULL, "Передача прошла успешно", "Notice", MB_SYSTEMMODAL);    //вывести сообщение об этом в строке состояния
        CykleEnable = 0; //завершаем цикл
     }
     else 
     {
       MessageBox(NULL, "Ошибка передачи", "Error", MB_SYSTEMMODAL);//иначе вывести в строке состояния сообщение об ошибке
     }   
     SuspendThread(writer);
   }
 }
 else
 {
   MessageBox(NULL, "Сначала откройте COM порт", "Notice", MB_SYSTEMMODAL);   //вывести сообщение об этом в строке состояния
 }
  
}
 
//---------------------------------------------------------------------------
 
//выводим принятые байты на экран и в файл (если включено)
void ReadPrinting()
{
 write(file, pCharRead, strlen(pCharRead));   //записать в файл данные из приёмного буфера
 memset(pCharRead, 0, sizeof(*pCharRead));          //очистить буфер (чтобы данные не накладывались друг на друга)
}
Правда проявилась еще одра проблема - передача двух байтов вместо одного. Обсуждение этой проблемы здесь
Вопрос: Как получить номер COM-порта, на котором "сидит" подключенное устройство

Всем доброго времени суток, уважаемые коллеги!
Заранее прошу прощения у модераторов, если моя тема не совсем соответствует данному разделу, просто я так и не определился к какому разделу её корректнее будет отнести. Выбрал этот, т.к. мой проект всё-таки на C++/CLI Windows Forms.
А теперь по сути. Вот фрагмент моего кода:
C++
1
2
3
4
5
6
7
8
9
10
11
#include <windows.h> 
#include <setupapi.h>
#include <Dbt.h>
#include <string.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
 
#pragma comment(lib,"setupapi.lib")
#pragma comment(lib,"advapi32.lib")
#pragma comment(lib,"user32.lib")
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/*void TreeUpdate(): функция идентифицирует (обновляет), подключенные USB и HID устройства и выводит их в TreeView (DevTree)*/
private: System::Void TreeUpdate() {
            GUID GUID_USB_DEVICE = { 0x36FC9E60, 0xC465, 0x11CF, 0x80, 0x56, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 };
            GUID GUID_HID_DEVICE = { 0x745a17a0, 0x74d3, 0x11d0, 0xb6, 0xfe, 0x00, 0xa0, 0xc9, 0x0f, 0x57, 0xda };
            HDEVINFO PnPHandle_USB = NULL;
            HDEVINFO PnPHandle_HID = NULL;
            SP_DEVINFO_DATA DeviceInfoData;
            SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
            PBYTE  buffer;
            DWORD  buffersize = 0;
 
            DevTree->Nodes[0]->Nodes->Clear();
            DevTree->Nodes[1]->Nodes->Clear();
            cbDevList->Items->Clear();
 
            PnPHandle_USB = SetupDiGetClassDevs
                (&GUID_USB_DEVICE, // GUID
                0,
                0,
                DIGCF_PRESENT // список (USB) устройств, которые в настоящее время присутствуют в системе
                );
            PnPHandle_HID = SetupDiGetClassDevs
                (&GUID_HID_DEVICE, // GUID
                0,
                0,
                DIGCF_PRESENT // список (HID) устройств, которые в настоящее время присутствуют в системе
                );
 
            if ((PnPHandle_USB == INVALID_HANDLE_VALUE) && (PnPHandle_HID == INVALID_HANDLE_VALUE))
            {
                MessageBox::Show("Список устройств НЕ получен!", "Warning!");
                return;
            }
 
            DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
            DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
 
            int ch = 0;
            int k = 0;
            // берем каждое USB устройство из списка
            for (ch = 0; SetupDiEnumDeviceInfo(PnPHandle_USB, k, &DeviceInfoData); k++)
            {
                buffer = 0;
                buffersize = 0;
                // и читаем его свойства в буфер
                while (!SetupDiGetDeviceRegistryProperty(
                    PnPHandle_USB,
                    &DeviceInfoData,
                    SPDRP_DEVICEDESC,
                    NULL,
                    buffer,
                    buffersize,
                    &buffersize))
                {
                    if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
                    {
                        if (buffer) LocalFree(buffer);
                        buffer = (PBYTE)LocalAlloc(LPTR, buffersize * 2);
                    }
                    else break;
                }
                ch++;
                // Вывод USB идентифицированных устройств в DevTree
                // Заполняем дочерние элементы первого узла дерева Node[0]
                DevTree->Nodes[0]->Nodes->Add(gcnew String(reinterpret_cast<wchar_t*>(buffer)));
                cbDevList->Items->Add(gcnew String(reinterpret_cast<wchar_t*>(buffer)));
            }
 
            ch = 0; k = 0;
            // берем каждое HID устройство из списка
            for (ch = 0; SetupDiEnumDeviceInfo(PnPHandle_HID, k, &DeviceInfoData); k++)
            {
                buffer = 0;
                buffersize = 0;
                // и читаем его свойства в буфер
                while (!SetupDiGetDeviceRegistryProperty(
                    PnPHandle_HID,
                    &DeviceInfoData,
                    SPDRP_DEVICEDESC,
                    NULL,
                    buffer,
                    buffersize,
                    &buffersize))
                {
                    if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
                    {
                        if (buffer) LocalFree(buffer);
                        buffer = (PBYTE)LocalAlloc(LPTR, buffersize * 2);
                    }
                    else break;
                }
                ch++;
                // Вывод HID идентифицированных устройств в DevTree
                // Заполняем дочерние элементы первого узла дерева Node[0]
                DevTree->Nodes[1]->Nodes->Add(gcnew String(reinterpret_cast<wchar_t*>(buffer)));
                cbDevList->Items->Add(gcnew String(reinterpret_cast<wchar_t*>(buffer)));
            }
 
            SetupDiDestroyDeviceInfoList(PnPHandle_USB);
            SetupDiDestroyDeviceInfoList(PnPHandle_HID);
}
Он рабочий(Неожиданное начало, не правда ли?)) )! Функция заполняет в дерево TreeView список, подключенных USB устройств. Хочу сделать, что бы потом по щелчку, ну т.е. когда выбираю в дереве какой-то элемент, я мог получить номер COM-порта, на котором он сидит (если такой есть вообще).
Пока теряюсь в идеях и догадках как бы это лучше и адекватнее, с меньшим количеством заморочек, организовать... Кто может помочь, подсказать, поделиться идеями? Примеры, или модификации непосредственно моего кода приветствуются
Ответ: Попробуйте соеденить с перечислением COM портов:
Вопрос: Потокобезопасность vs COM-порт в Visual C++

Всем доброго времени суток.
Пишу программу, которая должна общаться по COM-порту с устройством. Добавил в программу элемент serialPort, открыл - всё нормально. Но при подключении к компьютеру устройства программа завершается с ошибкой "Попытка доступа к элементу textBox1 не из того потока, в котором он был создан". Обработчик получения данных для serialPort1 следующий:
Код

private: System::Void serialPort1_DataReceived ( трампампам...
{
   textBox1->AddText ( serialPort1->ReadLine () );
}


Всё, что мне удалось нагуглить - это то, что проблема в так называемой потокобезопасности. Но все примеры решения, которые я нашёл, написаны для С#. Вопрос - как мне добавлять данные из serialPort1 в textBox1.
Ответ:
Спасибо, разобрался. Хорошо разобран вопрос вот здесь: 

Вопрос: Прием данных в COM порт и вывод HEX в JTextArea

Имеется класс события по приему данных в COM порт
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
 
...
    private JTextArea input = new JTextArea("input");
    private SerialPort serialPort = new SerialPort(comPort);
    PortReader portReader = new PortReader();
...
   // клас для имплементации события приема данных в com порт
    class PortReader implements SerialPortEventListener {
        
        @Override
        public void serialEvent(SerialPortEvent event) {
            if(event.isRXCHAR() && event.getEventValue() > 0){
                try {
                    // очистка JTextArea input
                    input.setText(null);
                   //Получаем ответ от устройства, обрабатываем данные и т.д.
                    readData = serialPort.readHexString(event.getEventValue());
                    // вывод принятых данных в окно input
                    onDataReceived(readData);
                    // 
                }
                catch (SerialPortException ex) {
                    System.out.println(ex);
                }
            }
        }
    }
и метод по выводу данных в JTextArea input
Java
1
2
3
4
    // метод отображения данных в input
    public void onDataReceived(String readData) {
        input.append(readData);
    }
На вход COM порта приходит непрерывный поток байт информации (скорость 115200) от 800 до 3000 байт с перидом в 1 секунду. Количество информации каждую секунду разное.
SerialPortEventListener работает нормально. Я так понимаю, что SerialPortEventListener находится в главном потоке приложения. И срабатывает он при каждом вхождении в поток если в буфере COM порта имеется хоть 1 байт информации.
Проблема в отображении в окне JTextArea input всей иформации принятой за один период приема (1 сек). Если делать очистку окна при каждом срабатывании SerialPortEventListener то в окне JTextArea input отобразится только последний кусок информации из всего непрерывного потока в (800...3000) байт. В сдующую секунду все повторится.

Как правильно организовать прием и отображение так, чтобы в окне JTextArea input отображалась вся информация за один период приема?
Ответ: append есть input.append(readData);
Проблема в том, что каждую секунду принятую информацию необходимо отбражать в чистом окне JTextArea. А значит перед каждым приемом окно нужно очищать. Дело в том, что SerialPortEventListener за один период прима срабатывает много раз - проще говоря информация одного общего приемного пакета (пакет приходит 1 раз в секунду) в приемном буфере появляется мелкими кусками по пару десятков байт. Вопрос в том как информацию соединить и отобразить всю (порядка 800...3000 байт) в очищенном окне JTextArea.
Первые четыре байта пакета - A1 A2 03 45 При этом A1 A2 - синхробайты (неизменны), 03 45 - одно из возможного количества последующих байт в пакете.
Допустим прием делаю так
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
...
// глобальный счетчик байт приема по COM
int comAllCount
// матрица приема по COM
byte[] arrReadComByte;
....
// клас для имплементации события приема данных в com порт
class PortReader implements SerialPortEventListener {
// локальный счетчик байт
int comCount;
        
@Override
public void serialEvent(SerialPortEvent event) {
if(event.isRXCHAR() && event.getEventValue() > 0){
// подсчет количества байт в буфере при каждом срабатывании event
comCount = serialPort.getInputBufferBytesCount();
// глобальный счетчик принятых байт
comAllCount = comAllCount + comCount;
// запись данных в матрицу 
byte[] arrReadComByte = serialPort.readBytes(comCount);
// перенос данных в строку
for (int i = 0; i < comCount; i++){
     readData = readData + String.format("%02X ", arrReadComByte[i]);
}
// вывод данных в окно input JTextArea
if(comAllCount > ?????){
// вывод принятых данных в окно input
onDataReceived(readData);
} 
 
..
Не врубаюсь как поймать в пакете второй и третий байты 03 45 чтобы вставить вместо ?????

Добавлено через 1 час 38 минут
Пытаюсь делать так
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
   // клас для имплементации события приема данных в com порт
    class PortReader implements SerialPortEventListener {
        
        int comCount;
        int comLenght; 
        byte[] arrReadComByte;
        
        @Override
        public void serialEvent(SerialPortEvent event) {
            if(event.isRXCHAR() && event.getEventValue() > 0){
                try {
                   //Получаем ответ от устройства, обрабатываем данные и т.д.
                    comCount = serialPort.getInputBufferBytesCount();
                    comAllCount = comAllCount + comCount;
                    arrReadComByte = serialPort.readBytes(comCount);
                    if(comCount > 0){
                        for(int i = 0; i < comCount; i++){
                            if(arrReadComByte[i] == 0xa1 && arrReadComByte[i + 1] == 0xa2){
                                comLenght = arrReadComByte[i + 2] | arrReadComByte[i + 3] << 8;
                                System.out.println(comLenght);
                            }
                        }
                    }
                    for (int i = 0; i < comCount; i++){
                        readData = readData + String.format("%02X ", arrReadComByte[i]);
                    }
                    if(comAllCount >= comLenght){
                        // обнулить глобальный счетчик байт 
                        comAllCount = 0;
                        input.setText(null);
                        // вывод принятых данных в окно input
                        onDataReceived(readData);
                        // очистка строки приема
                        readData = "";
                    }
                }
                catch (SerialPortException ex) {
                    System.out.println(ex);
                }
            }
        }
    }
Не работает конструкция
Java
1
2
3
4
5
6
                        for(int i = 0; i < comCount; i++){
                            if(arrReadComByte[i] == 0xa1 && arrReadComByte[i + 1] == 0xa2){
                                comLenght = arrReadComByte[i + 2] | arrReadComByte[i + 3] << 8;
                                System.out.println(comLenght);
                            }
                        }
Не врубаюсь почему не работает...
Не находятся в матрице последовательные байты a1 a2, хотя ни там точно есть.
Вопрос: Как передать в COM порт 7 байт за одну команду Write?

Ситуация:
К СОМ порту подключено устройство, которое понимает 2-х или 7-ми байтные команды. Описание всех команд есть и из родной (для этого устройства программы DIGI_XCTU) нормально понимает поступающие команды и нормально отвечает. Надо сделать своё приложение по управлению этим устройством. Взял компонент BCOMPort. Приём ответов от устройства идёт в своей программе без проблем.
Проблема: не получается передать 7-ми байтную команду. Байты команд надо передавать в определённой последовательности, передача начинается со старших байт команды, задержка в передаче бит более 1-ой битовой посылки считается устройством концом передачи команды.
Пример: передаём 7-ми байтную команду $12 34 56 78 90 AB CD соответственно через компорт сначала должен уйти байт $12 потом $34 и т.д. При этом задержка между передаваемыми битами, не должно превышать 1-ой битовой посылки. (т.е. при скорости передачи 57600 бит/с, задержка передачи в 0,018 мсек является концом передачи команды)
Если использовать следующий код (см.ниже), то управляемое устройство ничего не отвечает, видимо передача команды идёт не целым блоком, а с перерывами и устройство не воспринимает эту передачу как одну 7-ми байтную команду. Возможно неверно выставлены таймауты у порта (значения их выставлены по умолчанию (см.код ниже)).
var Buf:array[1..7] of byte;
begin
  Buf[1]:=$12;
  Buf[2]:=$34;
  Buf[3]:=$56;
  Buf[4]:=$78;
  Buf[5]:=$90;
  Buf[6]:=$AB;
  Buf[7]:=$CD;
  BCOMPort.Close;
  BCOMPort1.BoudRate:=br57600;
  BCOMPort1.ByteSize:=bs8;
  BCOMPort1.StopBits:=sb1;
  BCOMPort1.Parity=paNone;
  BCOMPort1.Timeouts.WriteTotalMultiplier:=100;
  BCOMPort1.Timeouts.WriteTotalConstant:=1000;
  BCOMPort.Open;
  BCOMPort1.Write(Buf[1],1);
  BCOMPort1.Write(Buf[2],1);
  BCOMPort1.Write(Buf[3],1);
  BCOMPort1.Write(Buf[4],1);
  BCOMPort1.Write(Buf[5],1);
  BCOMPort1.Write(Buf[6],1);
  BCOMPort1.Write(Buf[7],1);
end; 

Вопрос:
1. как организовать передачу 7 байт одним блоком, метода Write компонента BCOMPort?
2. какие должны быть значения таймаутов записи (WriteTotal...), чтобы все 7 байт передавались без задержки - одним блоком?
Ответ:
abwabw
задержка в передаче бит более 1-ой битовой посылки считается устройством концом передачи команды.
скорости передачи 57600 бит/с, задержка передачи в 0,018 мсек является концом передачи команды
и где такое написано?
это ж кроме $55 или $AA ничего и не отправить Ж)

+
Делай так:!
var Buf:array[1..7] of byte; B: byte;
begin
  Buf[1]:=$12;
  Buf[2]:=$34;
  Buf[3]:=$56;
  Buf[4]:=$78;
  Buf[5]:=$90;
  Buf[6]:=$AB;
  Buf[7]:=$CD;
  for B in Buf do try  
   BCOMPort.Close;
   BCOMPort1.BoudRate:=br57600;
   BCOMPort1.ByteSize:=bs8;
   BCOMPort1.StopBits:=sb1;
   BCOMPort1.Parity=paNone;
   BCOMPort1.Timeouts.WriteTotalMultiplier:=100;
   BCOMPort1.Timeouts.WriteTotalConstant:=500;
   BCOMPort.Open;
   BCOMPort1.Write(B,1);
   SleepEx(-0.0018);
  finally 
   BCOMPort.Free;
  endl
end; 
Вопрос: Чтение из com-порта

Доброго времени суток, уважаемые форумчане! В общем такая ситуевина, две программки взаимодействуют через com-порты, одна - эмулятор устройства, вторая - тестер, посылает команды. Запрос отправляется корректно, а вот ответ приходит кривой, состоящий из символов '?'. ComPort из библиотеки CPort, ответ читается командой ReadStr. Прикол в чем, если отлаживаться и зайти в эту функцию через отладчик и пройтись пошагово внутри, то значение читается корректно, а если не ставить точку остановы, то читаются левые символы. Слушал порты, ответ приходит в правильном формате. Затык именно при чтении из порта. Бред какой-то. Думаю, может comport`у таймаут какой нужен, для чтения. Перед каждым посылом запроса буфер порта чистится. Ставил слипы, все равно не помогает. Делфя десятка сиэтл. Буду рад любой помощи.
Ответ:
Alex_xelA
чую где-то подвох) Почему когда Я пошагово прошел внутри процедуры чтения из порта, у меня сформировался верный ответ

Наверняка отладчик глючит - показывает в хинте немного не то, что на самом деле.