Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.70/302: Рейтинг темы: голосов - 302, средняя оценка - 4.70
 Аватар для GennDALF
15 / 14 / 2
Регистрация: 24.09.2009
Сообщений: 68

Подключить устройство через COM-порт и отправить на него данные

31.03.2010, 17:05. Показов 56953. Ответов 38
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем доброго времени суток.
Потребовалось подключить устройство через COM-порт, и чтобы программа считывала и отправляла не него данные.
Начал разбираться в теме и нашел примерно такой код:
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
#include <iostream>
#include <string>
#include <conio.h>
#include <winbase.h>
 
void open_port();
void close_port();
DWORD __stdcall ReadThread(LPVOID hwnd);
 
public:
      HANDLE hCom;
 
int main()
{
      cout << "<=SERIAL PORT=>\n\n";
      //HANDLE hCom;
 
      // сперва открываем порт
      open_port();
 
      // в конце работы закрываем порт
      close_port();
 
      getch();
      return 0;
}
 
void open_port()
{
      char sPortName[] = "COM1";
      
      hCom = CreateFile(sPortName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
 
      if (hCom == INVALID_HANDLE_VALUE)
      {
            cout << "Error opening port!\n";
            getch();
            return;
      }
      else
      {
            cout << "Port succesfully opened!\n";
 
            DCB dcb;
            GetCommState(hCom, &dcb);
 
            dcb.BaudRate = CBR_57600;
            dcb.ByteSize = 8;
            dcb.Parity = NOPARITY;
            dcb.StopBits = ONESTOPBIT;
 
            if (SetCommState(hCom, &dcb))
                  cout << "Configuring OK.\n";
            else
                  cout << "Configuring error.\n";
 
            hTread = CreateThread(0, 0, ReadThread, (LPVOID)this, 0, 0);
      }
}
   
void close_port()
{
      if (hCom == INVALID_HANDLE_VALUE)
            return;
 
      TerminateThread(hThread, 0);
      CloseHandle(hCom);
 
      hCom = INVALID_HADLE_VALUE;
}
 
DWORD __stdcall ReadThread(LPVOID hwnd)
{
      DWORD iSize;
      char sReceivedChar;
 
      while (true)
      {
            ReadFile(hCom, &sReceivedChar, 1, &iSize, 0);
            SendDlgItemMessage((HWND)hwnd, IDC_EDIT2, WM_CHAR, sReceivedChar, 0);
      }
}
но скомпилировать его не получается по странной причине: компилятор находит кучу ошибок в хэдере winbase.h..
ошибки все из разряда "missing storage-class or type specifiers" и "missing ';' before identifier"

что-то у меня совсем нет идей как с этим бороться. Подскажите пожалуйста куда копать.
Спасибо!
Вложения
Тип файла: rar WinBase.rar (26.2 Кб, 391 просмотров)
1
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
31.03.2010, 17:05
Ответы с готовыми решениями:

Подскажите как отправить пакет 10 байт на устройство через com порт
Из меня программист некудышный.. что то получается отправить на ком порт из содранного примера, а как дальше действовать я не знаю. ...

Можно ли подключить USB устройство через COM-порт?
У меня на компе нету USB порта, а можно ли както подключить USB устройство через COM-порт??? Может есть какието переходники?, если есть,...

Отправить команду на устройство, подключенное к компьютеру через ethernet, и принять от него ответ
Здравствуйте, возникла проблема в подборе материала и примеров выполнения программы по работе с ethernet Собственно есть устройство...

38
125 / 123 / 0
Регистрация: 30.03.2009
Сообщений: 766
03.04.2010, 21:36
Студворк — интернет-сервис помощи студентам
но, ведь ReadThread в бесконечном цикле!! в нем надо выход оттуда по какому-либо условию))

Добавлено через 3 минуты
тебе кста писали условие с event-ами)
1
 Аватар для GennDALF
15 / 14 / 2
Регистрация: 24.09.2009
Сообщений: 68
04.04.2010, 07:17  [ТС]
Да, еще немного поправил код. Вот при таком варианте все работает как надо:
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
#include <iostream>
#include <string>
#include <conio.h>
#include <time.h>
#include <windows.h>
using namespace std;
 
 
void open_port(char * name);
void check_port(char * name);
void wait(float Seconds);
int write_data(const char * str);
void close_port();
DWORD __stdcall ReadThread(LPVOID param);
 
 
HANDLE hCom = INVALID_HANDLE_VALUE, 
       hThread, 
       hEvent = CreateEvent(NULL, false, false, NULL);
HWND hwnd;
DCB dcb;
COMMTIMEOUTS cto;
DWORD n1;
 
 
int main()
{
      cout << "<=SERIAL PORT=>\n\n";
      
      char sPortName[] = "COM1";
      // сперва открываем порт
      open_port(sPortName);
      getch();
 
      // проверяем какой он
      check_port(sPortName); 
 
      // создаем нить чтения
      hThread = CreateThread(0, 0, ReadThread, (LPVOID)hwnd, 0, 0);
/*
      // ждем 5 секунд
      wait(5);
*/
      // в конце работы закрываем порт
      close_port();
 
      getch();
      return 0;
}
 
 
void open_port(char * Name)
{
      hCom = CreateFile(Name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
 
      if (hCom == INVALID_HANDLE_VALUE)
      {
            cout << " *** Error opening port!\n";
            getch();
            return;
      }
      else
      {
            cout << " *** Port succesfully opened!\n";
 
            GetCommState(hCom, &dcb);
 
            dcb.BaudRate = CBR_57600;
            dcb.ByteSize = 8;
            dcb.Parity = NOPARITY;
            dcb.StopBits = ONESTOPBIT;
 
            if (SetCommState(hCom, &dcb))
                  cout << " *** Configuring OK.\n\n";
            else
                  cout << " *** Configuring error.\n\n";
      }
}
 
 
void check_port(char * Name)
{
      COMMCONFIG comm;
      if (GetDefaultCommConfig(Name, &comm, &comm.dwSize))
      {
            switch (comm.dwProviderSubType)
            {
            case PST_FAX :
                        cout << "FAX device " << endl;
                        break;
            case PST_LAT :
                        cout << "LAT protocol" << endl; 
                        break;
            case PST_MODEM :
                        cout << "Modem device " << endl;
                        break;
            case PST_NETWORK_BRIDGE :
                        cout << "Unspecified network bridge " << endl;
                        break;
            case PST_PARALLELPORT :
                        cout << "Parallel port " << endl;
                        break;
            case PST_RS232 :
                        cout << "RS-232 serial port " << endl;
                        break;
            case PST_RS422 :
                        cout << "RS-422 port " << endl;
                        break;
            case PST_RS423 :
                        cout << "RS-423 port " << endl;
                        break;
            case PST_RS449 :
                        cout << "RS-449 port " << endl;
                        break;
            case PST_SCANNER :
                        cout << "Scanner device " << endl;
                        break;
            case PST_TCPIP_TELNET :
                        cout << "TCP/IP TelnetR protocol " << endl;
                        break;
            case PST_UNSPECIFIED :
                        cout << "Unspecified " << endl;
                        break;
            case PST_X25 :
                        cout << "X.25 standards " << endl;
                        break;
            default :
                        cout << "?????? Microsft mail please ...." << endl;
                        break;
            }
      }
      else 
            cout << "Error access" << endl;
}
 
   
void close_port()
{
      if (hCom == INVALID_HANDLE_VALUE)
            return;
 
      //TerminateThread(hThread, 0);
      SetEvent(hEvent);
      cout << " *** Start waiting...\n";
      DWORD dwResult = WaitForSingleObject(hThread, INFINITE);
      cout << " *** End waiting.\n";
      if (WAIT_OBJECT_0 != dwResult)
      {
            TerminateThread(hThread, 0);
            cout << " *** Error closing port!\ndwResult = " << dwResult;
      }
      else
            cout << " *** Port succesfully closed!\ndwResult = " << dwResult;
 
      CloseHandle(hCom);
      CloseHandle(hThread);
      CloseHandle(hEvent);
      hCom = INVALID_HANDLE_VALUE;
}
 
 
void wait(float Seconds)
{
    clock_t delay = Seconds * CLOCKS_PER_SEC;
    clock_t start = clock();
    while (clock() - start < delay)
        ;
}
 
 
DWORD __stdcall ReadThread(LPVOID Param)
{
      DWORD iSize;
      char sReceivedChar;
      while (true)
      {
            DWORD dwResult = WaitForSingleObject(hEvent, 0);
            if (WAIT_OBJECT_0 == dwResult)
                  break;
 
            ReadFile(hCom, &sReceivedChar, 1, &iSize, 0);
            cout << sReceivedChar << "#\n"; 
      }
      return 0;
}
но стоит мне включить функцию задержки, как сразу же снова уходит в бесконечное ожидание.
И еще я не могу понять механизм выполнения потоковой функции?
Она ведь вроде как должна выполнятся все эти 5 секунд, разве нет?
0
125 / 123 / 0
Регистрация: 30.03.2009
Сообщений: 766
04.04.2010, 16:21
В общем, проблема не в том, что потоковая функция зависает в цикле, а в том, что зависает сама ReadFile, ожидая чего-нибудь от ком-порта. Для того, чтобы прервать ожидание, из основного потока перед
C++
1
 DWORD dwResult = WaitForSingleObject(hThread, INFINITE);
но после
C++
1
SetEvent(hEvent);
необходимо отменить чтение: CancelIoEx

Добавлено через 5 минут
хотя это тоже не до конца правильно решение....

Добавлено через 20 минут
правильное решение:
1.
C++
1
2
3
4
5
6
 
CRITICAL_SECTION sect;
int main()
{
   InitializeCriticalSection(&sect);
...
2.
C++
1
2
3
4
5
6
 
EnterCriticalSection(&sect);
SetEvent(hEvent);
CancelIoEx(hCom,0);
СloseHandle(hCom);
LeaveCriticalSection(&sect);
3.
C++
1
2
3
EnterCriticalSection(&sect);
LeaveCriticalSection(&sect);
ReadFile(hCom, &sReceivedChar, 1, &iSize, 0);
данное решение гарантирует, что в случае завершения потока или произойдет выход по Event, или чтение прервется по CancelIOEx, или чтение не начнется, т.к. порт уже будет закрыт, и тогда начнется следующая итерация цикла, на которой будет выполнен выход по Event
1
Эксперт С++
2924 / 1274 / 114
Регистрация: 27.05.2008
Сообщений: 3,465
04.04.2010, 18:21
Есть еще более правильное и несложное решение: использовать функцию SetCommTimeouts(). В случае, если за установленный таймаут в порт ничего не придет, функция ReadFile() тихо-мирно завершится, прочитав 0 байт. Разумеется, таймаут на завершение потока должен быть заведомо больше, чем таймаут на чтение, чтобы функция ReadFile заведомо успела завершиться - успешно или неуспешно.
2
 Аватар для GennDALF
15 / 14 / 2
Регистрация: 24.09.2009
Сообщений: 68
04.04.2010, 20:15  [ТС]
Да, установка таймаутов помогла, спасибо!
у меня еще один вопрос: почему функция чтения вызывается 2ой раз, после окончания ожидания, перед закрытием порта?
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
#include <iostream>
#include <string>
#include <conio.h>
#include <time.h>
#include <windows.h>
using namespace std;
 
 
void open_port(char * name);
void check_port(char * name);
void wait(float Seconds);
int write_data(const char * str);
void close_port();
DWORD __stdcall ReadThread(LPVOID param);
 
 
HANDLE hCom = INVALID_HANDLE_VALUE, 
       hThread, 
       hEvent = CreateEvent(NULL, false, false, NULL);
HWND hwnd;
DCB dcb;
COMMTIMEOUTS cto;
DWORD n1;
 
 
int main()
{
      cout << "<=SERIAL PORT=>\n\n";
      
      char sPortName[] = "COM1";
      // сперва открываем порт
      open_port(sPortName);
      getch();
 
      // создаем нить чтения
      hThread = CreateThread(0, 0, ReadThread, (LPVOID)hwnd, 0, 0);
 
      // устанавливаем таймауты
      //cto.ReadIntervalTimeout = 1000;
      cto.ReadTotalTimeoutConstant = 2000;
      if (SetCommTimeouts(hCom, &cto))
            cout << " *** Timeouts succesfully set!\n";
      else
            cout << " *** Error with setting timeouts!\n";
 
      // ждем 3 секунды
      wait(3);
      cout << "End waiting.\n";
 
      // в конце работы закрываем порт
      close_port();
 
      getch();
      return 0;
}
 
 
void open_port(char * Name)
{
      hCom = CreateFile(Name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
 
      if (hCom == INVALID_HANDLE_VALUE)
      {
            cout << " *** Error opening port!\n";
            getch();
            return;
      }
      else
      {
            cout << " *** Port succesfully opened!\n";
 
            GetCommState(hCom, &dcb);
 
            dcb.BaudRate = CBR_57600;
            dcb.ByteSize = 8;
            dcb.Parity = NOPARITY;
            dcb.StopBits = ONESTOPBIT;
 
            if (SetCommState(hCom, &dcb))
                  cout << " *** Configuring OK.\n\n";
            else
                  cout << " *** Configuring error.\n\n";
      }
}
 
 
void close_port()
{
      if (hCom == INVALID_HANDLE_VALUE)
            return;
 
      //TerminateThread(hThread, 0);
      SetEvent(hEvent);
      //cout << " *** Start waiting...\n";
      DWORD dwResult = WaitForSingleObject(hThread, INFINITE);
      //cout << " *** End waiting.\n";
      if (WAIT_OBJECT_0 != dwResult)
      {
            TerminateThread(hThread, 0);
            cout << " *** Error closing port!\n";//dwResult = " << dwResult;
      }
      else
            cout << " *** Port succesfully closed!\n";//dwResult = " << dwResult;
 
      CloseHandle(hCom);
      CloseHandle(hThread);
      CloseHandle(hEvent);
      hCom = INVALID_HANDLE_VALUE;
}
 
 
void wait(float Seconds)
{
    clock_t delay = Seconds * CLOCKS_PER_SEC;
    clock_t start = clock();
    while (clock() - start < delay)
        ;
}
 
 
DWORD __stdcall ReadThread(LPVOID Param)
{
      DWORD iSize;
      char sReceivedChar;
      while (true)
      {
            DWORD dwResult = WaitForSingleObject(hEvent, 0);
            if (WAIT_OBJECT_0 == dwResult)
                  break;
 
            ReadFile(hCom, &sReceivedChar, 1, &iSize, 0);
            if (iSize > 0)
                  cout << "iSize = " << iSize << "\n" << sReceivedChar << "#\n"; 
            else
                  cout << "iSize = " << iSize << "\n" << "There is nothing to read!\n";
      }
      return 0;
}
0
125 / 123 / 0
Регистрация: 30.03.2009
Сообщений: 766
04.04.2010, 22:52
а чего бы ей второй раз не вызывается? она ж в цикле!
0
 Аватар для GennDALF
15 / 14 / 2
Регистрация: 24.09.2009
Сообщений: 68
05.04.2010, 07:50  [ТС]
хм.. если я правильно понимаю, то функция ReadThread() должна завершиться за секунду до окончания задержки..

Добавлено через 56 минут
и еще кстати заметил, если при отладке ставить breakpoint на функцию ReadThread(), то программа выполняется чуть-чуть по другому: за то время пока я в режиме отладки "прохожу" по функции ReadThread() заканчивается время задержки (причем независимо от времени всегда на вызове ReadFile), в результате прога ничего на экран не выводит, потом " *** End waiting.", а потом новый проход по циклу и вывод "0 bytes"
причем за все это время не происходит выхода из ReadThread()
как-то это смущает.. вообще если на то пошло, то "лишний" здесь второй (до "End waiting") вывод результатов чтения, а не первый.
0
125 / 123 / 0
Регистрация: 30.03.2009
Сообщений: 766
05.04.2010, 10:02
она завершается за секунду до окончания задержки и в цикле запускается заново.

при отладке всегда будет работать не так, как в реале)) а вообще, многопоточность в данной программе в том виде, в каком она (программа) есть, не нужна
0
 Аватар для GennDALF
15 / 14 / 2
Регистрация: 24.09.2009
Сообщений: 68
09.05.2010, 14:30  [ТС]
Вот, на данный момент имеется следующая программа...
От многопоточности я избавился по совету Lolcht0 (еще давно), а потом решил написать пакетную передачу. Вобщем вроде программа работает... Но меня смущает сильно один момент:
Пакет объявлеятся как структура из трех элементов. И все бы было здорово, но функция WriteFile() принимает для передачи только const * void. И для того, чтобы передать заголовок и контрольную сумму приходится их насильно преобразовывать в string (а потом еще и в const * char) который съедается функцией WriteFile(). И вот не уверен я, что это нормально. Собственно вопрос: есть ли какие-нибудь другие варианты решения этой проблемы с типами?
Спасибо!

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
#include <iostream>
#include <string>
#include <conio.h>
#include <time.h>
#include <windows.h>
using namespace std;
 
 
struct package
{
      char header;
      string body;
      char summ;
};
 
 
int open_port(char * Name);                           // создание потока hCom, начальной конфигурации и установки таймаутов
void check_port(char * Name);                         // функция определения типа порта
int write_pack_data(package Pack);                    // функция записи пакета байтов
int read_pack_data();                                 // функция четния пакета байтов
int calc_check_summ(const char * Body);  // функция подсчета контрольной суммы
void wait(float Seconds);                             // функция задержки
void close_port();                                    // закрытие используемых потоков
 
 
HANDLE hCom = INVALID_HANDLE_VALUE;   // поток для работы с портом
COMMTIMEOUTS cto;                     // структура для установки таймаутов
DCB dcb;                              // структура для конфигурации
 
DWORD dwBytesWritten_h,               // записано байт заголовка
      dwBytesWritten_b,               // записано байт основного сообщения
      dwBytesWritten_s,               // записано байт суммы
      dwBuffer;                       // количество байтов записанных в поток hCom
 
 
// ========================================= Точка входа в программу =========================================
int main()
{
      cout << "<= SERIAL PORT - WORKING WITH PACKAGES =>\n\n";
      
      char sPortName[] = "COM1";
      // сперва открываем порт
      if (!open_port(sPortName))
            return 0;
 
      // проверяем какой он
      check_port(sPortName);
 
      string input = "";
      // получаем сообщение для передачи
      cout << "Enter string to send: ";
      getline(cin, input);
      while (input != "quit")
      {
            // создаем и конфигурируем пакет для передачи
            package data;
            data.header = 'h';
            data.body = input;
            data.summ = calc_check_summ(data.body.c_str());
            cout << "\ndata.header\t=\t\'" << data.header << 
                    "\'\ndata.body\t=\t\"" << data.body << 
                    "\"\ndata.CS\t\t=\t" << (int)data.summ << endl;
 
            // передаем данные
            int i_wd, i_rd;
            i_wd = write_pack_data(data);
            i_rd = read_pack_data();
 
            // снова получаем сообщение для передачи
            cout << "Enter string to send: ";
            cin >> input;
      }     
 
      // в конце работы закрываем порт
      close_port();
 
      getch();
      return 0;
}
 
 
// ========================================= Дополнительные функции =========================================
 
// функция записи пакета байтов
int write_pack_data(package Pack)
{
      size_t size_head = sizeof(Pack.header);
      size_t size_str = strlen(Pack.body.c_str());
      size_t size_CS = sizeof(Pack.summ);
 
      string head; head[0] = Pack.header;
      string summ; summ[0] = Pack.summ;
 
      int res = 0;
      if ( (size_str > 0) && (hCom != INVALID_HANDLE_VALUE) )
      {            
            res = WriteFile(hCom, head.c_str(), size_head, &dwBytesWritten_h, 0);
            res = WriteFile(hCom, Pack.body.c_str(), size_str, &dwBytesWritten_b, 0);
            res = WriteFile(hCom, summ.c_str(), size_CS, &dwBytesWritten_s, 0);
 
            cout << "\nWritten " << dwBytesWritten_h << " bytes of header\n\t" <<
                                    dwBytesWritten_b << " bytes of body\n\t" <<
                                    dwBytesWritten_s << " bytes of check summ\n";
      }
      return res;
}                                                             
 
// функция четния пакета байтов
int read_pack_data()
{
      dwBuffer = dwBytesWritten_h + dwBytesWritten_b + dwBytesWritten_s;
      int i = 0;
      DWORD dwBytesRead = 0;
      char * sReceivedChar = new char [dwBuffer];
      while (true)
      {
            for (int c = 0; c < dwBuffer; c++)
                  i = ReadFile(hCom, &(sReceivedChar[c]), 1, &dwBytesRead, 0);
            if (dwBytesRead > 0)
            {
                  cout << "\nRead " << dwBuffer << " bytes\n";
                  for (int c = 0; c < dwBuffer; c++)
                        cout << sReceivedChar[c];
                  cout << "#\n\n\n";
                  break;
            }
            else
            {
                  cout << "\nThere is nothing to read!\n\n\n";
                  break;
            }
      }
      return i;
}
 
// функция подсчета контрольной суммы
int calc_check_summ(const char * Body)
{
      int final = 0;
      for (int i = 1, j = 0, c = 0; j < strlen(Body); c++)
      {
            if ( (Body[j] & i) == i)
                  final++;
            i <<= 1;
            if (c == 8)
            {
                  c = -1; j++; i = 1;
            }
      }
      return final;
}
 
// функция создания потока hCom, начального конфигурирования и установки таймаутов
int open_port(char * Name)
{
      hCom = CreateFile(Name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
 
      if (hCom == INVALID_HANDLE_VALUE)
      {
            cout << " *** Error opening port!\n";
            getch();
            return 0;
      }
      else
      {
            cout << " *** Port succesfully opened!\n";
            
            // конфигурируем порт
            GetCommState(hCom, &dcb);
 
            dcb.BaudRate = CBR_9600;
            dcb.ByteSize = 8;
            dcb.Parity = NOPARITY;
            dcb.StopBits = ONESTOPBIT;
 
            if (SetCommState(hCom, &dcb))
                  cout << " *** Configuring OK.\n";
            else
                  cout << " *** Configuring error.\n";
 
            // устанавливаем таймауты 
            cto.ReadIntervalTimeout = MAXDWORD;
            cto.ReadTotalTimeoutMultiplier = MAXDWORD;
            cto.ReadTotalTimeoutConstant = 5000;
 
            if (SetCommTimeouts(hCom, &cto))
                  cout << " *** Timeouts succesfully set!\n\n";
            else
                  cout << " *** Error with setting timeouts!\n\n";
            
            return 1;
      }
}
 
// функция определения типа порта
void check_port(char * Name)
{
      COMMCONFIG comm;
      if (GetDefaultCommConfig(Name, &comm, &comm.dwSize))
      {
            switch (comm.dwProviderSubType)
            {
            case PST_FAX :
                        cout << "FAX device " << endl;
                        break;
            case PST_LAT :
                        cout << "LAT protocol" << endl; 
                        break;
            case PST_MODEM :
                        cout << "Modem device " << endl;
                        break;
            case PST_NETWORK_BRIDGE :
                        cout << "Unspecified network bridge " << endl;
                        break;
            case PST_PARALLELPORT :
                        cout << "Parallel port " << endl;
                        break;
            case PST_RS232 :
                        cout << "RS-232 serial port " << endl;
                        break;
            case PST_RS422 :
                        cout << "RS-422 port " << endl;
                        break;
            case PST_RS423 :
                        cout << "RS-423 port " << endl;
                        break;
            case PST_RS449 :
                        cout << "RS-449 port " << endl;
                        break;
            case PST_SCANNER :
                        cout << "Scanner device " << endl;
                        break;
            case PST_TCPIP_TELNET :
                        cout << "TCP/IP TelnetR protocol " << endl;
                        break;
            case PST_UNSPECIFIED :
                        cout << "Unspecified " << endl;
                        break;
            case PST_X25 :
                        cout << "X.25 standards " << endl;
                        break;
            default :
                        cout << "?????? Microsft mail please ...." << endl;
                        break;
            }
      }
      else 
            cout << "Error access" << endl;
      cout << endl;
}
 
// функция задержки
void wait(float Seconds)
{
    clock_t delay = Seconds * CLOCKS_PER_SEC;
    clock_t start = clock();
    while (clock() - start < delay)
        ;
}
// функция закрытия используемых потоков
void close_port()
{
      if (hCom == INVALID_HANDLE_VALUE)
            return;
 
      CloseHandle(hCom);
      cout << "\n *** Port succesfully closed!\n";
      hCom = INVALID_HANDLE_VALUE;
}
0
125 / 123 / 0
Регистрация: 30.03.2009
Сообщений: 766
09.05.2010, 20:51
на самом деле можно сразу приводить &Pack к типу (void *)
ну, типа
C++
1
res = WriteFile(hCom, (void*)&Pack, size_pack, &dwBytesWritten_h, 0);
Но, только нужно принимать во внимание тот факт, что размер структуры вообще говоря не равен размеру ее элементов, и более того, данные идут не подряд а с "дырками". Это называется выравнивание данных. Тебе же нужно его выключить, чтобы не передавать мусор в сеть, в Visual Studio это делается директивой #pragma pack
2
 Аватар для GennDALF
15 / 14 / 2
Регистрация: 24.09.2009
Сообщений: 68
10.05.2010, 09:39  [ТС]
на самом деле можно сразу приводить &Pack к типу (void *)
хм.. это интересно, но боюсь не то, что нужно.
смысл в том, чтобы отправить сперва заголовок и когда контроллер его идентифицирует, он сразу отправит сигнал компьютеру и переключится в нужный режим приема либо команды, либо данных.
т.е. отправлять всю структуру нет необходимости.. вообще ее можно было даже не создавать.. она нужна скорее для внутреннего удобства

а насколько корректно будет выглядеть такая запись?
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
struct package
{
      char header;
      string body;
      char summ;
};
 
......
 
int write_pack_data(package Pack)
{
      size_t size_head = sizeof(Pack.header);
      size_t size_str = sizeof(Pack.body.c_str());
      size_t size_CS = sizeof(Pack.summ);
 
      int res = 0;
      if ( (size_str > 0) && (hCom != INVALID_HANDLE_VALUE) )
      {
            ......
            res = WriteFile(hCom, (void *)&Pack.header, size_head, &dwBytesWritten_h, 0);
            res = WriteFile(hCom, Pack.body.c_str(), size_str, &dwBytesWritten_b, 0);
            res = WriteFile(hCom, (void *)&Pack.summ, size_CS, &dwBytesWritten_s, 0);
            ......
      }
      return res;
}
и еще хотел спросить насчет 13-ой строчки.. чем отличается strlen(Pack.body.c_str()) от sizeof(Pack.body.c_str())? Если я правильно понимаю, то каждый элемент массива кодируется одним байтом, значит численно они должны совпадать.. а у меня почему-то какой бы длины строку я не вводил - sizeof() всегда возвращает 4 байта...
0
125 / 123 / 0
Регистрация: 30.03.2009
Сообщений: 766
10.05.2010, 14:34
э, ну ты же не думаешь, что со стороны контроллера поток данных будет отличаться хоть каким либо образом при отправке хоть за раз, хоть 10ю порциями?

да, только вот string в моем случае нужно заменить, конечно, на char [N]

По последнему вопросу, собственно,
C++
1
sizeof(pointer_to_string)==sizeof(any_pointer_in_system_that_is_4_for_x86)!=strlen(pointer_to_string)
0
0 / 0 / 0
Регистрация: 27.01.2013
Сообщений: 10
03.02.2013, 19:10
Пожалуйста помогите!!!!
вот мой код:
Код C++
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
#include <iostream>
#include <conio.h>
#include <windows.h>
#include <fstream>
using namespace std;
char         *bufer_out="Polutchilos";
char         *bufer_in;
DWORD         bc;
 
 
 
int main()
{
    HANDLE hCOM=CreateFile(L"COM3",GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
    
 
 
 
 DCB dcb;
   dcb.DCBlength = sizeof(DCB);
 
    dcb.BaudRate = 9600;
    dcb.fBinary = FALSE;
    dcb.fOutxCtsFlow = FALSE;
    dcb.fOutxDsrFlow = FALSE;
    dcb.fDtrControl = DTR_CONTROL_DISABLE;
    dcb.fDsrSensitivity = 0;
    dcb.fNull = FALSE;
    dcb.fRtsControl = RTS_CONTROL_DISABLE;
    dcb.fAbortOnError = FALSE;   
    dcb.Parity = 0;
    dcb.StopBits =0;
    dcb.ByteSize = 6;
    
COMMTIMEOUTS comtimeouts; 
     comtimeouts.ReadIntervalTimeout = 0;
     comtimeouts.ReadTotalTimeoutMultiplier = 0;
    comtimeouts.ReadTotalTimeoutConstant = 0;
    comtimeouts.WriteTotalTimeoutMultiplier = 0;
    comtimeouts.WriteTotalTimeoutConstant = 0;
    
 WriteFile(hCOM,bufer_out,strlen(bufer_out),&bc,NULL);
 ReadFile(hCOM, bufer_out,strlen(bufer_in),&bc,NULL);
 cout << bufer_in;
 
 
    CloseHandle(hCOM);
    
    system ("pause");
return 0;
 
 
 
 
 
 
 
}
когда запумкаю - вылазит ошибка:

Необработанное исключение в "0x5458d540 (msvcr100d.dll)" в "KUKA_PULT_V1.0.exe": 0xC0000005: Нарушение прав доступа при чтении "0x00000000".

вылазит он не в обычном поле ошибок, а отделным окном(у меня VS 2008 express edition
)


P.S. И подскажите как поставить аватарку
0
 Аватар для Пёс
229 / 76 / 9
Регистрация: 03.02.2013
Сообщений: 311
05.02.2013, 17:55
Shadow_i, вот... Ошибка была в том, что buffer_in указывал хрен пойми куда.

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
#include <iostream>
#include <conio.h>
#include <windows.h>
#include <fstream>
using namespace std;
 
char         *bufer_out = "Polutchilos";
char         *bufer_in = new char[strlen(bufer_out) + 1];
DWORD         bc;
 
 
int main()
{
    HANDLE hCOM=CreateFile(L"COM3",GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
    DCB dcb;
 
    dcb.DCBlength = sizeof(DCB);
 
    dcb.BaudRate = 9600;
    dcb.fBinary = FALSE;
    dcb.fOutxCtsFlow = FALSE;
    dcb.fOutxDsrFlow = FALSE;
    dcb.fDtrControl = DTR_CONTROL_DISABLE;
    dcb.fDsrSensitivity = 0;
    dcb.fNull = FALSE;
    dcb.fRtsControl = RTS_CONTROL_DISABLE;
    dcb.fAbortOnError = FALSE;   
    dcb.Parity = 0;
    dcb.StopBits =0;
    dcb.ByteSize = 6;
    
    COMMTIMEOUTS comtimeouts; 
    
    comtimeouts.ReadIntervalTimeout = 0;
    comtimeouts.ReadTotalTimeoutMultiplier = 0;
    comtimeouts.ReadTotalTimeoutConstant = 0;
    comtimeouts.WriteTotalTimeoutMultiplier = 0;
    comtimeouts.WriteTotalTimeoutConstant = 0;
    
    WriteFile(hCOM,bufer_out,strlen(bufer_out),&bc,NULL);
    
    ReadFile(hCOM, bufer_in,strlen(bufer_in),&bc, NULL);
    
    cout << bufer_in;
 
    CloseHandle(hCOM);
    
    system ("pause");
return 0;
}
Добавлено через 1 час 46 минут
Да, и ещё... Ошибку я вам исправил, но программа от этого рабочей не стала. Всё дело в том что, когда вы вызываете
C++
1
WriteFile(hCOM,bufer_out,strlen(bufer_out),&bc,NULL);
то вы отсылаете данные "в пустоту", ну не то чтобы в пустоту, просто эти данные никто не принимает. А когда дело доходит до
C++
1
ReadFile(hCOM, bufer_in,strlen(bufer_in),&bc, NULL);
то программа ждёт данных с COMпорта, но их никто не высылает, поэтому она зацикливается на этой строчке.
0
1 / 0 / 4
Регистрация: 10.04.2015
Сообщений: 58
17.04.2015, 11:27
Добрый день! Не могли бы посоветовать еще литературы по работе с COM-портами?
0
1 / 1 / 0
Регистрация: 01.04.2015
Сообщений: 16
19.04.2015, 13:11
http://piclist.ru/S-COM-THREAD... D-RUS.html
1
10 / 13 / 1
Регистрация: 16.07.2020
Сообщений: 137
Записей в блоге: 1
14.09.2024, 00:58
Десятый - пятнадцатый годы =)
Поднимем тему?
Мне нужно отравить одну переменную (любую) на COM3. Без разницы каким языком.
Есть что попроще? Почему так много функций?
Может быть batch? Но хотелось бы на плюсах, с кнопочкой =)
Подскажите куда копать, пожалуйста.
0
 Аватар для MallSerg
95 / 63 / 14
Регистрация: 16.11.2018
Сообщений: 297
14.09.2024, 08:34
Цитата Сообщение от Toz Pipe Посмотреть сообщение
Может быть batch?
Windows Batch file
1
dir > com3
Работа с ком портом мало чем отличается от работы с файлом.
1
Модератор
1245 / 676 / 292
Регистрация: 10.11.2019
Сообщений: 1,406
14.09.2024, 10:50
Для получения числа байт при чтении из COM порта используется функция ClearCommError (попробуй -
догадайся по названию !) . Эта функция возвращает структуру COMSTAT

https://learn.microsoft.com/en... se-comstat

В этой структуре содержится

cbInQue - The number of bytes received by the serial provider but not yet read by a ReadFile operation.

Таким образом можно читать COM порт не по одному байту с непонятными трюками,
а нормально всю очередь байт. Аналогично - с ожиданием готовности при передаче в COM порт.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
14.09.2024, 10:50

Отправить данные на открытый порт
Как написать программу какая будет отправлять файлы на открытый порт другого пк. В с++ новичок но оч нужна такая прога, прошу помогите.

Отправить данные на открытый порт
Как написать программу какая будет отправлять файлы на открытый порт другого пк. В с++ новичок но оч нужна такая прога, прошу помогите.

Отправить данные на COM порт и вывести ответ
День добрый. Нужна ваша помощь. Пытаюсь отправить данные на ком порт и вывести ответ.При использовании метода port.Read(buffer,int,int) вся...

Принять данные с одного порта, распарсить и отправить на другой порт
Доброго времени суток, уважаемые! Второй день сижу над задачей сам себя уже запутал читая все мануалы.. Суть такая: на определенный порт...

Удалённое устройство или ресурс не принимает подключения через порт
Здравствуйте. Есть доменная сеть с 20 компьютерами. На двух из них утром обрубился интернет. Локальщая сеть работает, но все выходы в...


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

Или воспользуйтесь поиском по форуму:
39
Ответ Создать тему
Новые блоги и статьи
Из невошедшего на форум (диалог с ИИ-гугла)
zorxor 29.07.2026
А вот, что интересно, сказал мне ИИ-гугла: Этот текст — эмоциональный пост пользователя под ником zorxor на интернет-форуме (вероятно, посвященном мистике, непознанному или альтернативной науке). . . .
Был праздник вчера, а я и не знал.
kumehtar 28.07.2026
27. 07. 2026г. Intel Core 2 Duo исполнилось 20 лет Новости компьютерного мира и их обсуждение (4) Салют, шампанское, овации! :drink:
Нейтральные знания, чистый код - бла-бла-бла-бла, на самом деле кликбейт и самореклама, плагиат, и вот почему
Hrethgir 27.07.2026
То-есть отклонение такой публикации говорит само за себя, и пусть только возьмут на вооружение после отклонения публикации - это будет чистейшим актом плагиата. Отклонял Хабр. Дословно, отклонённая. . .
тв 16 бой ии
anaschu 27.07.2026
Великий Перелом ИИ: Как уравнения ОДУ Radau дожали цензурные фильтры Алисы Фиксируем в мемофонде Теории Всего беспрецедентный факт в истории ИИ-зондирования. В затяжном многораундовом. . .
мв 15. непроверенное, возможно, глюк
anaschu 27.07.2026
НАУЧНО-АНАЛИТИЧЕСКИЙ ОТЧЕТ. РАЗДЕЛ 1. 1: «НАУКА» (РАСШИРЕННАЯ СТЕХИОМЕТРИЧЕСКАЯ И ГЕНЕТИЧЕСКАЯ ВЕРСИЯ)Тема: Теоретическое обоснование инвариантности 19-мерного тензорного ядра непрерывных ОДУ и. . .
Очистка реквизитов и табличных частей документа при копировании (вариант 2)
Maks 26.07.2026
Алгоритм из решения ниже разработан на примере нетипового документа "ЗаявкаНаРаботу", разработанного в КА2. Задача: Заменить алгоритм запрета копирования документов для сотрудников с ролью "Стажер",. . .
Доктрина интенционального знания - Доктрина для портала "Срез".
Hrethgir 25.07.2026
Может найдётся кто захочет оценить доктрину. . . Написания правил участия для меня роскошь, требующая лимита времени, поэтому все сообщения не прошедшие модерацию будут видны только участникам портала,. . .
сукцессия 44. Решил подать на припринт в межународные сервисы препринтов. Но нужно одобрение от ученых
anaschu 25.07.2026
Английский вариант. Пока кто то не одобрит мою личность, мне не получиться это опубликовать на препринте. Но заявку на публикацию статьи я сегодня подам.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru