0 / 0 / 1
Регистрация: 10.01.2016
Сообщений: 46
1

Зацикливание при чтении COM-порта в функции ReadFile()

27.05.2019, 10:17. Показов 2518. Ответов 1
Метки нет (Все метки)

Создал класс Transmit для работы с виртуальным COM-портом ПК.

Transmit.h
Кликните здесь для просмотра всего текста

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
#include "Windows.h"
 
#define TIME_DIVISION_CHANNELS_SENSOR_ADDRESS 0x0F      // Адрес датчика для протокола c временным разделением канала
 
#define SUCCESS 1                                       // Коды ошибок
#define OPEN_PORT_ERROR 0   
#define PORT_CONFIGURATION_ERROR 2
#define TIME_IS_UP_ERROR 3
#define PORT_IS_BUSY_ERROR 5
 
#define WAIT_TIME 1000                                  // Время ожидания ответа датчика в ms
 
#pragma once
ref class Transmit
{
private:
    HANDLE port;                                        // Адрес порта
 
    unsigned char *package;                             // Сформированный отправляемый пакет. Зависит от входных данных
 
    unsigned int startTime;                             // Время начала отсчета. Необходимо для таймера
    bool timeIsUp;                                      // Флаг конца отсчета таймера
 
    unsigned char *recivedPackage;                      // Ответ датчика
    DWORD sizeOfResivedPackage;                         // Число принятых байт
 
public:
    Transmit();
 
    int TimeDivisionChannelsLoad(unsigned char *data,   // Указатель на массив data
        unsigned char sizeOfData);                      // Размер data
 
private:
    int OpenPort();
};


Transmit.cpp
Кликните здесь для просмотра всего текста

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include "Transmit.h"
 
 
int Transmit::OpenPort()
{
    // Открытие последовательного порта
    port = CreateFile(L"COM3", GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, NULL, NULL);
    if (port == INVALID_HANDLE_VALUE)
    {
        if (GetLastError() == PORT_IS_BUSY_ERROR) return PORT_IS_BUSY_ERROR;
        else return OPEN_PORT_ERROR;
    }
 
    // Настройка порта
    DCB dcb;
    GetCommState(port, &dcb);
    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.BaudRate = CBR_9600;                // Скорость передачи данных
    dcb.fParity = NOPARITY;                 // Проверка четности
    dcb.ByteSize = 8;                       // Размер байта данных
    dcb.StopBits = ONESTOPBIT;              // Количество стоповых бит
 
    if (!SetCommState(port, &dcb))
    {
        CloseHandle(port);
        return PORT_CONFIGURATION_ERROR;
    }
 
    return SUCCESS;
}
 
unsigned char СalculateKS(unsigned char *package, unsigned char sizeOfData)
{
    unsigned char KS = TIME_DIVISION_CHANNELS_SENSOR_ADDRESS;
    KS ^= sizeOfData;
 
    for (int i = 6; i < sizeOfData; i++) 
        KS ^= package[i];
 
    return KS;
}
 
Transmit::Transmit() { }
 
int Transmit::TimeDivisionChannelsLoad(unsigned char *data, unsigned char sizeOfData)
{
    // Проверка на ошибки открытия порта
    switch (OpenPort())
    {
    case OPEN_PORT_ERROR: return OPEN_PORT_ERROR;
    case PORT_IS_BUSY_ERROR: return PORT_IS_BUSY_ERROR;
    case PORT_CONFIGURATION_ERROR: return PORT_CONFIGURATION_ERROR;
    }
 
    package = new unsigned char[sizeOfData + 6];
    recivedPackage = new unsigned char[100];
    
    package[0] = 0xFF;
    package[1] = 0x05;
    package[2] = 0x50;
    package[3] = TIME_DIVISION_CHANNELS_SENSOR_ADDRESS;
    package[4] = sizeOfData;
    package[5] = СalculateKS(data, sizeOfData);
 
    for (int i = 0; i < sizeOfData; i++)
        package[i + 6] = data[i];
 
    DWORD recivedSize = NULL;
    startTime = GetTickCount();
 
    // Отправка пакета
    WriteFile(port, package, sizeof(package), NULL, NULL);
 
    // Прием ответа
    while (recivedSize != recivedPackage[4] + 6)
    {
        ReadFile(port, recivedPackage, 100, &recivedSize, NULL);
 
        if (GetTickCount() > startTime + WAIT_TIME)
        {
            timeIsUp = true;
            break;
        }
    }
 
    sizeOfResivedPackage = recivedSize;
    CloseHandle(port);
 
    if (timeIsUp) return TIME_IS_UP_ERROR;
        
    return SUCCESS;
}


Из основной программы вызываю функцию записи:
C++
1
2
3
unsigned char package[] = { /* какие-то данные */ };
Transmit ^transmit = gcnew Transmit;
transmit->TimeDivisionChannelsLoad(package, sizeof(package));
Программа виснет. В дебаггере прошелся по шагам. На строчке 83 Transmit.cpp при вызове функции ReadFile() компилятор проваливается в эту функцию и больше не вылезает. В чем может быть проблема?

Не по теме:


Кликните здесь для просмотра всего текста

Почему не могу передать ссылку на переменную из тела класса в функцию ReadFile()?

C++
1
2
3
4
5
// В теле класса
DWORD recivedSize;
 
// В методе
ReadFile(port, recivedPackage, 100, &recivedSize, NULL);
interior_ptr<DWORD> не совместим с LPDWORD

Пробую преобразовать тип:
C++
1
2
3
4
5
// В теле класса
DWORD recivedSize;
 
// В методе
ReadFile(port, recivedPackage, 100, (LPDWORD)&recivedSize, NULL);
Невозможно преобразовать cli::interior_ptr<DWORD> в LPDWORD.

Передать в ReadFile() можно только переменную из метода или указатель из тела класса на переменную в теле метода.
Я еще просто зеленый в ООП.

0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
27.05.2019, 10:17
Ответы с готовыми решениями:

Работа функции FlushFileBuffers при синхронном чтении из Com-порта
Всем здравствуйте. Пытаюсь освоить работу с Com-портом средствами API. В описании к функции...

Разница между ReadFile() и ReadConsole() при чтении с консоли?
разница между ReadFile() и ReadConsole() при чтении с консоли? Просто в задании сказано...

Ошибка 87 "Неверный параметр" при чтении файла (ReadFile)
Пытаюсь прочитать структуру из файла, но при этом выскакивает ошибка 87 - неверный параметр. Вот...

Чтение из COM порта, При чтении из порта зависает read()
Каждому рано или поздно приходится программировать com порт. Вот и мой черед пришол. Я ужу умею:...

1
2291 / 790 / 299
Регистрация: 10.02.2018
Сообщений: 1,851
27.05.2019, 14:23 2
Лучший ответ Сообщение было отмечено Konigin как решение

Решение

Цитата Сообщение от Konigin Посмотреть сообщение
В чем может быть проблема?
По умолчанию ReadFile для COM-порта работает в блокирующем режиме. Это означает, что функция будет ждать получения указанного количества байт бесконечно. Если вы не хотите, что бы функция висела бесконечно установите таймауты (SetCommTimeouts). Можно установить общий таймаут приёма, тогда вызов функции будет завершаться через заданное время или по получению нужного количества байт. Можно установить время перерыва между входящими байтами, тогда можно будет уловить окончание передаваемых пакетов, если их размер меньше размера буфера чтения и используемый протокол обмена подразумевает наличие пакетов. Можно комбинировать времена и получать более сложные условия выхода.

Не по теме:

Получение адреса прекрасно работает в Си и Си++, так что лучше спросить на эту тему в соответствующем выбранному языку разделе.

1
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
27.05.2019, 14:23
Помогаю со студенческими работами здесь

Зацикливание при чтении файла
Привет всем. Помогите найти ошибку. Проблема в чтение файла. Выводит то, что ввели и потом идёт...

Зацикливание при чтении из файла
Пытаюсь читать из файла данные,сохраненные из Экселя ...

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

Зацикливание при чтении объекта из файловой системы
Такая проблема. Читаю файл из файловой системы. Перед этим проверяю существует ли файл. public...


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

Или воспользуйтесь поиском по форуму:
2
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru