Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.77/26: Рейтинг темы: голосов - 26, средняя оценка - 4.77
17 / 17 / 5
Регистрация: 19.09.2012
Сообщений: 216

Баг в работе с COM портом

08.02.2013, 00:49. Показов 5948. Ответов 38
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток всем, что-то я зачастил сюда Собственно нашел баг в программе и никак не могу его исправить, как я только не крутил таймауты, не выходит убрать... Собственно ближе к делу...
Код открытия порта:
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
void COMOpen()
{
 char* portname;         //имя порта (например, "COM1", "COM2" и т.д.)
 DCB dcb;                //структура для общей инициализации порта DCB
 COMMTIMEOUTS timeouts;  //структура для установки таймаутов
 
 portname = Form1->ComboBox1->Text.t_str(); //получить имя выбранного порта
 
 //открыть порт, для асинхронных операций обязательно нужно указать флаг FILE_FLAG_OVERLAPPED
 COMport = CreateFile(portname,GENERIC_READ | GENERIC_WRITE,0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
 
 if(COMport == INVALID_HANDLE_VALUE)            //если ошибка открытия порта
  {
   Form1->Memo1->Lines->Add("Не удалось открыть порт");       //вывести сообщение в строке состояния
   return;
  }
 
 //инициализация порта
 
 dcb.DCBlength = sizeof(DCB);   //в первое поле структуры DCB необходимо занести её длину, она будет использоваться функциями настройки порта для контроля корректности структуры
 
 //считать структуру DCB из порта
 if(!GetCommState(COMport, &dcb))   //если не удалось - закрыть порт и вывести сообщение об ошибке в строке состояния
  {
   COMClose();
   Form1->Memo1->Lines->Add("Не удалось считать DCB");
   return;
  }
 
 //инициализация структуры DCB
 dcb.BaudRate = StrToInt(Form1->ComboBox2->Text);       //задаём скорость передачи
 dcb.fBinary = TRUE;                                    //включаем двоичный режим обмена
 dcb.fOutxCtsFlow = FALSE;                              //выключаем режим слежения за сигналом CTS
 dcb.fOutxDsrFlow = FALSE;                              //выключаем режим слежения за сигналом DSR
 dcb.fDtrControl = DTR_CONTROL_ENABLE;                 //отключаем использование линии DTR
 dcb.fDsrSensitivity = FALSE;                           //отключаем восприимчивость драйвера к состоянию линии DSR
 dcb.fNull = FALSE;                                     //разрешить приём нулевых байтов
 dcb.fRtsControl = RTS_CONTROL_DISABLE;                 //отключаем использование линии RTS
 dcb.fAbortOnError = TRUE;                             //отключаем остановку всех операций чтения/записи при ошибке
 dcb.ByteSize = 8;                                      //задаём число бит в байте
 dcb.Parity = 0;                                        //отключаем проверку чётности
 dcb.StopBits = 0;                                      //задаём один стоп-бит
 
 //загрузить структуру DCB в порт
 if(!SetCommState(COMport, &dcb))   //если не удалось - закрыть порт и вывести сообщение об ошибке в строке состояния
  {
   COMClose();
   Form1->Memo1->Lines->Add("Не удалось установить DCB");
   return;
  }
 
 //установить таймауты
 timeouts.ReadIntervalTimeout = 10;     //таймаут между двумя символами
 timeouts.ReadTotalTimeoutMultiplier = 10;  //общий таймаут операции чтения
 timeouts.ReadTotalTimeoutConstant = 10;         //константа для общего таймаута операции чтения
 timeouts.WriteTotalTimeoutMultiplier = 10;      //общий таймаут операции записи
 timeouts.WriteTotalTimeoutConstant = 10;        //константа для общего таймаута операции записи
 
 //записать структуру таймаутов в порт
 if(!SetCommTimeouts(COMport, &timeouts))   //если не удалось - закрыть порт и вывести сообщение об ошибке в строке состояния
  {
   COMClose();
   Form1->Memo1->Lines->Add("Не удалось установить тайм-ауты");
   return;
  }
 
 //установить размеры очередей приёма и передачи
 SetupComm(COMport,4000,4000);
 
 PurgeComm(COMport, PURGE_RXCLEAR); //очистить принимающий буфер порта
 
 reader = CreateThread(NULL, 0, ReadThread, NULL, 0, NULL);     //создаём поток чтения, который сразу начнёт выполняться (предпоследний параметр = 0)
 
 Form1->Memo1->Lines->Add("Порт открыт");
 
}
Функция приема данных и функция вывода
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
void ReadPrinting()
{
 AnsiString answer = AnsiString((char *)bufrd);
 Form1->Memo1->Lines->Add("Ответ: " + answer);
 
 memset(bufrd, 0, BUFSIZE);                  //очистить буфер (чтобы данные не накладывались друг на друга)
 PurgeComm(COMport, PURGE_RXCLEAR);
 }
//---------------------------------------------------------------------------
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)                                                       //пока поток не будет прерван, выполняем цикл
  {
   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)                                                 //если действительно есть байты для чтения
        {
         memset(bufrd, 0, BUFSIZE);
         ReadFile(COMport, bufrd, btr, &temp, &overlapped);     //прочитать байты из порта в буфер программы
         counter+=btr;                                          //увеличиваем счётчик байтов
         ReadPrinting();                                        //вызываем функцию для вывода данных на экран и в файл
        }
       }
    }
  }
}
Теперь сама проблема... Заметил неприятный баг: код может выводить данные как полностью правильно, так и кусками... например: правильно -
C++
1
Ответ: я!0117010D00000000570400570400D0070000000000000ADE2
, неправильно
C++
1
Ответ: я!0117010D0000000057040057040 Ответ: 0D0070000000000000ADE2
Как бы избавиться от этой заразы ? По началу вообще не замечал этого, но когда начали появляться ошибки при обработке, стал копать и попал сюда

Добавлено через 1 час 1 минуту
Он непонятно из-за чего может считать кусками... причем изменение таймаутов почему-то не влияет, а может считать и все верно... Причем последовательности в ошибках нет, каждый раз по разному...
1
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
08.02.2013, 00:49
Ответы с готовыми решениями:

Информация по работе с Com-портом.
Всем привет! Народ, дайте ссылку(ки) на инфу по работе с СОМ портом.(интерфейсы, методы...) а то я немного запутался, лазяя по...

Ошибка в работе службы с com-портом
Разработал программу-библиотеки, которые работают с com-портом. Запускаю как desktop - все отлично. Запускаю как Windows Service - ошибки...

Общие вопросы по работе с COM-портом
У меня Win7. На системе классический встроенный последовательный порт и Usb преобразователь (FTDI). Если посмотреть параметры порта из...

38
 Аватар для Kulgar
511 / 196 / 26
Регистрация: 07.08.2013
Сообщений: 814
29.11.2013, 17:30
Студворк — интернет-сервис помощи студентам
Димитрий, попробуйте использовать предложенный мною вариант.
1
 Аватар для Димитрий
0 / 0 / 0
Регистрация: 06.07.2008
Сообщений: 32
29.11.2013, 17:49
Сейчас попробую. Если не трудно объяснить мат часть не могу найти описания Terminated.
C++
1
while(!Terminated)                     //пока поток не будет прерван, выполняем цикл
Добавлено через 7 минут
C++
1
bufrd_TMP+=(char*)bufrd;
и ещё вопрос а разве данные хоронящиеся в буфере не будут дублироваться повторно при следующем событии?
0
 Аватар для Kulgar
511 / 196 / 26
Регистрация: 07.08.2013
Сообщений: 814
29.11.2013, 17:56
Цитата Сообщение от Димитрий Посмотреть сообщение
и ещё вопрос а разве данные хоронящиеся в буфере не будут дублироваться повторно при следующем событии?
Не будут дублироваться. За это отвечает Synchronize:
C++
1
2
3
4
5
6
                if(btr)                                     //если действительно есть байты для чтения
                {
                    ReadFile(COMport, bufrd, btr, &temp, &overlapped);     //прочитать байты из порта в буфер программы
                    counter+=btr;                                          //увеличиваем счётчик байтов
                    Synchronize(Printing);                              //вызываем функцию для вывода данных на экран и в файл
                }
1
 Аватар для Димитрий
0 / 0 / 0
Регистрация: 06.07.2008
Сообщений: 32
29.11.2013, 18:14
Synchronize как правильно её вызвать откуда она?
0
 Аватар для Kulgar
511 / 196 / 26
Регистрация: 07.08.2013
Сообщений: 814
02.12.2013, 09:14
Димитрий, класс TThread. Я в 9м посте приводил ссылку на другую тему. Обратите внимание на статью Работа с COM-портом с помощью потоков.
1
 Аватар для Димитрий
0 / 0 / 0
Регистрация: 06.07.2008
Сообщений: 32
02.12.2013, 17:53
Я уже разобрался и переписываю свою программу с использования классов.
0
 Аватар для Димитрий
0 / 0 / 0
Регистрация: 06.07.2008
Сообщений: 32
04.12.2013, 18:12
Переписал но теперь при активации потока записи в порт возникает ошибка Access violation at address
C++
1
2
3
4
5
6
7
8
9
10
void Getis(int as)
{
 char a[2];
 memset(bufwr,0,BUFSIZE);
 PurgeComm(COMport, PURGE_TXCLEAR);         
 a[0] = as + '0';
 a[1] = 0;
 strcpy(bufwr,a);                             
 writer->Resume();                          //а здесь возникает ошибка
 }
Я всего хочу послать в порт цифру 2 раньше посылал правда без Resume
0
91 / 91 / 22
Регистрация: 02.07.2013
Сообщений: 332
04.12.2013, 22:03
Локальный буфер char a[2] умирает после выхода из функции. Сделать static или глобальным.
1
 Аватар для Димитрий
0 / 0 / 0
Регистрация: 06.07.2008
Сообщений: 32
05.12.2013, 15:10
Попробовал сделать глобальной, а потом переделал так
C++
1
2
 if(as == 1) static char a = '1';
 if(as == 2) static char a = '2';
результат не меняется ошибка та же.
0
91 / 91 / 22
Регистрация: 02.07.2013
Сообщений: 332
05.12.2013, 15:23
Про буфер я, конечно, загнул с недосыпу. Что есть bufwr? И как объявлен writer?
0
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906
05.12.2013, 15:31
Цитата Сообщение от Димитрий Посмотреть сообщение
возникает ошибка Access violation at address
Цитата Сообщение от Димитрий Посмотреть сообщение
//а здесь возникает ошибка
Ну значит в методе Resume() объекта writer и надо глядеть.
1
 Аватар для Димитрий
0 / 0 / 0
Регистрация: 06.07.2008
Сообщений: 32
05.12.2013, 15:43
#define BUFSIZE 128
unsigned char bufrd[BUFSIZE], bufwr[BUFSIZE]; //приёмный и передающий буферы
WriteThread *writer; //объект потока WriteThread

Добавлено через 8 минут
Resume() есть одна из методов класса TThread
0
91 / 91 / 22
Регистрация: 02.07.2013
Сообщений: 332
05.12.2013, 15:46
А writer где-нибудь суспендится? Resume видно, а где Suspend?
1
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906
05.12.2013, 15:52
Цитата Сообщение от c0rvax Посмотреть сообщение
Resume видно, а где Suspend?
Димитрий, весь Execute() показывайте.
1
 Аватар для Димитрий
0 / 0 / 0
Регистрация: 06.07.2008
Сообщений: 32
05.12.2013, 15:57
Вот почти вся прога
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
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
#pragma hdrstop
#include <vcl.h>
#include "Formas.h"
#include <vcl/dstring.h>
#include <io.h>         //äëÿ ðàáîòû ñ ôàéëàìè
#include <fcntl.h>      //äëÿ ðàáîòû ñ ôàéëàìè
#include <sys\stat.h>   //äëÿ ðàáîòû ñ ôàéëàìè
#include <windows.h>
//---------------------------------------------------------------------------
 
#pragma package(smart_init)
//=============================================================================
//..................... îáúÿâëåíèÿ ãëîáàëüíûõ ïåðåìåííûõ ......................
//=============================================================================
extern int Status;
extern int fuseH;
extern int fuseL;
extern int fuseS;
#define BUFSIZE 128     //¸ìêîñòü áóôåðà
 
extern unsigned char bufrd[BUFSIZE], bufwr[BUFSIZE]; //ïðè¸ìíûé è ïåðåäàþùèé áóôåðû
AnsiString CompletePackage="",bufrd_TMP="";//ñòðîêè äëÿ ïàðñåðà ïðèíèìàåìûõ äàííûõ
 char a[2];
//---------------------------------------------------------------------------
 
extern HANDLE COMport;      //äåñêðèïòîð ïîðòà
 
//ñòðóêòóðà OVERLAPPED íåîáõîäèìà äëÿ àñèíõðîííûõ îïåðàöèé, ïðè ýòîì äëÿ îïåðàöèè ÷òåíèÿ è çàïèñè íóæíî îáúÿâèòü ðàçíûå ñòðóêòóðû
//ýòè ñòðóêòóðû íåîáõîäèìî îáúÿâèòü ãëîáàëüíî, èíà÷å ïðîãðàììà íå áóäåò ðàáîòàòü ïðàâèëüíî
extern OVERLAPPED overlapped;       //áóäåì èñïîëüçîâàòü äëÿ îïåðàöèé ÷òåíèÿ (ñì. ïîòîê ReadThread)
extern OVERLAPPED overlappedwr;         //áóäåì èñïîëüçîâàòü äëÿ îïåðàöèé çàïèñè (ñì. ïîòîê WriteThread)
//---------------------------------------------------------------------------
//extern int handle;                //äåñêðèïòîð äëÿ ðàáîòû ñ ôàéëîì ñ ïîìîùüþ áèáëèîòåêè <io.h>
//---------------------------------------------------------------------------
 
extern bool fl=0;   //ôëàã, óêàçûâàþùèé íà óñïåøíîñòü îïåðàöèé çàïèñè (1 - óñïåøíî, 0 - íå óñïåøíî)
 
extern unsigned long counter;   //ñ÷¸ò÷èê ïðèíÿòûõ áàéòîâ, îáíóëÿåòñÿ ïðè êàæäîì îòêðûòèè ïîðòà
 
//=============================================================================
//.............................. îáúÿâëåíèÿ ôóíêöèé ...........................
//=============================================================================
 
//extern void COMOpen(void);             //îòêðûòü ïîðò
//extern void COMClose(void);            //çàêðûòü ïîðò
 
//=============================================================================
//.............................. ðåàëèçàöèÿ ïîòîêîâ ...........................
//=============================================================================
 //ïîòîê äëÿ ÷òåíèÿ ïîñëåäîâàòåëüíîñòè áàéòîâ èç COM-ïîðòà â áóôåð
class ReadThread : public TThread
{
 private:
        void __fastcall Printing(); //âûâîä ïðèíÿòûõ áàéòîâ íà ýêðàí è â ôàéë
 protected:
        void __fastcall Execute();  //îñíîâíàÿ ôóíêöèÿ ïîòîêà
        //void __fastcall Synchronize();
 public:
        __fastcall ReadThread(bool CreateSuspended);    //êîíñòðóêòîð ïîòîêà
};
//---------------------------------------------------------------------------
 
//ïîòîê äëÿ çàïèñè ïîñëåäîâàòåëüíîñòè áàéòîâ èç áóôåðà â COM-ïîðò
class WriteThread : public TThread
{
private:
    void __fastcall Printing(); //âûâîä ñîñòîÿíèÿ íà ýêðàí
protected:
        void __fastcall Execute();      //îñíîâíàÿ ôóíêöèÿ ïîòîêà
        //void __fastcall Synchronize();
public:
        __fastcall WriteThread(bool CreateSuspended);   //êîíñòðóêòîð ïîòîêà
};  //*/
 
 
//-----------------------------------------------------------------------------
//............................... ïîòîê ReadThead .............................
//-----------------------------------------------------------------------------
 
ReadThread *reader;     //îáúåêò ïîòîêà ReadThread
 
//---------------------------------------------------------------------------
 
//êîíñòðóêòîð ïîòîêà ReadThread, ïî óìîë÷àíèþ ïóñòîé
__fastcall ReadThread::ReadThread(bool CreateSuspended) : TThread(CreateSuspended)
{}
 
//---------------------------------------------------------------------------
 
//ãëàâíàÿ ôóíêöèÿ ïîòîêà, ðåàëèçóåò ïðè¸ì áàéòîâ èç COM-ïîðòà
void __fastcall ReadThread::Execute()
{
 COMSTAT comstat;       //ñòðóêòóðà òåêóùåãî ñîñòîÿíèÿ ïîðòà, â äàííîé ïðîãðàììå èñïîëüçóåòñÿ äëÿ îïðåäåëåíèÿ êîëè÷åñòâà ïðèíÿòûõ â ïîðò áàéòîâ
 DWORD btr, temp, mask, signal; //ïåðåìåííàÿ temp èñïîëüçóåòñÿ â êà÷åñòâå çàãëóøêè
 
 overlapped.hEvent = CreateEvent(NULL, true, true, NULL);   //ñîçäàòü ñèãíàëüíûé îáúåêò-ñîáûòèå äëÿ àñèíõðîííûõ îïåðàöèé
 SetCommMask(COMport, EV_RXCHAR);                               //óñòàíîâèòü ìàñêó íà ñðàáàòûâàíèå ïî ñîáûòèþ ïðè¸ìà áàéòà â ïîðò
 while(!Terminated)                     //ïîêà ïîòîê íå áóäåò ïðåðâàí, âûïîëíÿåì öèêë
  {
   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);     //ïðî÷èòàòü áàéòû èç ïîðòà â áóôåð ïðîãðàììû
         counter+=btr;                                          //óâåëè÷èâàåì ñ÷¸ò÷èê áàéòîâ
         Synchronize(Printing);                             //âûçûâàåì ôóíêöèþ äëÿ âûâîäà äàííûõ íà ýêðàí è â ôàéë
        }
       }
    }
  }
 CloseHandle(overlapped.hEvent);        //ïåðåä âûõîäîì èç ïîòîêà çàêðûòü îáúåêò-ñîáûòèå
}
 
//---------------------------------------------------------------------------
 
//âûâîäèì ïðèíÿòûå áàéòû íà ýêðàí è â ôàéë (åñëè âêëþ÷åíî)
void __fastcall ReadThread::Printing()
{
bufrd_TMP+=(char*)bufrd;
for (int j=1;j<bufrd_TMP.Length();j++)
    if (bufrd_TMP.SubString(j,1)=="$")
    {
        CompletePackage=bufrd_TMP.SubString(1,j-1);//???????? ?????? ?????
        bufrd_TMP=bufrd_TMP.SubString(j,bufrd_TMP.Length());//??????? ???????????? ? bufrd_TMP
        break;
    }
 Form1->Memo1->Lines->Add((char*)bufrd);    //âûâîäèì ïðèíÿòóþ ñòðîêó â Memo
 Form1->StatusBar1->Panels->Items[2]->Text = "Âñåãî ïðèíÿòî " + IntToStr(counter) + " áàéò";    //âûâîäèì ñ÷¸ò÷èê â ñòðîêå ñîñòîÿíèÿ
 memset(bufrd, 0, BUFSIZE);         //î÷èñòèòü áóôåð (÷òîáû äàííûå íå íàêëàäûâàëèñü äðóã íà äðóãà)
}
 
//---------------------------------------------------------------------------
 
//-----------------------------------------------------------------------------
//............................... ïîòîê WriteThead ............................
//-----------------------------------------------------------------------------
 
WriteThread *writer;     //îáúåêò ïîòîêà WriteThread
 
//---------------------------------------------------------------------------
 
//êîíñòðóêòîð ïîòîêà WriteThread, ïî óìîë÷àíèþ ïóñòîé
__fastcall WriteThread::WriteThread(bool CreateSuspended) : TThread(CreateSuspended)
{}
 
//---------------------------------------------------------------------------
 
//ãëàâíàÿ ôóíêöèÿ ïîòîêà, âûïîëíÿåò ïåðåäà÷ó áàéòîâ èç áóôåðà â COM-ïîðò
void __fastcall WriteThread::Execute()
{
 DWORD temp, signal;    //temp - ïåðåìåííàÿ-çàãëóøêà
 
 overlappedwr.hEvent = CreateEvent(NULL, true, true, NULL);       //ñîçäàòü ñîáûòèå
 
 while(!Terminated)     //ïîêà ïîòîê íå áóäåò çàâåðø¸í, âûïîëíÿòü öèêë
 {
  WriteFile(COMport, bufwr, strlen(bufwr), &temp, &overlappedwr);  //çàïèñàòü áàéòû â ïîðò (ïåðåêðûâàåìàÿ îïåðàöèÿ!)
  signal = WaitForSingleObject(overlappedwr.hEvent, INFINITE);    //ïðèîñòàíîâèòü ïîòîê, ïîêà íå çàâåðøèòñÿ ïåðåêðûâàåìàÿ îïåðàöèÿ WriteFile
  if((signal == WAIT_OBJECT_0) && (GetOverlappedResult(COMport, &overlappedwr, &temp, true))) fl = true; //åñëè îïåðàöèÿ çàâåðøèëàñü óñïåøíî, óñòàíîâèòü ñîîòâåòñòâóþùèé ôëàæîê
  else fl = false;
 
  Synchronize(Printing);    //âûâåñòè ñîñòîÿíèå îïåðàöèè â ñòðîêå ñîñòîÿíèÿ
  writer->Suspend();        //ïðèîñòàíîâèòü ïîòîê çàïèñè â ïîðò, ïîêà îí íå ïîòðåáóåòñÿ ñíîâà
 }
 CloseHandle(overlappedwr.hEvent);      //ïåðåä âûõîäîì èç ïîòîêà çàêðûòü îáúåêò-ñîáûòèå
}
 
//---------------------------------------------------------------------------
 
//âûâîä ñîñòîÿíèÿ ïåðåäà÷è äàííûõ íà ýêðàí
void __fastcall WriteThread::Printing()
{
 if(!fl)    //ïðîâåðÿåì ñîñòîÿíèå ôëàæêà
  {
   Form1->StatusBar1->Panels->Items[0]->Text  = "Îøèáêà ïåðåäà÷è";
   return;
  }
 Form1->StatusBar1->Panels->Items[0]->Text  = "Ïåðåäà÷à ïðîøëà óñïåøíî";
 
}
 
//---------------------------------------------------------------------------
 
/*/îáðàáîò÷èê íàæàòèÿ íà êíîïêó "Îòêðûòü ïîðò"
void __fastcall TForm1::SpeedButton1Click(TObject *Sender)
{
 if(SpeedButton1->Down)
  {
   COMOpen();                   //åñëè êíîïêà íàæàòà - îòêðûòü ïîðò
   counter = 0; //ñáðàñûâàåì ñ÷¸ò÷èê áàéòîâ
  }
 
 else
  {
   COMClose();                  //åñëè êíîïêà îòæàòà - çàêðûòü ïîðò
  }
} //*/
 
//---------------------------------------------------------------------------
 
//îáðàáîò÷èê çàêðûòèÿ ôîðìû
void CloseFormas(void)
{
 if(reader)reader->Terminate();     //çàâåðøèòü ïîòîê ÷òåíèÿ èç ïîðòà, ïðîâåðêà if(reader) îáÿçàòåëüíà, èíà÷å âîçíèêàþò îøèáêè
 if(writer)writer->Terminate();         //çàâåðøèòü ïîòîê çàïèñè â ïîðò, ïðîâåðêà if(writer) îáÿçàòåëüíà, èíà÷å âîçíèêàþò îøèáêè
 if(COMport)CloseHandle(COMport);       //çàêðûòü ïîðò
} //*/
 
//=============================================================================
//........................... ðåàëèçàöèè ôóíêöèé ..............................
//=============================================================================
 
//---------------------------------------------------------------------------
 
//ôóíêöèÿ îòêðûòèÿ è èíèöèàëèçàöèè ïîðòà
void COMOpen()
{
 String portname;        //èìÿ ïîðòà (íàïðèìåð, "COM1", "COM2" è ò.ä.)
 DCB dcb;                //ñòðóêòóðà äëÿ îáùåé èíèöèàëèçàöèè ïîðòà DCB
 COMMTIMEOUTS timeouts;  //ñòðóêòóðà äëÿ óñòàíîâêè òàéìàóòîâ
 
 portname = Form1->ComboBox1->Text; //ïîëó÷èòü èìÿ âûáðàííîãî ïîðòà
 
 //îòêðûòü ïîðò, äëÿ àñèíõðîííûõ îïåðàöèé îáÿçàòåëüíî íóæíî óêàçàòü ôëàã FILE_FLAG_OVERLAPPED
 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)            //åñëè îøèáêà îòêðûòèÿ ïîðòà
  {
   Form1->StatusBar1->Panels->Items[0]->Text = "Íå óäàëîñü îòêðûòü ïîðò";       //âûâåñòè ñîîáùåíèå â ñòðîêå ñîñòîÿíèÿ
   return;
  }
 
 //èíèöèàëèçàöèÿ ïîðòà
 
 dcb.DCBlength = sizeof(DCB);   //â ïåðâîå ïîëå ñòðóêòóðû DCB íåîáõîäèìî çàíåñòè å¸ äëèíó, îíà áóäåò èñïîëüçîâàòüñÿ ôóíêöèÿìè íàñòðîéêè ïîðòà äëÿ êîíòðîëÿ êîððåêòíîñòè ñòðóêòóðû
 
 //ñ÷èòàòü ñòðóêòóðó DCB èç ïîðòà
 if(!GetCommState(COMport, &dcb))   //åñëè íå óäàëîñü - çàêðûòü ïîðò è âûâåñòè ñîîáùåíèå îá îøèáêå â ñòðîêå ñîñòîÿíèÿ
  {
   COMClose();
   Form1->StatusBar1->Panels->Items[0]->Text  = "Íå óäàëîñü ñ÷èòàòü DCB";
   return;
  }
 
 //èíèöèàëèçàöèÿ ñòðóêòóðû DCB
 dcb.BaudRate = 9600;                                   //çàäà¸ì ñêîðîñòü ïåðåäà÷è 9600 áîä
 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))   //åñëè íå óäàëîñü - çàêðûòü ïîðò è âûâåñòè ñîîáùåíèå îá îøèáêå â ñòðîêå ñîñòîÿíèÿ
  {
   COMClose();
   Form1->StatusBar1->Panels->Items[0]->Text  = "Íå óäàëîñü óñòàíîâèòü DCB";
   return;
  }
 
 //óñòàíîâèòü òàéìàóòû
 timeouts.ReadIntervalTimeout = 0;      //òàéìàóò ìåæäó äâóìÿ ñèìâîëàìè
 timeouts.ReadTotalTimeoutMultiplier = 0;   //îáùèé òàéìàóò îïåðàöèè ÷òåíèÿ
 timeouts.ReadTotalTimeoutConstant = 0;         //êîíñòàíòà äëÿ îáùåãî òàéìàóòà îïåðàöèè ÷òåíèÿ
 timeouts.WriteTotalTimeoutMultiplier = 0;      //îáùèé òàéìàóò îïåðàöèè çàïèñè
 timeouts.WriteTotalTimeoutConstant = 0;        //êîíñòàíòà äëÿ îáùåãî òàéìàóòà îïåðàöèè çàïèñè
 
 //çàïèñàòü ñòðóêòóðó òàéìàóòîâ â ïîðò
 if(!SetCommTimeouts(COMport, &timeouts))   //åñëè íå óäàëîñü - çàêðûòü ïîðò è âûâåñòè ñîîáùåíèå îá îøèáêå â ñòðîêå ñîñòîÿíèÿ
  {
   COMClose();
   Form1->StatusBar1->Panels->Items[0]->Text  = "Íå óäàëîñü óñòàíîâèòü òàéì-àóòû";
   return;
  }
}
 
//---------------------------------------------------------------------------
 
//ôóíêöèÿ çàêðûòèÿ ïîðòà
void COMClose()
{
 //åñëè ïîòîê çàïèñè ñóùåñòâóåò, ïîäàòü åìó êîìàíäó íà çàâåðøåíèå è çàïóñòèòü åãî, ÷òîáû îí âûïîëíèë çàâåðøåíèå;
 if(writer) //ïðîâåðêà if(writer) îáÿçàòåëüíà, èíà÷å âîçíèêàþò îøèáêè;
  {
   writer->Terminate();
   writer->Resume();
  }
 
 if(reader)reader->Terminate();         //åñëè ïîòîê ÷òåíèÿ ðàáîòàåò, çàâåðøèòü åãî; ïðîâåðêà if(reader) îáÿçàòåëüíà, èíà÷å âîçíèêàþò îøèáêè
 CloseHandle(COMport);                  //çàêðûòü ïîðò
 COMport=0;             //îáíóëèòü ïåðåìåííóþ äëÿ äåñêðèïòîðà ïîðòà
}
 
//---------------------------------------------------------------------------
void Getis(int as)
{
 memset(bufwr,0,BUFSIZE);           //î÷èñòèòü ïðîãðàììíûé ïåðåäàþùèé áóôåð, ÷òîáû äàííûå íå íàêëàäûâàëèñü äðóã íà äðóãà
 PurgeComm(COMport, PURGE_TXCLEAR);             //î÷èñòèòü ïåðåäàþùèé áóôåð ïîðòà
 if(as == 1) static char a = '1';
 if(as == 2) static char a = '2';
 //a[0] = as + '0';
 //a[1] = 0;
 strcpy(bufwr,a);                              //çàíåñòè â ïðîãðàììíûé ïåðåäàþùèé áóôåð ñòðîêó êîìàííäó
 writer->Resume();                          //àêòèâèðîâàòü ïîòîê çàïèñè â ïîðò
 }
//---------------------------------------------------------------------------
0
91 / 91 / 22
Регистрация: 02.07.2013
Сообщений: 332
05.12.2013, 16:15
static char a доступна только внутри if. Фактически в bufwr копируется глабальная char a[2] с каким-то мусором.
1
 Аватар для Димитрий
0 / 0 / 0
Регистрация: 06.07.2008
Сообщений: 32
05.12.2013, 16:37
При отладке делал останов программы на writer->Resume(); и смотрел что в bufwr там всё нормально "2/0/0/..." но следующий шаг и прога вылетает
0
Почетный модератор
Эксперт С++
 Аватар для SatanaXIII
5851 / 2862 / 392
Регистрация: 01.11.2011
Сообщений: 6,906
05.12.2013, 16:42
Димитрий, поставьте точку на
C++
1
while(!Terminated)
и посмотрите поточнее.
1
 Аватар для Димитрий
0 / 0 / 0
Регистрация: 06.07.2008
Сообщений: 32
05.12.2013, 17:05
ReadThread вызывается когда приходит что-нибудь из порта, а пока я не пошлю туда команду от туда будет тишина, и смотреть while(!Terminated) мне пока рано.
Извиняюсь вы говорите о WriteThread::Execute() Сейчас разберусь

Добавлено через 14 минут
Если честно то я списал вот отсюда, только немножко адаптировал (подсмотрев у других) но все равно насколько знаю о работе портов не вижу криминала.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//главная функция потока, выполняет передачу байтов из буфера в 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);  //записать байты в порт (перекрываемая операция!)
   signal = WaitForSingleObject(overlappedwr.hEvent, INFINITE);   //приостановить поток, пока не завершится перекрываемая операция WriteFile
 
   if((signal == WAIT_OBJECT_0) && (GetOverlappedResult(COMport, &overlappedwr, &temp, true)))  //если операция завершилась успешно
     {
      Form1->StatusBar1->Panels->Items[0]->Text  = "Передача прошла успешно";    //вывести сообщение об этом в строке состояния
     }
   else {Form1->StatusBar1->Panels->Items[0]->Text  = "Ошибка передачи";}     //иначе вывести в строке состояния сообщение об ошибке
 
   SuspendThread(writer);
   
  }
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
05.12.2013, 17:05

Ошибка при работе с COM-портом
Здравствуйте! Пульт, собранный на микроконтроллере, периодически посылает по RS485 на компьютер запросы, компьютер - отвечает. Однако,...

Программа виснет при работе с com-портом
Та же проблема, в программе задействовано 2 com порта, со вторым постоянные неприятности! Ни каких эксепшенов просто зависает программа!...

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

Потеря данных при работе с COM портом
Добрый день. У меня сложилась проблема с программированием COM порта. Я пишу программу, которая должна взаимодействовать с оборудованием....

Наводки при работе с портом Atmega8515
Atmega 8515 DDRB = 0xFF; //выход все порты б portb - out PORTB = 0xFF; PORTC = 0xFF;//on DDRC = 0x00;//in Если...


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

Или воспользуйтесь поиском по форуму:
39
Ответ Создать тему
Новые блоги и статьи
Запустил конкурс "тем и промптов для текстовых квестов созданных почти чисто ИИ"
Adler 06.10.2026
Всем привет! За последние три-четыре дня я создал более 16 текстовых квестовых игр используя преимущественно по одному запросу к ИИ на игру. Мне так понравилось смотреть все ветки/ сцены во всех. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru