Форум программистов, компьютерный форум, киберфорум
Visual Basic
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.55/56: Рейтинг темы: голосов - 56, средняя оценка - 4.55
 Аватар для уни
368 / 146 / 17
Регистрация: 06.03.2010
Сообщений: 327
Записей в блоге: 1

Класс для COM-порта с поддержкой событий

05.09.2014, 11:48. Показов 11681. Ответов 30

Студворк — интернет-сервис помощи студентам
Доброго. Мне нужен класс для работы с COM-портом с поддержкой событий.

У меня есть вариант: Serial Port Communication in Excel (VBA). Я его использую в Excel. Проблема в том, что нужно ручками регулировать время между командой и ответом, чтобы гарантировано принять данные во входной буфер. Хотелось бы иметь событие OnReceive(), которое основано на WaitCommEvent(). Без событийного решения трудно реализовать оптимальный по скорости алгоритм работы с устройствами. Мне нужно с определённой частотой читать данные и желательно получать их по мере заполнения входного буфера нужной посылкой.

Можно ли что-то такое сделать на vb6? Мне не нужны сторонние решения в готовом виде (ActiveX, dll и т.п.). Нужно всё реализовать на макросах в таблице.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
05.09.2014, 11:48
Ответы с готовыми решениями:

Класс для работы со строками (с поддержкой китайских символов)
Всем привет! Необходима помощь по созданию класса на C++ для работы со строками, строки должны поддерживать китайские символы. Заранее...

Календарь событий с заметками и поддержкой файлов
Помогите с курсовой роботой Пользователь на выбранную дату и время может установить произвольную событие. Дополнительный сервис включает...

Кто встречал контрол типа стандартного Line, но с поддержкой событий?
Нужен сабж, чтобы можно было ловить клики на нем.

30
Модератор
10048 / 3894 / 883
Регистрация: 22.02.2013
Сообщений: 5,847
Записей в блоге: 79
05.09.2014, 13:13
Не вникал. В общем виде тебе нужен класс, который при установке объекта в сигнальное состояние возбуждает событие?
0
 Аватар для уни
368 / 146 / 17
Регистрация: 06.03.2010
Сообщений: 327
Записей в блоге: 1
05.09.2014, 16:28  [ТС]
Да, можно так, но это в лучшем случае. Можно просто в цикле дожидаться появления флага RX и выходить из цикла, либо по таймауту. Сейчас я использую код выше где тупо вставляю некоторую эмпирическую задержку, чтобы ответ точно находился в буфере приёмника, т.е. пакет принят и я его могу считать при помощи WinAPI. Но это плохой вариант, если мне нужно вести работу на десятках герц (в зависимости от скорости и длины посылки). Иногда данные выпадают (буфер пустой при чтении), а с одним прибором я вообще не могу организовать такую связь, хотя одиночные команды работают нормально. Ещё есть прибор, который сам шлёт данные без запроса. С ним тоже не просто, если нет события.

Не пойму пока в чём дело, может что-то с таймаутами, которые в коде взяты с потолка, может ещё что, но всё равно, мне нужен стабильный факт приёма или превышение таймаута на ожидание ответа. Т.е. два даже события. Примеры есть в сети, но не для бейсика. Мне трудно их с ходу перевести.

Видел хороший пример реализации класса на delphi, но найти его не могу сейчас. Там всё чисто на WinAPI, как мне надо.
0
Модератор
10048 / 3894 / 883
Регистрация: 22.02.2013
Сообщений: 5,847
Записей в блоге: 79
05.09.2014, 16:30
уни, как домой приду скину, я делал такой класс. В другом потоке запускается цикл с Wait функцией при срабатывании генерируется событие.
1
Модератор
10048 / 3894 / 883
Регистрация: 22.02.2013
Сообщений: 5,847
Записей в блоге: 79
07.09.2014, 01:06
Лучший ответ Сообщение было отмечено The trick как решение

Решение

уни, как и обещал. Немного доработал и выложил в блоге, если это то конечно.
1
 Аватар для уни
368 / 146 / 17
Регистрация: 06.03.2010
Сообщений: 327
Записей в блоге: 1
07.09.2014, 07:29  [ТС]
Спасибо за код, но он не подойдёт в моём конкретном применении. Дело в том, что я использую vba, а его существует 4 разновидности: 2 разрядности и версии до и после 2010. Мне нужен универсальный код на макросах, который бы охватывал и разрядности, и старые версии офиса. Ассемблер уже перебор. Я WinAPI функции с трудом описываю для всех вариантов.
0
Модератор
10048 / 3894 / 883
Регистрация: 22.02.2013
Сообщений: 5,847
Записей в блоге: 79
07.09.2014, 11:47
уни, а просто цикл с WaitForSingleObject не идет?
0
 Аватар для уни
368 / 146 / 17
Регистрация: 06.03.2010
Сообщений: 327
Записей в блоге: 1
08.09.2014, 11:20  [ТС]
The trick, WaitForSingleObject() подходит, только я ещё толком не понял как его использовать правильно в моём случае. Вот статья из MSDN, где есть куски нужного мне кода по чтению данных из приёмного буфера: Serial Communications.

У меня алгоритм такой (командный вариант):

1. Сбрасываем входные буферы приёмника и передатчика (имеются в виду системные).
2. Посылаем команду чтения и ожидаем приёма в течении некоторого таймаута чтения.
3. Считываем данные из системного буфера.

Мне нужно, чтобы в течении таймаута я считывал только тогда, когда ответ действительно будет в буфере, а не в произвольный момент времени с эмпирической задержкой, как сейчас я это делаю. Операция ReadFile() должна ожидать нужного количества принятых байт, а потом уже возвращать результат. Та функция, которую я сейчас использую, так не делает. Она сразу возвращает результат. Поэтому я искусственно ввожу задержку.

Возможно у меня проблема в том, что умолчания, по которым идёт работа с COM-портом, настроены не так как мне нужно. Судя по статье, есть два варианта использования функций чтения: блокирующий и неблокирующий (определяется специальным параметром). Наверное у меня включено неблокирующее чтение, но обработка его идёт не полностью.

Вот ещё одна ссылка на набор функций для работы с COM-портом через WinAPI: Serial Port Communication.

Добавлено через 1 час 17 минут
У меня есть ещё и другая проблема. Операция записи буферизируется системой. В результате чего вместо трёх посылок (команд) фактически посылается одна. Пока не понял как это победить. Проще всего, наверное, сделать все операции блокирующими, но это повлияет на интерфейс пользователя при длительных операциях, а у меня в форме строка прогресса обновляться должна.

В общем, всё довольно сложно и придётся разбираться для достижения нужного эффекта с реальными приборами.
0
Модератор
10048 / 3894 / 883
Регистрация: 22.02.2013
Сообщений: 5,847
Записей в блоге: 79
08.09.2014, 16:49
  1. Открывай порт через CreateFile.
  2. Создавай событие CreateEvent
  3. Заполняй в структуре OVERLAPPED поле hEvent.
  4. Делай ReadFile/WriteFile передавая структуру OVERLAPPED последним параметром.
  5. Запускай бесконечный цикл с WaitForSingleObject с таймаутом и в теле вызывай DoEvents.
  6. При установке в сигнальное состояние эвента, вызывай GetOverlappedResult для получения статуса
.
0
 Аватар для уни
368 / 146 / 17
Регистрация: 06.03.2010
Сообщений: 327
Записей в блоге: 1
10.09.2014, 14:12  [ТС]
Запускай бесконечный цикл с WaitForSingleObject с таймаутом и в теле вызывай DoEvents.
Мне получается бесконечный цикл не нужен, т.к. если в течении некоторого таймаута (100 мс, к примеру) ответ не пришёл, то ждать мне смысла нет. Прибор не отвечает - ошибка на линии.
0
Модератор
10048 / 3894 / 883
Регистрация: 22.02.2013
Сообщений: 5,847
Записей в блоге: 79
10.09.2014, 14:15
Цитата Сообщение от уни Посмотреть сообщение
Мне получается бесконечный цикл не нужен, т.к. если в течении некоторого таймаута (100 мс, к примеру) ответ не пришёл, то ждать мне смысла нет. Прибор не отвечает - ошибка на линии.
Значит не нужен. Ставь таймаут на 100 мс и проверяй возвращаемое значение, если возвратит WAIT_TIMEOUT, значит не пришел ответ, иначе проверяй GetOverlappedResult.
0
 Аватар для уни
368 / 146 / 17
Регистрация: 06.03.2010
Сообщений: 327
Записей в блоге: 1
18.09.2014, 12:12  [ТС]
Помогите перевести работающий код с c++/cli на vb6. У меня проблема с заполнением буфера при чтении в vb6 версии.

В качестве шаблона для vb6 версии можно взять модуль по ссылке, на которую я указывал выше. Я сам переделал под себя, запрос-ответ происходит (слежу монитором порта), а вот в приёмный буфер данные не записываются, хотя принятое количество байт показывается. Не пойму в чём дело.

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
238
239
240
241
242
243
244
245
// TestSerial.cpp : main project file.
 
#include "stdafx.h"
#include "windows.h"
#include <string>
#include <iostream>
#include <exception>
 
using namespace std;
 
using namespace System;
 
#define READ_TIMEOUT_MSEC 100
 
const DWORD READ_BUF_SIZE = 20;
 
 
BOOL WriteComPort(HANDLE hComm, char * lpBuf, DWORD dwToWrite, DWORD &dwWritten)
{
    OVERLAPPED osWrite = { 0 };
    DWORD dwRes;
    BOOL fRes = FALSE;
 
    // Create this write operation's OVERLAPPED structure's hEvent.
    osWrite.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
 
    if (osWrite.hEvent == NULL) {
    
        // error creating overlapped event handle
        return FALSE;
    }
 
    // Issue write.
    if (!::WriteFile(hComm, lpBuf, dwToWrite, &dwWritten, &osWrite)) {
 
        if (::GetLastError() != ERROR_IO_PENDING) {
            
            // WriteFile failed, but isn't delayed. Report error and abort.
            fRes = FALSE;
        }
        else {
 
            // Write is pending.
            dwRes = ::WaitForSingleObject(osWrite.hEvent, INFINITE);
 
            switch (dwRes)
            {
                // OVERLAPPED structure's event has been signaled. 
                case WAIT_OBJECT_0:
 
                    if (!::GetOverlappedResult(hComm, &osWrite, &dwWritten, TRUE))
                        fRes = FALSE;
                    else
                        // Write operation completed successfully.
                        fRes = TRUE;
                    break;
 
                default:
 
                    // An error has occurred in WaitForSingleObject.
                    // This usually indicates a problem with the
                    // OVERLAPPED structure's event handle.
                    fRes = FALSE;
                    break;
                }
            }
    }
    else {
    
        // WriteFile completed immediately.
        fRes = TRUE;
    }
 
    if (osWrite.hEvent != NULL) ::CloseHandle(osWrite.hEvent);
 
    return fRes;
}
 
 
BOOL ReadComPort(HANDLE hComm, char * lpBuf, DWORD &dwRead) {
 
    BOOL fRes = FALSE;
    OVERLAPPED osReader = { 0 };
 
    // Create the overlapped event. Must be closed before exiting
    // to avoid a handle leak.
    osReader.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
 
    if (osReader.hEvent == NULL) {
 
        // error creating overlapped event handle
        return FALSE;
    }
 
    // Issue read operation.
    DWORD fSuccess = ::ReadFile(hComm, lpBuf, READ_BUF_SIZE, &dwRead, &osReader);
    
    DWORD dwErr = GetLastError();
 
    if (!fSuccess) {
            
        //if (::GetLastError() != ERROR_IO_PENDING) {
        if (false) {
 
            // WriteFile failed, but isn't delayed. Report error and abort.
            fRes = FALSE;
        }
        else {
 
            DWORD dwRes = ::WaitForSingleObject(osReader.hEvent, READ_TIMEOUT_MSEC);
 
            switch (dwRes) {
 
                // Read completed.
                case WAIT_OBJECT_0:
 
                    if (!::GetOverlappedResult(hComm, &osReader, &dwRead, FALSE)) {
 
                        // Error in communications; report it.
                        throw new exception("Error in communications");
 
                    }
                    else {
 
                        // Read completed successfully.
                        fRes = TRUE;
                    }
 
                    break;
 
                case WAIT_TIMEOUT:
 
                    // Operation isn't complete yet. fWaitingOnRead flag isn't
                    // changed since I'll loop back around, and I don't want
                    // to issue another read until the first one finishes.
                    //
                    // This is a good time to do some background work.
                    fRes = FALSE;
                    break;
 
                default:
                    // Error in the WaitForSingleObject; abort.
                    // This indicates a problem with the OVERLAPPED structure's
                    // event handle.
                    fRes = FALSE;
                    break;
            }
 
        }
 
    }
 
    if (osReader.hEvent != NULL) ::CloseHandle(osReader.hEvent);
}
 
 
int main(array<System::String ^> ^args)
{
    wstring name;
    HANDLE hComm = NULL;
    char * buff = new char[21];
 
    try {
 
        name = L"COM1";
 
        hComm = ::CreateFile( name.c_str(),
            GENERIC_READ | GENERIC_WRITE,
            0,
            NULL,
            OPEN_EXISTING,
            FILE_FLAG_OVERLAPPED,
            NULL);
 
        if ( hComm == INVALID_HANDLE_VALUE ) {
            
            throw new exception("INVALID_HANDLE_VALUE");
        }
 
        DCB dcb;
        
        ::FillMemory(&dcb, sizeof(dcb), 0);
 
        DWORD fSuccess = ::GetCommState(hComm, &dcb);
        
        if (!fSuccess){
            
            throw new exception("GetCommState()");
        }
 
        dcb.DCBlength = sizeof(DCB);
        
        if (!::BuildCommDCB(L"9600,n,8,1", &dcb)) {
 
            // Couldn't build the DCB. Usually a problem
            // with the communications specification string.
            throw new exception("BuildCommDCB()");
        }
 
        fSuccess = ::SetCommState(hComm, &dcb);
        
        if (!fSuccess){
 
            throw new exception("SetCommState()");
        }
 
        // Contains various COM timeouts 
        COMMTIMEOUTS CommTimeouts;       
 
        // Timeouts in msec.
        CommTimeouts.ReadIntervalTimeout = MAXDWORD;
        CommTimeouts.ReadTotalTimeoutMultiplier = 10;
        CommTimeouts.ReadTotalTimeoutConstant = 100;
        CommTimeouts.WriteTotalTimeoutMultiplier = 0;
        CommTimeouts.WriteTotalTimeoutConstant = 0;
 
        // Set COM timeouts.
        fSuccess = ::SetCommTimeouts(hComm, &CommTimeouts);
 
        if (!fSuccess){
        
            throw new exception("SetCommTimeouts()");
        }
 
        // Посылаем команду чтения данных.
        string cmd = "AT02R";
        DWORD dwWritten;
 
        WriteComPort(hComm, (char *)cmd.c_str(), cmd.length(), dwWritten);
 
        // Принимаем ответ.       
        DWORD dwRead;
 
        ReadComPort(hComm, buff, dwRead);
        
    }
    catch ( exception &ex ) {
        
        cout << "[ERROR] " << ex.what() << endl;
    }
 
    if (hComm != NULL)  ::CloseHandle(hComm);
 
    return 0;
}
Вот функция чтения:

Visual Basic
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
Public Function CommRead(intPortID As Integer, strData As String, _
    lngSize As Long) As Long
 
    Dim lngStatus As Long
    Dim lngRdSize As Long, lngBytesRead As Long
    Dim lngRdStatus As Long, strRdBuffer As String * 1024
    Dim lngErrorFlags As Long, udtCommStat As COMSTAT
    
    Dim osReader As OVERLAPPED
    
    osReader.hEvent = 0
    osReader.Internal = 0
    osReader.InternalHigh = 0
    osReader.offset = 0
    osReader.OffsetHigh = 0
    
    On Error GoTo Routine_Error
 
    strData = ""
    lngBytesRead = 0
    
'    ' Clear any previous errors and get current status.
'    lngStatus = ClearCommError(udtPorts(intPortID).lngHandle, lngErrorFlags, _
'        udtCommStat)
'
'    If lngStatus = 0 Then
'
'        lngBytesRead = -1
'        lngStatus = SetCommError("CommRead (ClearCommError)")
'        GoTo Routine_Exit
'
'    End If
        
'    If udtCommStat.cbInQue > 0 Then
'
'        If udtCommStat.cbInQue > lngSize Then
'
'            lngRdSize = udtCommStat.cbInQue
'
'        Else
'
'            lngRdSize = lngSize
'
'        End If
'
'    Else
'
'        lngRdSize = 0
'
'    End If
    
    lngRdSize = lngSize
    
    If lngRdSize Then
        
        osReader.hEvent = CreateEvent(0, True, False, 0)
    
        If osReader.hEvent = 0 Then
        
            lngBytesRead = -1
            lngStatus = SetCommErrorEx("CommRead (CreateEvent)", _
                udtPorts(intPortID).lngHandle)
                
            GoTo Routine_Exit
 
        End If
                
        lngRdStatus = ReadFile(udtPorts(intPortID).lngHandle, strRdBuffer, _
            lngRdSize, 0, osReader)
            
        If lngRdStatus = 0 Then
                    
            Dim dwRes As Long
        
            ' Wait for read to complete.
            dwRes = WaitForSingleObject(osReader.hEvent, READ_TIMEOUT)
            
            Select Case dwRes
            
                ' Read completed.
                Case WAIT_OBJECT_0
            
                    If GetOverlappedResult(udtPorts(intPortID).lngHandle, _
                        osReader, lngBytesRead, False) = 0 Then
                        
                        ' Error in communications; report it.
                        lngBytesRead = -1
                        lngStatus = SetCommErrorEx("CommRead (GetOverlappedResult)", _
                            udtPorts(intPortID).lngHandle)
                            
                        GoTo Routine_Exit
                
                    Else
                    
                        ' Read completed successfully.
                    
                    End If
                    
          
                Case WAIT_TIMEOUT
 
                    lngBytesRead = -1
                    lngStatus = SetCommErrorEx("CommRead (WaitForSingleObject)", _
                        udtPorts(intPortID).lngHandle)
                        
                    GoTo Routine_Exit
                
                Case Else
 
                    lngBytesRead = -1
                    lngStatus = SetCommErrorEx("CommRead (WaitForSingleObject)", _
                        udtPorts(intPortID).lngHandle)
                    GoTo Routine_Exit
                        
            End Select
            
        End If
    
        strData = Left$(strRdBuffer, lngBytesRead)
        
    End If
 
Routine_Exit:
    
    If Not osReader.hEvent = 0 Then CloseHandle osReader.hEvent
 
    CommRead = lngBytesRead
    Exit Function
 
Routine_Error:
    lngBytesRead = -1
    lngStatus = Err.Number
    
    With udtCommError
    
        .lngErrorCode = lngStatus
        .strFunction = "CommRead"
        .strErrorMessage = Err.Description
        
    End With
    
    Resume Routine_Exit
    
End Function
0
Модератор
10048 / 3894 / 883
Регистрация: 22.02.2013
Сообщений: 5,847
Записей в блоге: 79
18.09.2014, 12:22
Во-первых, где объявления API функций?
Что это такое strRdBuffer? Какой тип в C++ передается? А у тебя?
0
 Аватар для уни
368 / 146 / 17
Регистрация: 06.03.2010
Сообщений: 327
Записей в блоге: 1
18.09.2014, 14:19  [ТС]
Цитата Сообщение от уни Посмотреть сообщение
В качестве шаблона для vb6 версии можно взять модуль по ссылке, на которую я указывал выше.
Цитата Сообщение от уни Посмотреть сообщение
Вот ещё одна ссылка на набор функций для работы с COM-портом через WinAPI: Serial Port Communication.
Базовый код я брал оттуда, так как он работал, но в "синхронном" режиме. Я начал переделывать под "асинхронный". Запись работает, а чтение нет. В мониторе порта я вижу и команду, и ответ. Но ответ не попадает в буфер этот самый в программе на vb6.
0
Модератор
10048 / 3894 / 883
Регистрация: 22.02.2013
Сообщений: 5,847
Записей в блоге: 79
18.09.2014, 15:48
уни, у тебя в коде на C++ буфер представляет собой массив из 21 элемента типа char (аналог VB6 - byte). Ты туда вставил String. Вопрос - зачем? String - это не char, String - это BSTR*. BSTR - WCHAR*. WCHAR - 16-bit Unicode character, на 8-битный char вообще не похоже.
0
 Аватар для уни
368 / 146 / 17
Регистрация: 06.03.2010
Сообщений: 327
Записей в блоге: 1
18.09.2014, 15:55  [ТС]
Это не я вставил, это так было и это не суть важно, так как я могу получить байтовый массив из строки. Важно тут другое, этот буфер при принятии ответа не заполняется. При отладке, когда я принимаю ответ, он пуст, хотя алгоритм приема работает нормально и даже возвращает количество принятых байт.
0
Модератор
10048 / 3894 / 883
Регистрация: 22.02.2013
Сообщений: 5,847
Записей в блоге: 79
18.09.2014, 16:02
уни, думаешь я просто так написал тебе этот пост?
Цитата Сообщение от уни Посмотреть сообщение
Это не я вставил, это так было и это не суть важно, так как я могу получить байтовый массив из строки.
За тот код, который там опубликован автору нужно укоротить руки и навсегда запретить пользоваться интернетом чтобы он не постил говнокод в качестве туториалов. Если ты не знаешь почему у тебя не работает код, тогда почему ты так уверен что "это не суть важно"? Я знаю почему у тебя не работает код и я написал тебе, но ты упорно не хочешь следовать моему совету. Почему?
Цитата Сообщение от уни Посмотреть сообщение
При отладке, когда я принимаю ответ, он пуст, хотя алгоритм приема работает нормально и даже возвращает количество принятых байт.
Алгоритм работает нормально - он нормален. Код не работает нормально - он ненормален. Причину я написал.
0
 Аватар для уни
368 / 146 / 17
Регистрация: 06.03.2010
Сообщений: 327
Записей в блоге: 1
18.09.2014, 16:47  [ТС]
Не суть важно, потому что это выделенная область неуправляемой памяти, доступная для чтения и записи. Если запись и чтение с этой областью происходят, то мне нет дела пока до того как это оформлено.

Его код в оригинале работает даже с бинарными данными, я проверял. Пусть там будет пока строка или что угодно. Главное, чтобы указатели были правильные. Мне пока нет дела до интерпретации. Мне нужен просто факт того, что в буфере что-то есть.

Когда я перешёл на OVERLAPPED режим, то у меня изменился внутренний системный алгоритм работы. Я долго доводил до ума программу на c++, прежде чем она заработала как надо. Там очень много тонкостей как оказалось.

Я не думаю, что проблема в том, что используется строка вместо указателя на выделенный участок памяти. Пусть это некорректно, но что-то должно попадать в буфер всё-равно. У меня была похожая проблема в программе на c++, когда я не мог принять ответ, хотя команда проходила. Оказалось, что нельзя при таком режиме оставлять нулевые таймауты для чтения при настройке порта. Когда я их изменил, ReadFile начала заполнять буфер и возвращать результат.
0
Модератор
10048 / 3894 / 883
Регистрация: 22.02.2013
Сообщений: 5,847
Записей в блоге: 79
18.09.2014, 16:54
Цитата Сообщение от уни Посмотреть сообщение
Не суть важно, потому что это выделенная область неуправляемой памяти, доступная для чтения и записи. Если запись и чтение с этой областью происходят, то мне нет дела пока до того как это оформлено.
Ты уверен? Неужели трудно заменить строку массивом байт и убедиться как это волшебным образом заработает?
Цитата Сообщение от уни Посмотреть сообщение
Его код в оригинале работает даже с бинарными данными, я проверял. Пусть там будет пока строка или что угодно. Главное, чтобы указатели были правильные. Мне пока нет дела до интерпретации. Мне нужен просто факт того, что в буфере что-то есть.
Ты уже сам отвечаешь на свой вопрос.
Цитата Сообщение от уни Посмотреть сообщение
Когда я перешёл на OVERLAPPED режим, то у меня изменился внутренний системный алгоритм работы. Я долго доводил до ума программу на c++, прежде чем она заработала как надо. Там очень много тонкостей как оказалось.
Все тонкости описаны в статье на MSDN.
Цитата Сообщение от уни Посмотреть сообщение
Я не думаю, что проблема в том, что используется строка вместо указателя на выделенный участок памяти.
Не думай - это вообще-то твоя проблема. Я больше не буду тебе подсказывать, т.к. не вижу в этом смысла, после твоего игнорирования.
Цитата Сообщение от уни Посмотреть сообщение
Пусть это некорректно, но что-то должно попадать в буфер всё-равно.
Ключевое слово здесь некорректно.
Цитата Сообщение от уни Посмотреть сообщение
У меня была похожая проблема в программе на c++, когда я не мог принять ответ, хотя команда проходила. Оказалось, что нельзя при таком режиме оставлять нулевые таймауты для чтения при настройке порта. Когда я их изменил, ReadFile начала заполнять буфер и возвращать результат.
Твоя проблема не в этом.
0
 Аватар для уни
368 / 146 / 17
Регистрация: 06.03.2010
Сообщений: 327
Записей в блоге: 1
18.09.2014, 17:42  [ТС]
Цитата Сообщение от The trick Посмотреть сообщение
Ты уверен? Неужели трудно заменить строку массивом байт и убедиться как это волшебным образом заработает?
У меня уже всё работает. Два прибора и программа в Excel на VBA с указанной обёрткой ReadFile. Я конвертирую строку в набор байт и беру нужные мне байты.

Ты даёшь совет как мне красивее и правильнее доставать байты из буфера? Хм. В полезности совета не сомневаюсь, но не хочу пока трогать то, что и так работает.

Остальное доделаю сам.
Миниатюры
Класс для COM-порта с поддержкой событий  
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
18.09.2014, 17:42
Помогаю со студенческими работами здесь

Класс с поддержкой интерфейса IEnumerable<T>
Имеется некоторый класс: class DoublyLinkedList&lt;T&gt; : IEnumerable&lt;T&gt; {...} Хочу реализовать у него поддержку интерфейса...

Класс длинная арифметика с поддержкой арифметических операций
Кто-нибудь уже писал класс для работы с очень большими числами, с поддержкой операторов +-/*, если да, то дайте, пожалуйста, ссылку на код....

Нужен батник для создания отчета событий и их свойств из журнала событий на локальном компьютере
Пакетный файл, предназначенный для создания отчета событий и их свойств из журнала событий на локальном компьютере. Журналы событий:...

Реализовать хранилище событий, для хранения событий в БД
Доброго дня! Поставлена задача реализовать хранилище событий, для хранения событий в БД) Событие представляет собой обработанную...

Подскажите бесплатный хостинг с поддержкой MySQL баз и с поддержкой внешних подключений к базе данных
Нужен бесплатный хостинг, у которого нет такого прикола как указание IP адреса явно разрешённого для подключения к MySQL базе данных....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru