Russian Qt Forum
Март 29, 2024, 17:11
Добро пожаловать,
Гость
. Пожалуйста,
войдите
или
зарегистрируйтесь
.
Вам не пришло
письмо с кодом активации?
1 час
1 день
1 неделя
1 месяц
Навсегда
Войти
Начало
Форум
WIKI (Вики)
FAQ
Помощь
Поиск
Войти
Регистрация
Russian Qt Forum
>
Forum
>
Qt
>
Вопросы новичков
>
Принятие пакета с Com порта
Страниц: [
1
]
2
Вниз
« предыдущая тема
следующая тема »
Печать
Автор
Тема: Принятие пакета с Com порта (Прочитано 12139 раз)
Ostapich
Гость
Принятие пакета с Com порта
«
:
Октябрь 29, 2017, 00:12 »
Все привет! Возникла проблема! Необходимо читать с подключенной к USB Ардуинки пакет определенной структуры. Написал программу, если просто поток байтов читать, то все ок. Недавно сел за Qt и немого непривычно. Прошу подсказать.
Привожу код:
PORT_H :
Код:
#ifndef PORT_H
#define PORT_H
#include <QObject>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
struct Settings {
QString name;
qint32 baudRate;
QSerialPort::DataBits dataBits;
QSerialPort::Parity parity;
QSerialPort::StopBits stopBits;
QSerialPort::FlowControl flowControl;
};
class Port : public QObject
{
Q_OBJECT
public:
explicit Port(QObject *parent = 0);
~Port();
QSerialPort thisPort;
Settings SettingsPort;
signals:
void finished_Port(); //
void error_(QString err);
void outPort(QString data);
public slots:
void DisconnectPort();
void ConnectPort(void);
void Write_Settings_Port(QString name, int baudrate, int DataBits, int Parity, int StopBits, int FlowControl);
void process_Port();
void WriteToPort(QByteArray data);
void ReadInPort();
private slots:
void handleError(QSerialPort::SerialPortError error);//
public:
};
#endif // PORT_H
Port.cpp
Код:
#include "port.h"
#include <qdebug.h>
Port::Port(QObject *parent) :
QObject(parent)
{
}
Port::~Port()
{
qDebug("By in Thread!");
emit finished_Port();
}
void Port :: process_Port(){
qDebug("Hello World in Thread!");
connect(&thisPort,SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(handleError(QSerialPort::SerialPortError)));
connect(&thisPort, SIGNAL(readyRead()),this,SLOT(ReadInPort()));
}
void Port :: Write_Settings_Port(QString name, int baudrate,int DataBits,
int Parity,int StopBits, int FlowControl){
SettingsPort.name = name;
SettingsPort.baudRate = (QSerialPort::BaudRate) baudrate;
SettingsPort.dataBits = (QSerialPort::DataBits) DataBits;
SettingsPort.parity = (QSerialPort::Parity) Parity;
SettingsPort.stopBits = (QSerialPort::StopBits) StopBits;
SettingsPort.flowControl = (QSerialPort::FlowControl) FlowControl;
}
void Port :: ConnectPort(void){//
thisPort.setPortName(SettingsPort.name);
if (thisPort.open(QIODevice::ReadWrite)) {
if (thisPort.setBaudRate(SettingsPort.baudRate)
&& thisPort.setDataBits(SettingsPort.dataBits)//DataBits
&& thisPort.setParity(SettingsPort.parity)
&& thisPort.setStopBits(SettingsPort.stopBits)
&& thisPort.setFlowControl(SettingsPort.flowControl))
{
if (thisPort.isOpen()){
error_((SettingsPort.name+ " >> Открыт!\r").toLocal8Bit());
}
} else {
thisPort.close();
error_(thisPort.errorString().toLocal8Bit());
}
} else {
thisPort.close();
error_(thisPort.errorString().toLocal8Bit());
}
}
void Port::handleError(QSerialPort::SerialPortError error)//
{
if ( (thisPort.isOpen()) && (error == QSerialPort::ResourceError)) {
error_(thisPort.errorString().toLocal8Bit());
DisconnectPort();
}
}//
void Port::DisconnectPort(){
if(thisPort.isOpen()){
thisPort.close();
error_(SettingsPort.name.toLocal8Bit() + " >> Закрыт!\r");
}
}
//ot tuta kovuratji!!!
void Port :: WriteToPort(QByteArray data){
if(thisPort.isOpen()){
thisPort.write(data);
}
}
//
void Port :: ReadInPort(){
QByteArray data;
data.append(thisPort.readAll());
outPort(data);
//((QString)(adr.toInt())).toLatin1().toHex()
}
Окно где происходит настройка порта, в него пока хочу читать значение.
DIALOG_SETTINGS_H:
Код:
#ifndef DIALOG_SETTINGS_H
#define DIALOG_SETTINGS_H
#include "port.h"
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
#include <QDialog>
struct packet_big //пакет PC
{
unsigned char start_byte_one;//в длинном пакете равен 254
unsigned char start_byte_two;//в длинном пакете равен 232
unsigned char temp_pomp;//температура охлаждения
unsigned char on_of_pomp;//on-off насоса (1 или 0)
unsigned char ex_temp_reactor;//текущая температура в реакторе
unsigned char current_temp_reactor;//выставленная температура в реакторе
unsigned char timer_ex;//таймер
unsigned char tmp;//пока не трогаем
unsigned char CRC8;//пока не трогаем
void pask()
{
CRC8 = (start_byte_one + start_byte_two + temp_pomp + on_of_pomp + ex_temp_reactor + current_temp_reactor + timer_ex + tmp) / 10;
}
/*проверка упаковки*/
bool test_pask()
{
if (CRC8 == ((start_byte_one + start_byte_two + temp_pomp + on_of_pomp + ex_temp_reactor + current_temp_reactor + timer_ex + tmp)) / 10) return 0; //ОК
return -1; // ошибка
}
};
namespace Ui {
class Dialog_Settings;
}
class Dialog_Settings : public QDialog
{
Q_OBJECT
public:
packet_big packet_one={254, 232, 0, 0, 0, 0, 0, 0, 0};
explicit Dialog_Settings(QWidget *parent = 0);
~Dialog_Settings();
signals:
void savesettings(QString name, int baudrate, int DataBits, int Parity, int StopBits, int FlowControl);
void writeData(QByteArray data);
void send_str();
public slots:
void on_BtnSave_clicked();
void checkCustomBaudRatePolicy(int idx);
void on_cEnterText_returnPressed();
void Print(QString data);
void save_str(QString data);
private:
Ui::Dialog_Settings *ui;
};
#endif // DIALOG_SETTINGS_H
DIALOG_SETTINGS.сpp
Код:
#include "dialog_settings.h"
#include "ui_dialog_settings.h"
#include <QThread>
#include <QString>
#include <qdebug.h>
Dialog_Settings::Dialog_Settings(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog_Settings)
{
ui->setupUi(this);
connect(ui->BaudRateBox, SIGNAL(currentIndexChanged(int)),this, SLOT(checkCustomBaudRatePolicy(int)));
ui->BaudRateBox->addItem(QLatin1String("9600"), QSerialPort::Baud9600);
ui->BaudRateBox->addItem(QLatin1String("19200"), QSerialPort::Baud19200);
ui->BaudRateBox->addItem(QLatin1String("38400"), QSerialPort::Baud38400);
ui->BaudRateBox->addItem(QLatin1String("115200"), QSerialPort::Baud115200);
ui->BaudRateBox->addItem(QLatin1String("Custom"));
// fill data bits
ui->DataBitsBox->addItem(QLatin1String("5"), QSerialPort::Data5);
ui->DataBitsBox->addItem(QLatin1String("6"), QSerialPort::Data6);
ui->DataBitsBox->addItem(QLatin1String("7"), QSerialPort::Data7);
ui->DataBitsBox->addItem(QLatin1String("8"), QSerialPort::Data8);
ui->DataBitsBox->setCurrentIndex(3);
// fill parity
ui->ParityBox->addItem(QLatin1String("None"), QSerialPort::NoParity);
ui->ParityBox->addItem(QLatin1String("Even"), QSerialPort::EvenParity);
ui->ParityBox->addItem(QLatin1String("Odd"), QSerialPort::OddParity);
ui->ParityBox->addItem(QLatin1String("Mark"), QSerialPort::MarkParity);
ui->ParityBox->addItem(QLatin1String("Space"), QSerialPort::SpaceParity);
// fill stop bits
ui->StopBitsBox->addItem(QLatin1String("1"), QSerialPort::OneStop);
#ifdef Q_OS_WIN
ui->StopBitsBox->addItem(QLatin1String("1.5"), QSerialPort::OneAndHalfStop);
#endif
ui->StopBitsBox->addItem(QLatin1String("2"), QSerialPort::TwoStop);
// fill flow control
ui->FlowControlBox->addItem(QLatin1String("None"), QSerialPort::NoFlowControl);
ui->FlowControlBox->addItem(QLatin1String("RTS/CTS"), QSerialPort::HardwareControl);
ui->FlowControlBox->addItem(QLatin1String("XON/XOFF"), QSerialPort::SoftwareControl);
connect(ui->cBtnSend,SIGNAL(clicked()),this, SLOT(on_cEnterText_returnPressed()) );
QThread *thread_New = new QThread;//Создаем поток для порта платы
Port *PortNew = new Port();//Создаем обьект по классу
PortNew->moveToThread(thread_New);//помешаем класс в поток
PortNew->thisPort.moveToThread(thread_New);//Помещаем сам порт в поток
connect(thread_New, SIGNAL(started()), PortNew, SLOT(process_Port()));//Переназначения метода run
connect(PortNew, SIGNAL(finished_Port()), thread_New, SLOT(quit()));//Переназначение метода выход
connect(thread_New, SIGNAL(finished()), PortNew, SLOT(deleteLater()));//Удалить к чертям поток
connect(PortNew, SIGNAL(finished_Port()), thread_New, SLOT(deleteLater()));//Удалить к чертям поток
connect(this,SIGNAL(savesettings(QString,int,int,int,int,int)),PortNew,SLOT(Write_Settings_Port(QString,int,int,int,int,int)));//Слот - ввод настроек!
connect(ui->BtnSave, SIGNAL(clicked()),PortNew,SLOT(ConnectPort()));
connect(PortNew, SIGNAL(outPort(QString)), this, SLOT(Print(QString)));//Лог ошибок
connect(PortNew, SIGNAL(outPort(QString)), this, SLOT(save_str(QString)));//Лог ошибок
connect(this,SIGNAL(writeData(QByteArray)),PortNew,SLOT(WriteToPort(QByteArray)));
ui->comboBox->clear();
foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
{
ui->comboBox->addItem(info.portName());
}
ui->lcdNumber->display(packet_one.temp_pomp);
thread_New->start();
}
Dialog_Settings::~Dialog_Settings()
{
delete ui;
qDebug("dellit setting");
}
void Dialog_Settings ::on_BtnSave_clicked()
{
savesettings(ui->comboBox->currentText(), ui->BaudRateBox->currentText().toInt(),ui->DataBitsBox->currentText().toInt(),
ui->ParityBox->currentText().toInt(), ui->StopBitsBox->currentText().toInt(), ui->FlowControlBox->currentText().toInt());
qDebug("save setting");
}
void Dialog_Settings::checkCustomBaudRatePolicy(int idx)
{
bool isCustomBaudRate = !ui->BaudRateBox->itemData(idx).isValid();
ui->BaudRateBox->setEditable(isCustomBaudRate);
if (isCustomBaudRate)
{
ui->BaudRateBox->clearEditText();
}
}
//+++++++++++++[Процедура ввода данных из строки]++++++++++++++++++++++++++++++++++++++++
void Dialog_Settings::on_cEnterText_returnPressed()
{
QByteArray data; // Текстовая переменная
data = ui->cEnterText->text().toLocal8Bit(); // Присвоение "data" значения из EnterText
//data = ui->cEnterText->text().toLocal8Bit().toHex() + '\r';
writeData(data); // Отправка данных в порт
Print(data); // Вывод данных в консоль
}
//+++++++++++++[Процедура вывода данных в консоль]++++++++++++++++++++++++++++++++++++++++
void Dialog_Settings::Print(QString data)
{
ui->consol->textCursor().insertText(data+'\r'); // Вывод текста в консоль
ui->consol->moveCursor(QTextCursor::End);//Scroll
}
void Dialog_Settings::save_str(QString data)
{
char* ptr28 = (char* )&packet_one;
char* qwe2=(char*) &data;
qDebug("1");
if (sizeof(data) >= sizeof(packet_big))
{
char buf_pump = 0;
for (size_t i = 0; i < sizeof(packet_big); i++){
if (i == 0 && data[0] != 254)
{
qDebug("2");
i = 0;
continue;
}
if (i == 1 && data[0] != 232)
{
qDebug("3");
i = 0;
continue;
}
if (i >= 2)
{
qDebug("4");
ptr28[i] = qwe2[i];
if (i == sizeof(packet_big) - 1)
{
if (packet_one.test_pask()) //проверяем контрольную сумму
{
qDebug("5");
i = 0;
}
qDebug("6");
}
}
}
}
так вод, по образу чтения с последовательного порта ардуинки , другой ардуинкой , надо написать всего то одну функцию. Порт формирует массив байт, испускает сигнал, все ок. Связываю этот сигнал со слотом :
Код:
void Dialog_Settings::save_str(QString data)
{
char* ptr28 = (char* )&packet_one;
char* qwe2=(char*) &data;
qDebug("1");
if (sizeof(data) >= sizeof(packet_big))
{
char buf_pump = 0;
for (size_t i = 0; i < sizeof(packet_big); i++){
if (i == 0 && data[0] != 254)
{
qDebug("2");
i = 0;
continue;
}
if (i == 1 && data[0] != 232)
{
qDebug("3");
i = 0;
continue;
}
if (i >= 2)
{
qDebug("4");
ptr28[i] = qwe2[i];
if (i == sizeof(packet_big) - 1)
{
if (packet_one.test_pask()) //проверяем контрольную сумму
{
qDebug("5");
i = 0;
}
qDebug("6");
}
}
}
}
Но ничего не происходит. Подскажите что не так делаю. Я вообще программирование самостоятельно изучаю, поэтому за код строго не судите. Топорно, но на ардуинке все работает.
Заранее спасибо
Записан
Ostapich
Гость
Re: Принятие пакета с Com порта
«
Ответ #1 :
Октябрь 29, 2017, 00:17 »
Может поменять как то типы данных структуры? я понимаю что решение проблемы простое, но хоть убейте не вижу...
Записан
Ostapich
Гость
Re: Принятие пакета с Com порта
«
Ответ #2 :
Октябрь 29, 2017, 09:21 »
Массив который читается с потока, почему то всегда 4 байта весит, не увеличивается.... короче тупик пока...)
Записан
Mikhail
Программист
Offline
Сообщений: 586
Re: Принятие пакета с Com порта
«
Ответ #3 :
Октябрь 29, 2017, 13:34 »
А не пробовали читать из порта по приходу сигнала о наличии в нем данных. Данные приходят в порт неравномерно и количество байт в блоке не определено. Прочитав один блок, надо быть готовым читать остальные. И все это по сигналам.
Записан
Ostapich
Гость
Re: Принятие пакета с Com порта
«
Ответ #4 :
Октябрь 29, 2017, 14:02 »
Прошу прощения, но если сигнал из порта приходит, значит данные есть. Я правильно понимаю? Или прошу поподробнее....
Записан
Ostapich
Гость
Re: Принятие пакета с Com порта
«
Ответ #5 :
Октябрь 29, 2017, 14:04 »
Как я понял Port :: ReadInPort() каждый раз читает по одному байту, хотя если в дебаг выводить QSerialPort :: bytesAvailable () , то там 200 слишним байт, но если выводить data.size() , то там всегда 4 байта, ничего не пойму откуда ноги растут. На Ардуинке этот алгоритм работает, тут я так понял проблема с типами данных и с поочередностью поступления пакета. На ардуинке разобрался, тут что то не пойму.
Записан
titan83
Гость
Re: Принятие пакета с Com порта
«
Ответ #6 :
Октябрь 29, 2017, 17:30 »
Здорова, ты упускаешь такой момент: на ардуино нет буферизации (не уверен, но почти 100%), т.е. все что поступает одним физическим "пакетом" сразу же и доступно. На "больших братьях" с ОС все немного иначе: тут буферы, уведомления от драйверов аппаратуры... Поэтому ты не можешь контролировать сколько именно байт отдаст драйвер твоей программе.
Короче, тебе надо отслеживать, что пакет, который ты ожидаешь пришел целиком, его надо где-то "собирать".
Т.е. заведи не локальный QByteArray и в него делай append каждый раз в функции ReadInPort (почему "In"Тогда уж "From"). Когда поймешь, что пришло все, что ожидал (нужная комбинация байт или таймаут, или что там в твоем протоколе), то тогда уже передавай собранный массив дальше, не забыв его очистить для следующего сеанса.
Ну и отвыкай от char'ов))
Записан
Ostapich
Гость
Re: Принятие пакета с Com порта
«
Ответ #7 :
Октябрь 29, 2017, 17:41 »
Так, все по порядку. Весь алгоритм вычленения пакета я делаю в слоте ReadInPort ( сейчас приеду домой, переименую). Я создаю QByteArray в самом классе порта, потом когда вызывается слот по сигналу readeread( как ты сказал приехать может сколько угодно байт, одному богу известно), я добавляю в массив данные и смотрю что в нем лежит. А если придет меньше , чем хотя бы первые два стартовых байта?мастерить конечный автомат? И что вместо char? И вообще был бы благодарен за псевдокод..)
Записан
Ostapich
Гость
Re: Принятие пакета с Com порта
«
Ответ #8 :
Октябрь 29, 2017, 17:49 »
Или если пришло меньше чем размер нужного нам пакета, положить в массив и ждать еще остаток?
Записан
Ostapich
Гость
Re: Принятие пакета с Com порта
«
Ответ #9 :
Октябрь 29, 2017, 17:55 »
Как я себе представил: Приходит пакет неизвестного размера, мы его запихиваем в массив, смотрим , если меньше того сколько нам нужно , то выходим из слота и ждем следующего, если больше, то в цикле режем его на нужные части и запихиваем в локальный массив, который отправляем вызовом сигнала, если что то осталось, повторяем пока станет меньше или ничего не останется?
Записан
titan83
Гость
Re: Принятие пакета с Com порта
«
Ответ #10 :
Октябрь 29, 2017, 17:57 »
Цитата: Ostapich от Октябрь 29, 2017, 17:49
Или если пришло меньше чем размер нужного нам пакета, положить в массив и ждать еще остаток?
Видишь ли, есть разные признаки "законченности" пакета: определенный размер, набор неких байт в конце пакета, временной интервал после пакета.
Нужно понять, что у тебя.
Вот пример ожидания по таймауту:
Код:
if (_serialPort.bytesAvailable() > 0) {
if (_reciveData) {
_inputData.append(_serialPort.readAll());
_finishSerialReadingTimer.start(100);
}
}
Здесь _inputData - как раз QByteArray, определенный в классе. В него дописывают все пришедшие данные, а когда 100мс ничего не приходит, то вызывается, слот по сигналу timeout() от _finishSerialReadingTimer и там этот массив уже обрабатывается.
Записан
Ostapich
Гость
Re: Принятие пакета с Com порта
«
Ответ #11 :
Октябрь 29, 2017, 18:01 »
Ну у меня есть только размер и первые два стартовых байта, в конце идет контрольная сумма. Т.е. Если я в ардуино настрою что пакеты отправляются через 100мс, у меня будет еще дополнительны параметр. Ок.
Записан
titan83
Гость
Re: Принятие пакета с Com порта
«
Ответ #12 :
Октябрь 29, 2017, 18:08 »
Цитата: Ostapich от Октябрь 29, 2017, 18:01
Ну у меня есть только размер и первые два стартовых байта, в конце идет контрольная сумма. Т.е. Если я в ардуино настрою что пакеты отправляются через 100мс, у меня будет еще дополнительны параметр. Ок.
Зачем тебе время, если известен размер пакета и стартовые байты? Используй их для приема.
Записан
Ostapich
Гость
Re: Принятие пакета с Com порта
«
Ответ #13 :
Октябрь 29, 2017, 18:16 »
Ок. Отпишусь по результатам...
Записан
Ostapich
Гость
Re: Принятие пакета с Com порта
«
Ответ #14 :
Октябрь 30, 2017, 21:00 »
Товарищи, что не так!?
Код:
void Port :: ReadInPort(){
if(thisPort.bytesAvailable()>0){
QByteArray tmp;
in_data.append(thisPort.readAll());
if(in_data.size()>=sizeof(packet_big)){
qDebug()<<"1";
for(size_t i=0;i<in_data.size();i++){
qDebug()<<"2";
if(in_data[i]==254){
qDebug()<<"3";
qDebug()<<" "<<in_data[i];
if(in_data[i+1]==232){
qDebug()<<"4";
qDebug()<<" "<<in_data[i+1];
if(in_data.size()>=sizeof(packet_big)){
qDebug()<<"5";
tmp=in_data.mid(i,sizeof(packet_big)-1);
in_data.remove(0,i+(sizeof(packet_big)-1));
qDebug()<<" "<<tmp;
emit Send_Data(tmp);
}
else{
qDebug()<<"6";
in_data.remove(0,i);
break;
}
}
}
}
}
}
}
ПО дебагу все if проходит, доходит до 5. но когда пытаюсь вывести через дебаг массив, белеберду выводит : "\xFE\xE8\x00\x00\x00\x00\x00\x00", почему пустые данные , а заполнены только 2.
Записан
Страниц: [
1
]
2
Вверх
Печать
« предыдущая тема
следующая тема »
Перейти в:
Пожалуйста, выберите назначение:
-----------------------------
Qt
-----------------------------
=> Вопросы новичков
=> Уроки и статьи
=> Установка, сборка, отладка, тестирование
=> Общие вопросы
=> Пользовательский интерфейс (GUI)
=> Qt Quick
=> Model-View (MV)
=> Базы данных
=> Работа с сетью
=> Многопоточное программирование, процессы
=> Мультимедиа
=> 2D и 3D графика
=> OpenGL
=> Печать
=> Интернационализация, локализация
=> QSS
=> XML
=> Qt Script, QtWebKit
=> ActiveX
=> Qt Embedded
=> Дополнительные компоненты
=> Кладовая готовых решений
=> Вклад сообщества в Qt
=> Qt-инструментарий
-----------------------------
Программирование
-----------------------------
=> Общий
=> С/C++
=> Python
=> Алгоритмы
=> Базы данных
=> Разработка игр
-----------------------------
Компиляторы и платформы
-----------------------------
=> Linux
=> Windows
=> Mac OS X
=> Компиляторы
===> Visual C++
-----------------------------
Разное
-----------------------------
=> Новости
===> Новости Qt сообщества
===> Новости IT сферы
=> Говорилка
=> Юмор
=> Объявления
Загружается...