Форум программистов, компьютерный форум, киберфорум
Boost C++
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
0 / 0 / 0
Регистрация: 06.10.2023
Сообщений: 1
1

ASIO serial_port

06.10.2023, 20:10. Показов 2143. Ответов 0

Author24 — интернет-сервис помощи студентам
Здравствуйте!

При рефакторинге программы столкнулся со следующей проблемой. У нас изделия имеют в своем составе порт RS-485, который в процессе настройки нужно проверять на работоспособность, для чего применяется следующий алгоритм, на прибор подается команда "Провести тестирование" и прибор по порту RS-485 посылает какие-либо данные, задача программы в этот момент данные прочитать и с небольшой задержкой отправить обратно, прибор уже анализирует, если данные совпадают, то порт рабочий, если нет, то нет.

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

Сейчас же решили делать код кроссплатформенным, поэтому было принято решение об использовании boost::asio. Так как я не нашел возможность узнать, сколько байт информации получено по com порту, сделал несколько по другому алгоритму: данные из порта вычитываются по одному, запуск операции чтения выполняется командой run_one_for, если run_one_for не вызывала обработчик, то считаем, что данные пришли полностью и нужно их отправить обратно.

Так-то все вроде работает, но почему-то первое сообщение принимается без искажений, а все последующие искажаются:

[06/10/2023 18:52:53] - Read data
53 74 61 72 74 20 54 65 73 74 20 4d 6f 64 62 75 Start Test Modbu
73 20 21 21 21 00 s !!!.
[06/10/2023 18:52:55] - Written data
53 74 61 72 74 20 54 65 73 74 20 4d 6f 64 62 75 Start Test Modbu
73 20 21 21 21 00 s !!!.
[06/10/2023 18:52:59] - Read data
53 74 61 72 74 20 54 65 73 74 20 4d 6f 64 62 75 Start Test Modbu
73 20 21 21 21 00 s !!!.
[06/10/2023 18:53:01] - Written data
53 74 72 74 20 20 54 65 74 20 4d 6f 64 62 75 73 Strt Tet Modbus
20 21 21 21 21 00 !!!!.
[06/10/2023 18:53:04] - Read data
53 74 61 72 74 20 54 65 73 74 20 4d 6f 64 62 75 Start Test Modbu
73 20 21 21 21 00 s !!!.
[06/10/2023 18:53:11] - Written data
53 74 61 72 74 20 73 74 20 4d 6f 64 62 75 73 73 Start st Modbuss
73 20 21 21 21 21 s !!!!



код программы:

COM_EchoAsync.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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#ifndef TCOM_EchoAsync_H
#define TCOM_EchoAsync_H
//---------------------------------------------------------------------------
#include <boost/atomic.hpp>
#include <boost/chrono/duration.hpp>
#include <boost/chrono/time_point.hpp>
#include <boost/chrono/system_clocks.hpp>
#include <boost/asio/basic_socket.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/serial_port.hpp>
#include <boost/thread/thread.hpp>
#include <string>
class TCOMEchoAsync
{
            public:
                        TCOMEchoAsync();
                        virtual ~TCOMEchoAsync();
                        /// Установить соединение
                        virtual void Open();
                        /// Разорвать соединение
                        virtual void Close();
                        ///
                        virtual bool StartEcho();
                        ///
                        virtual bool StopEcho();
                        ///
                        void Write(std::string sMsg);
           private:
                        boost::asio::io_context Fcontext;   ///< Требуется для общения с сервисом ввода/вывода операционной системы
                        std::unique_ptr<boost::asio::serial_port> FptrSPort;
                        bool FbConnectError; ///< Признак ошибки при установке соединения
                        unsigned char FcChar;
                        std::vector<unsigned char> FvReadData;
                        ///  поток, выполняющий всю работу
                        boost::thread FWorkThread;
                        /// флаг, пока true отвечаем эхом
                        boost::atomic<bool> FbRun;
                        /// флаг, показывающий, что идет запись информации
                        boost::atomic<bool> FbTranssend;
                        /// флаг, показывающий, что передача только начинается
                        boost::atomic<bool> FbBeginn;
                        ///
                        bool FbReadExist;
                        void InitHandle(HANDLE port);
                        /// Запуск контекста
                        void RunContext();
                        /// Функция обратного вызова, вызываемая при асинхронном чтении
                        void on_read(const boost::system::error_code &err, std::size_t bytes);
                        /// Функция обратного вызова, вызываемая при асинхронной записи
                        void on_write(const boost::system::error_code &err, std::size_t bytes);
};
#endif
COM_EchoAsync.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
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
#include "COM_EchoAsync.h"
#include <boost/ref.hpp>
//#include <boost/bind.hpp>
#include <boost/bind/bind.hpp>
#include <Windows.h>
#include <chrono>
#include <iostream>
//---------------------------------------------------------------------------
constexpr unsigned int iDelayTwoSymbols = 64u; // Задержка между передачами, мс
using namespace boost::asio;
using namespace std;
TCOMEchoAsync::TCOMEchoAsync():
                                           FptrSPort(new boost::asio::serial_port(Fcontext))
{
}
TCOMEchoAsync::~TCOMEchoAsync()
{
}
//---------------------------------------------------------------------------
void TCOMEchoAsync::InitHandle(HANDLE port)
{
            DCB dcbSerialParams = { 0 };
            GetCommState(port, &dcbSerialParams);
            dcbSerialParams.BaudRate = 9600;//CBR_9600;
            dcbSerialParams.ByteSize = 8;
            dcbSerialParams.StopBits = ONESTOPBIT;
            dcbSerialParams.Parity = NOPARITY;
            dcbSerialParams.fNull=FALSE;
            dcbSerialParams.fErrorChar=FALSE;
            dcbSerialParams.fDtrControl = DTR_CONTROL_ENABLE;
            dcbSerialParams.fRtsControl = RTS_CONTROL_ENABLE;
            dcbSerialParams.fOutX=false;
            dcbSerialParams.fInX=false;
            SetCommState(port, &dcbSerialParams);
            PurgeComm(port,PURGE_TXABORT|PURGE_RXABORT); // отмена операций чтения/записи
            PurgeComm(port,PURGE_TXCLEAR|PURGE_RXCLEAR); // очистка буферов приема/передачи драйвера
}
 
//---------------------------------------------------------------------------
// Установить соединение
void TCOMEchoAsync::Open()
{
            using boost::system::system_error;
            {
                        // Открываем соединение, если не открыто
                        if (!FptrSPort->is_open())
                        {
                                   FptrSPort->open("COM3");
                                   InitHandle(FptrSPort->native_handle());
                        }
            }
}
//---------------------------------------------------------------------------
// Разорвать соединение
void TCOMEchoAsync::Close()
{
            if (FptrSPort->is_open())
            {
                        FptrSPort->close();
            }
}
//---------------------------------------------------------------------------
// Запуск контекста
void TCOMEchoAsync::RunContext()
{
            while(FbRun)
            {
                        FbReadExist = false;
 //                       Fcontext.restart();
                        if(FbBeginn)
                                   Fcontext.run_one();
                        else
                                   Fcontext.run_one_for(std::chrono::milliseconds(iDelayTwoSymbols));
                        if(!FbReadExist)
                        {
                                   FbTranssend = true;
                                   FbBeginn = true;
                                   boost::this_thread::sleep(boost::chrono::milliseconds(1000));
                                   FptrSPort->async_write_some(buffer(FvReadData),
                                         boost::bind(&TCOMEchoAsync::on_write, this, boost::placeholders::_1, boost::placeholders::_2));
                                   Fcontext.run_one();
                        }
            }
}
//---------------------------------------------------------------------------
//
bool TCOMEchoAsync::StartEcho()
{
            using namespace boost::chrono;
            Fcontext.restart();
            FvReadData.clear();
            FvReadData.reserve(100);
            FbBeginn = true;
            FbRun = true;
            FptrSPort->async_read_some(buffer(&FcChar,1),
                     boost::bind(&TCOMEchoAsync::on_read, this, boost::placeholders::_1, boost::placeholders::_2));
            FbTranssend = false;
            FWorkThread = boost::thread(&TCOMEchoAsync::RunContext, this);
            return true;
}
//---------------------------------------------------------------------------
//
bool TCOMEchoAsync::StopEcho()
{
            Fcontext.stop();
            FbRun = false;
            FWorkThread.join();
            return true;
}
//---------------------------------------------------------------------------
// Функция обратного вызова, вызываемая при асинхронном чтении
void TCOMEchoAsync::on_read(const boost::system::error_code &err, std::size_t bytes)
{
            using namespace boost::chrono;
            FbBeginn = false;
            FbTranssend = false;
            FbReadExist = true; 
            FvReadData.push_back(FcChar);
            FptrSPort->async_read_some(buffer(&FcChar,1),
                        boost::bind(&TCOMEchoAsync::on_read, this, boost::placeholders::_1, boost::placeholders::_2));
}
//---------------------------------------------------------------------------
// Функция обратного вызова, вызываемая при асинхронной записи
void TCOMEchoAsync::on_write(const boost::system::error_code &err, std::size_t bytes)
{
            using namespace boost::chrono;
            FvReadData.clear();
            FvReadData.reserve(100);
            FbBeginn = true;
            FptrSPort->async_read_some(buffer(&FcChar,1),
                   boost::bind(&TCOMEchoAsync::on_read, this, boost::placeholders::_1, boost::placeholders::_2));
}
//---------------------------------------------------------------------------
main.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include "Device\COM_EchoAsync.h"
/**
* Тестовая программа для проверки эхо ответчика
*/
using namespace std;
using namespace boost::chrono;
int main()
{
            TCOMEchoAsync *pCOMEchoAsync = new TCOMEchoAsync();
            pCOMEchoAsync->Open();
            pCOMEchoAsync->StartEcho();
            int num;
            cin >> num;
            cout << "The End" << endl;
            pCOMEchoAsync->Close();
           delete pCOMEchoAsync;
           return 0;
}
Может я вообще пошел по неправильному пути, может можно по другому решить задачу.

Буду благодарен за помощь.
Вложения
Тип файла: zip ComPort.zip (3.7 Кб, 3 просмотров)
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
06.10.2023, 20:10
Ответы с готовыми решениями:

Общение с принтером через serial_port и exception "Inappropriate ioctl for device"
Доброго времени суток! Только начал использовать библиотеку Boost и хочу с её помощью посылать...

Asio, g++
Не компилируется проект. Код: #include &lt;boost/asio.hpp&gt; #include &lt;iostream&gt; #include...

asio
Здравствуйте, хочу спросить у вас совета, дело вот в чем у меня есть асинхронные операции.......

Boost Asio C++
Добрый день. Юзаю этот ( http://www.boost.org/ ) проект. Нужна помощь с документаций...

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

Boost::asio
Всем привет. Столкнулся с такой проблемой: Скачал, установил boost (IDE msvs 2019), при...

asio+bind
при выполнении в bind.hpp и handler_type_requirements.hpp возникают ошибки вот код Server.h...

boost asio
Что-то не работает... Окошко abort() и конец. Что делать? #include &lt;iostream&gt; #ifdef _WIN32...

Boost.asio
Добрый день. Я только начал знакомство с boost.asio и при использовании примеров с офф.сайта...

boost::asio
начал ковырять буст. Возник вопрос с созданием клинт-серверного приложения. Для ознакомления хочу...

boost/asio
Кто тестил asio в Вuilder-е? Код использовал отсюда...


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

Или воспользуйтесь поиском по форуму:
1
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru