Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.54/13: Рейтинг темы: голосов - 13, средняя оценка - 4.54
-13 / 6 / 6
Регистрация: 04.08.2015
Сообщений: 622

Не работает Com порт в асинхронном режиме

12.10.2016, 11:07. Показов 2898. Ответов 20
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Крайне необходимо небольшое приложение для Com порта работающее в асинхронном режиме. Принял некоторое переменное количество байт и сразу передал некоторое конечное количество байт.
Для реализации решил воспользоваться предложенным вариантом http://piclist.ru/S-COM-THREAD... D-RUS.html Составил небольшой проект в C++ Builder 6 на WinAPI
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
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
#include <vcl.h>
#pragma hdrstop
 
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
 
#define BUFSIZE 1000     //ёмкость буфера
 
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
  : TForm(Owner)
{
}
//---------------------------------------------------------------------------
// Глобальные переменные
 
//---------------------------------------------------------------------------
AnsiString portname;
HANDLE COMport;
DWORD WINAPI ReadThread(LPVOID);
DWORD WINAPI WriteThread(LPVOID);
 
//дескриптор потока чтения из порта
HANDLE reader;
//дескриптор потока записи в порт
HANDLE writer;
//приёмный и передающий буферы
unsigned char bufrd[BUFSIZE], bufwr[BUFSIZE];
 
//структура OVERLAPPED необходима для асинхронных операций, при этом для операции чтения и записи нужно объявить разные структуры
//эти структуры необходимо объявить глобально, иначе программа не будет работать правильно
OVERLAPPED overlapped;      //будем использовать для операций чтения (см. поток ReadThread)
OVERLAPPED overlappedwr;    //будем использовать для операций записи (см. поток WriteThread)
int handle;                 //дескриптор для работы с файлом с помощью библиотеки <io.h>
//  bool fl=0;  //флаг, указывающий на успешность операций записи (1 - успешно, 0 - не успешно)
DWORD bc;
DCB *dcb;
// счетчик приемов
unsigned long counterRX;
 
//---------------------------------------------------------------------------
 
// Функции
 
//---------------------------------------------------------------------------
// Вывод принятых байтов на экран
 
void ReadPrinting(DWORD btr)
{
  String stroka, temp_str;
  for(UINT32 i=0; i<btr ; i++)
    stroka = stroka + IntToHex(bufrd[i], 2) + ' '; // Перенос буфера в строку.
 
  Form1->Memo1->Lines->Add(stroka); // Вывод.
  Form1->Label1->Caption = "Всего принято: " + IntToStr(counterRX);
  memset(bufrd, 0, BUFSIZE); // Очистить буфер (чтобы данные не накладывались друг на друга).
}
 
//---------------------------------------------------------------------------
// Поток чтения ReadThead
 
//главная функция потока, реализует приём байтов из COM-порта
DWORD WINAPI ReadThread(LPVOID)
{
  COMSTAT comstat;        // структура текущего состояния порта, в данной программе используется для определения количества принятых в порт байтов
  DWORD btr, temp, mask, signal;  // переменная temp используется в качестве заглушки
 
  overlapped.hEvent = CreateEvent(NULL, true, true, NULL); // создать сигнальный объект-событие для асинхронных операций
  SetCommMask(COMport, EV_RXCHAR);                     // установить маску на срабатывание по событию приёма байта в порт
  while(1)
  //while(!flag)                       // пока поток не будет прерван, выполняем цикл
  {
    WaitCommEvent(COMport, &mask, &overlapped);                   //ожидать события приёма байта (это и есть перекрываемая операция)
    signal = WaitForSingleObject(overlapped.hEvent, INFINITE);    //приостановить поток до прихода байта
    if(signal == WAIT_OBJECT_0)                       //если событие прихода байта произошло
    {
      if(GetOverlappedResult(COMport, &overlapped, &temp, true)) //проверяем, успешно ли завершилась перекрываемая операция WaitCommEvent
        if((mask & EV_RXCHAR)!=0)                 //если произошло именно событие прихода байта
        {
          ClearCommError(COMport, &temp, &comstat); // нужно заполнить структуру COMSTAT
          btr = comstat.cbInQue;                    // и получить из неё количество принятых байтов
          if(btr)                                   // если действительно есть байты для чтения
          {
            ReadFile(COMport, bufrd, btr, &temp, &overlapped); // прочитать байты из порта в буфер программы
            counterRX+=btr;                                      // увеличиваем счётчик байтов
            ReadPrinting(btr);                                    // вызываем функцию для вывода данных на экран и в файл
          }
        }
    }
  }
//CloseHandle(overlapped.hEvent);
//flag2=1;
}
 
//---------------------------------------------------------------------------
// Поток записи WriteThread
 
//главная функция потока, выполняет передачу байтов из буфера в COM-порт
DWORD WINAPI WriteThread(LPVOID)
{
  DWORD temp, signal;   //temp - переменная-заглушка
 
  overlappedwr.hEvent = CreateEvent(NULL, true, true, NULL);      //создать событие
  while(1)
  {
    //записать байты в порт (перекрываемая операция!)
    WriteFile(COMport, bufwr, strlen(bufwr), &temp, &overlappedwr);
 
    //приостановить поток, пока не завершится перекрываемая операция WriteFile
    signal = WaitForSingleObject(overlappedwr.hEvent, INFINITE);
 
    //если операция завершилась успешно
    if((signal == WAIT_OBJECT_0) && (GetOverlappedResult(COMport, &overlappedwr, &temp, true)))
    {
      //вывести сообщение об этом в строке состояния
      Form1->Panel2->Caption = "Передача прошла успешно";
    }
    //иначе вывести в строке состояния сообщение об ошибке
    else {Form1->Panel2->Caption = "Ошибка передачи";}
 
    SuspendThread(writer);
  }
}
 
//---------------------------------------------------------------------------
// установки Com порта
 
void __fastcall TForm1::Button1Click(TObject *Sender)
{
  Form1->Panel1->Caption = "";
  DCB dcb;
  COMMTIMEOUTS timeouts;
 
  // Открытие порта
//  portname += "\\\\.";  // com_port.c_str()
//  portname += ComboBox1->Text;
  //portname = ChoiceCOM->Text;
  portname = Form1->ComboBox1->Text;
  COMport=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(COMport==INVALID_HANDLE_VALUE)
  {
    Panel1->Font->Color = clRed;
    Panel1->Caption = " Не удалось открыть последовательный порт " + AnsiString(portname.c_str()) + ".";
    return;
  }
  else
  {
    Panel1->Font->Color = clGreen;
    Panel1->Caption = " Открыт порт " + AnsiString(portname.c_str());
    return;
  }
 
  // Инициализация порта
  //dcb=(DCB*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DCB)); // Выделение области памяти для DCB из кучи и заполнение этой области нулями.
  dcb.DCBlength=sizeof(DCB);
 
  if(!GetCommState(COMport, &dcb)) // Эта функция заполняет DCB информацией о текущем состоянии устройства, точнее о его настройках.
  {
  // Если не удалось - закрыть порт и вывести сообщение об ошибке в строке состояния.
//  HeapFree(GetProcessHeap(),0,dcb); // Освобождение памяти из кучи.
    CloseHandle(COMport);
    Panel1->Font->Color = clRed;
    Panel1->Caption = "Не удалось считать DCB";
    return;
  }
 
  // Инициализация структуры DCB.
  dcb.BaudRate = StrToInt(Form1->ComboBox2->Text); //задаём скорость передачи 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(COMport, &dcb))
  {// Если не удалось - закрыть порт и вывести сообщение об ошибке в строке состояния.
//  HeapFree(GetProcessHeap(),0,dcb); // Освобождение памяти из кучи.
    CloseHandle(COMport);
    Panel1->Font->Color = clRed;
    Panel1->Caption = "Не удалось установить DCB.";
    return;
  }
 
  // Установка таймаутов.
  timeouts.ReadIntervalTimeout = 0;     // таймаут между двумя символами
  timeouts.ReadTotalTimeoutMultiplier = 0;  // общий таймаут операции чтения
  timeouts.ReadTotalTimeoutConstant = 0;    // константа для общего таймаута операции чтения
  timeouts.WriteTotalTimeoutMultiplier = 0; // общий таймаут операции записи
  timeouts.WriteTotalTimeoutConstant = 0;   // константа для общего таймаута операции записи
 
  // Загрузить структуру таймаутов в порт.
  if(!SetCommTimeouts(COMport, &timeouts))
  {// Если не удалось - закрыть порт и вывести сообщение об ошибке в строке состояния.
    CloseHandle(COMport);
    Panel1->Font->Color = clRed;
    Panel1->Caption = "Не удалось установить тайм-ауты.";
    return;
  }
 
  // Установить размеры очередей приёма и передачи
  SetupComm(COMport,2000,2000);
 
  PurgeComm(COMport,PURGE_RXCLEAR); // Очистка буферов порта.
 
  Button1->Enabled = false;
  Button2->Enabled = true;
 
  // Создание потоков на WINAPI:
 
  // Cоздаём поток чтения, который сразу начнёт выполняться (предпоследний параметр = 0).
  reader = CreateThread(NULL, 0, ReadThread, NULL, 0, NULL);
 
  // Cоздаём поток записи в остановленном состоянии (предпоследний параметр = CREATE_SUSPENDED).
  writer = CreateThread(NULL, 0, WriteThread, NULL, CREATE_SUSPENDED, NULL);
 
  counterRX = 0;
}
//---------------------------------------------------------------------------
// завершение по закрытию формы
 
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
  if(writer)
  {
    TerminateThread(writer,0);
    CloseHandle(overlappedwr.hEvent);   //нужно закрыть объект-событие
    CloseHandle(writer);
  }
  //завершить поток чтения из порта, проверка if(reader) обязательна, иначе возникают ошибки
  //if(reader) reader->Terminate();
  //завершить поток записи в порт, проверка if(writer) обязательна, иначе возникают ошибки
//  if(writer)writer->Terminate();
  if(COMport) CloseHandle(COMport);  //закрыть порт
//  if(handle) close(handle);      //закрыть файл, в который велась запись принимаемых данных
 
  if(reader)
  {
    TerminateThread(reader,0);
    CloseHandle(overlappedwr.hEvent);   //нужно закрыть объект-событие
    CloseHandle(reader);
  }
 
}
//---------------------------------------------------------------------------
// передача данных 
 
void __fastcall TForm1::Button2Click(TObject *Sender)
{
  memset(bufwr,0,BUFSIZE); //очистить программный передающий буфер,
    //чтобы данные не накладывались друг на друга
  PurgeComm(COMport, PURGE_TXCLEAR);            //очистить передающий буфер порта
  strcpy(bufwr,Form1->Edit1->Text.c_str());     //занести в программный передающий буфер строку из Edit1
 
  ResumeThread(writer);               //активировать поток записи данных в порт
}
//---------------------------------------------------------------------------
Но ничего не работает ни на передачу ни на прием. Хотя порт по нажатию Button1 открывается.
Подскажите пожалуйста что в коде не так. Может кто сталкивался буду признателен за код рабочих функций приема и передачи по Com в асинхронном режиме.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
12.10.2016, 11:07
Ответы с готовыми решениями:

COM-порт в асинхронном режиме
Настраиваю COM-порт для работы в асинхронном режиме с использованием API. К порту подключаю RS-232 переходник и смотрю сигналы на выводах....

Работа с COM-портом в асинхронном режиме
Пробую разобраться с работой COM порта. Получилось запустить в синхронном режиме. Стало ясно, что в этом режиме, вызывая функцию чтения...

Не работает 32к кварц в асинхронном режиме таймера
ATmega8A, таймер2 настроил на счет от внешнего кварца (32к с кондерами 22пФ): ASSR = 1&lt;&lt;AS2; /* XTAL (32k...

20
-13 / 6 / 6
Регистрация: 04.08.2015
Сообщений: 622
14.10.2016, 17:28  [ТС]
Прием заработал. Подскажите пожалуйста как правильно сделать передачу в нужное время.
Поскольку принимаются данные побайтно
C++
1
2
3
4
5
6
          if(btr)                                   // если действительно есть байты для чтения
          {
            ReadFile(COMport, bufrd, btr, &temp, &overlapped); // прочитать байты из порта в буфер программы
            counterRX+=btr;                                      // увеличиваем счётчик байтов
            ReadPrinting(btr);                                    // вызываем функцию для вывода данных на экран и в файл
          }
то заранее неизвестно когда будет принят непрерывный пакет данных.
А передать данные обратно нужно только после приема непрерывного пакета данных. Данных в пакете каждый раз может быть разное количество.
Подскажите пожалуйста как обнаружить окончание приема пакета?
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
15.10.2016, 16:32
Цитата Сообщение от VlGuvin Посмотреть сообщение
Подскажите пожалуйста как обнаружить окончание приема пакета?
Почитать документацию устройства про протоколу обмена, посмотреть как там задается количество данных.

Не по теме:

На заметку, если интересно мой велосипед, только у меня чтение/запись по таймаутам:
https://www.cyberforum.ru/blog... g4416.html
https://github.com/Avazart/Bic... Serial.cpp

0
-13 / 6 / 6
Регистрация: 04.08.2015
Сообщений: 622
16.10.2016, 20:07  [ТС]
При чем тут устройство? Каждую секунду на порт приходит различное количество байт (непрерывный пакет). В асинхронном режиме порт принимает данные побайтно (хотя аппаратно почему-то по 8 байт). Да, если в пакете имеются синхросимволы или фреймы с синхросимволами то можно просто ловить их и определять примерно время заполнение буфера данными. Но вопрос в том, как программно не имея в принимаемом пакете синхросимволов или фреймов с синхросимволами определить окончание приема непрерывного пакета данных (непрерывной последовательности байт)?
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
16.10.2016, 20:25
Цитата Сообщение от VlGuvin Посмотреть сообщение
При чем тут устройство?
А включить мозг и подумать?
Обмен данными и логика работы может сильно отличатся. Все это зависит от протокола обмена.

Цитата Сообщение от VlGuvin Посмотреть сообщение
Но вопрос в том, как программно не имея в принимаемом пакете синхросимволов или фреймов с синхросимволами определить окончание приема непрерывного пакета данных (непрерывной последовательности байт)?
Разложить карты, кинуть кости , заглянуть в стеклянный шар ?

P.S.: И вообще логика страдала сильно... если поток непрерывный, то о каком окончании может быть речь?
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
16.10.2016, 20:25
VlGuvin, буквально сегодня реализовал у себя то, что надо тебе. Вот код приема:
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
 DWORD dw;
 HANDLE COMPort;
 DCB dcb;
 COMSTAT COMState;
 
 ...
 
 // ПОЛУЧЕНИЕ ОТВЕТА ------------------------------------------------------------
 for(DWORD in = 0, vl = 0, st = GetTickCount();;)                              //
  {                                                                            //
   Sleep(10000 / dcb.BaudRate);                                                //
                                                                               //
   if(ClearCommError(COMPort, &dw, &COMState) && !dw && COMState.cbInQue > in) //
    {                                                                          //
     in = COMState.cbInQue;                                                    //
     vl = 0;                                                                   //
     continue;                                                                 //
    }                                                                          //
                                                                               //
   if((!in && ((GetTickCount() - st) > 3000)) || (in && ++vl > 1))             //
    {                                                                          //
     Data.resize(COMState.cbInQue);                                            //
     if(Data.size() &&                                                         //
        (!ReadFile(COMPort, &Data.front(), Data.size(), &dw, NULL) ||          //
        dw != Data.size()))                                                    //
       throw L"Не удается прочитать ответ из COM порта!";                      //
     break;                                                                     //
    }                                                                          //
  }                                                                            //
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
16.10.2016, 20:31
d7d1cd, Честно - кривое решение, есть же OVERLAPPED для таких целей.
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
16.10.2016, 20:34
OVERLAPPED это когда COM порт работает в асинхронном режиме? Уточните, в чем кривизна моего решения?
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
16.10.2016, 20:39
Цитата Сообщение от d7d1cd Посмотреть сообщение
Уточните, в чем кривизна моего решения?
Синхронный режим, цикл, замеры времени, слип, т.е все.

Цитата Сообщение от d7d1cd Посмотреть сообщение
OVERLAPPED это когда COM порт работает в асинхронном режиме?
OVERLAPPED это использование "перекрываемых операций".
Т.е использование объекта синхронизация "событие" ф-ций ожидания WaitForXXX() для ожидания данных.
Используя OVERLAPPED можно достигнуть чтения с отработкой по таймаутам.
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
16.10.2016, 20:47
Avazart, тогда покажите пример на конкретную задачу, ради которой я написал кривой, по Вашему, код. Задача такая. Устройству через COM порт отправляется запрос. Длина ответа от устройства, согласно протоколу обмена, может быть от 5 до 255 байт. То есть, заранее определить сколько устройство пришлет байт в ответ, невозможно. Причем связь может быть прервана и устройство вообще ничего не пришлет. Ждем Вашего решения.
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
16.10.2016, 20:59
Цитата Сообщение от d7d1cd Посмотреть сообщение
Avazart, тогда покажите пример на конкретную задачу, ради которой я написал кривой, по Вашему, код.
Кривой код для кривых задач?
Вообще я думаю он ни на что не годится.

Цитата Сообщение от d7d1cd Посмотреть сообщение
Длина ответа от устройства, согласно протоколу обмена, может быть от 5 до 255 байт. То есть, заранее определить сколько устройство пришлет байт в ответ, невозможно. Причем связь может быть прервана и устройство вообще ничего не пришлет. Ждем Вашего решения.
Решение - уволить разработчика протокола обмена(устройства) и нанять нового.

Ибо по нормальному должно использоваться что-то из:
  1. Последовательность стоп-битов.
  2. Фиксированный размер.
  3. Заголовок в котором указано последующее кол-во символов
  4. Какие-то временные рамки в которые должна уложится передача(что хуже других вариантов)
  5. Комбинации перечисленного.
  6. Что-то еще что позволяет определить конец (и отличить его от подвисания устройства)
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
16.10.2016, 21:01
Цитата Сообщение от Avazart Посмотреть сообщение
Решение - уволить разработчика протокола обмена и нанять нового.
Нет у нас такой власти, чтобы увольнять. Тем более людей из других организаций...
Я привел решение по поставленному вопросу. Пусть оно кривое, на Ваш взгляд, но оно справляется с поставленной задачей. От Вас будет решение, кроме увольнения разработчика?
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
16.10.2016, 21:03
Цитата Сообщение от d7d1cd Посмотреть сообщение
Нет у нас такой власти, чтобы увольнять. Тем более людей из других организаций...
Тогда стоит самому уволится.

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

Цитата Сообщение от d7d1cd Посмотреть сообщение
Я привел решение по поставленному вопросу. Пусть оно кривое, на Ваш взгляд, но оно справляется с поставленной задачей. От
Это не решение а откровенный быдлокод, на что я мягко намекал.
И его быдлокодность абсолютно не имеет никакого отношения к обсуждаемому вопросу.
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
16.10.2016, 21:16
Цитата Сообщение от Avazart Посмотреть сообщение
Тогда стоит самому уволится.
Avazart, если бы Вам принесли устройство с таким протоколом обмена (реально таким протоколом, а не "правильным", но недочитанным) и дали задание написать программу, то Вы бы уволились?
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
16.10.2016, 21:46
Цитата Сообщение от d7d1cd Посмотреть сообщение
Avazart, если бы Вам принесли устройство с таким протоколом обмена (реально таким протоколом, а не "правильным", но недочитанным) и дали задание написать программу, то Вы бы уволились?
А если бы вам дали лопату с не обработанным черенком и погнутым тупым полотном, и сказали копай яму что бы вы делали?
Мучались и копали?

Но в данному случае кривизна лопаты видимо совпала с руками растущими ....
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
16.10.2016, 22:05
Цитата Сообщение от Avazart Посмотреть сообщение
А если бы вам дали лопату с не обработанным черенком и погнутым тупым полотном, и сказали копай яму что бы вы делали? Мучались и копали?
Вы сначала ответьте на вопрос, прежде чем свой задавать. Или подобная задача не имеет решения, кроме как через быдлокод, но для Вас, как существа очевидно приближенного к Богу программирования, подобный путь совершенно неприемлем, а искать другой ниже Вашего достоинства?

Цитата Сообщение от Avazart Посмотреть сообщение
Но в данному случае кривизна лопаты видимо совпала с руками растущими...
Ну да... Что еще можно ожидать от Avazart (неоднократно замечено), кроме как хамства.
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
16.10.2016, 22:13
Цитата Сообщение от d7d1cd Посмотреть сообщение
Или подобная задача не имеет решения, кроме как через быдлокод,
Еще раз повторю
Цитата Сообщение от Avazart Посмотреть сообщение
Это не решение а откровенный быдлокод, на что я мягко намекал.
И его быдлокодность абсолютно не имеет никакого отношения к обсуждаемому вопросу.
Я четко указал на проблемы вашего кода, и никакого отношения к протоколу, концу передачи, постановке задачи не имеют.
Цитата Сообщение от d7d1cd Посмотреть сообщение
Ну да... Что еще можно ожидать от Avazart (неоднократно замечено), кроме как хамства.
А чего вы ожидали в ответ на невежество? Поощрения? Ну.. я не ваша мама
0
-13 / 6 / 6
Регистрация: 04.08.2015
Сообщений: 622
16.10.2016, 22:31  [ТС]
буквально сегодня реализовал у себя то, что надо тебе.
Может решение и неплохое. Но реализовано для чтения в синхронном режиме. Думаю при неизвестном количестве приходящих байт читать порт нужно в асинхронном режиме, тоесть с использованием OVERLAPPED. Так я и попытался реализовать. Код работает. Но при разном количестве приходящих байт от 800 до 4800 затруднительно 1. точно подсчитать количество приходящих байт 2. точно определить момент окончания приема непрерывного потока байт (непрерывный поток поступает с периодом в 1 сек) для того, чтобы знать момент начала передачи ответа (связь по одному проводу - (полудуплекс - rs485)). Если кто реализовывал код представленный в http://piclist.ru/S-COM-THREAD... D-RUS.html то должны были возникнуть эти же проблемы. Кому удалось написать код приема по com в асинхронном режиме где решены эти две проблемы откликнитесь please.
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
16.10.2016, 22:42
Цитата Сообщение от VlGuvin Посмотреть сообщение
Может решение и неплохое. Но реализовано для чтения в синхронном режиме.
Где-то в википедии говорится что использовать синх. режим плохо, и объясняются почему (чет не найду сходу)

Добавлено через 1 минуту
Цитата Сообщение от VlGuvin Посмотреть сообщение
сли кто реализовывал код представленный в http://piclist.ru/S-COM-THREAD... D-RUS.html то должны были возникнуть эти же проблемы.
Ну я видел этот код раньше, как и много других примеров из интернета там много спорных моментов, в частности многопоточности.

Цитата Сообщение от VlGuvin Посмотреть сообщение
Кому удалось написать код приема по com в асинхронном режиме где решены эти две проблемы откликнитесь please.
Если не заметили я приводил выше ссылки на github на мою реализацию думаю с минимальными правками можно заставить его работать под C++Builder6

Цитата Сообщение от VlGuvin Посмотреть сообщение
для того, чтобы знать момент начала передачи ответа (связь по одному проводу - (полудуплекс - rs485)).
Т.е. только чтение с порта?
0
-13 / 6 / 6
Регистрация: 04.08.2015
Сообщений: 622
17.10.2016, 16:55  [ТС]
Нет. Прием затем ответ. Интерфейс rs485 предполагает обязательный адаптер или преобразователь в rs232. Полудуплекс это значит прием и передача обязательно разделены во времени. Полный дуплекс когда передачу ответа можно вести одновременно с приемом. Это rs232 или rs422.
Вобщем один раз в секунду сначала прием 800...4800 (скорость 115200) байт затем сразу после получения всех содержащихся в одном непрерывном пакете байт - ответ 128 байт.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
17.10.2016, 16:55
Помогаю со студенческими работами здесь

ADO в асинхронном режиме.
Ну вот, и я решил задать вопрос, может кто-то натолкнет на мысль. Суть непонятки в следующем: while...

Проблема работы COM- в асинхронном режиме
Задача написать WPF приложение, работающее с пулом COM-портов, к которым подключены модемы. Вначале выбирается свободный модем: ...

Таймер Т2 в асинхронном режиме, Атмега8
Здравствуйте, сил нет и мысли кончились. Простите за такую преамбулу. Делаю простой и незатейливый код на Атмеге8, для начала просто...

Записать данные в файл в асинхронном режиме
Добрый день. Подскажите как записать данные в файл в асинхронном режиме.

Выполнение запроса к БД MSSQL в асинхронном режиме
Вопрос такой : в PHP 5 при использовании драйверов ODBC по неизвестной причине запрос типа 'SELECT * FROM ...' выполняется асинхронно, а...


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

Или воспользуйтесь поиском по форуму:
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