Russian Qt Forum
Сентябрь 30, 2024, 20:24 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Проблема с QSerialDevice  (Прочитано 1846 раз)
Backloz
Гость
« : Август 01, 2013, 11:10 »

Доброго всем времени суток.
Недавно возникла необходимость передавать и читать данные от устройства через com порт.
в программе реализован QTimer по сигналу от которого происходит вызов следующего кода
Код:
void MainWindow::onDataGetTaimer()
{
    short ADCDATA;
    int i=0;
    QByteArray Data,DATA1;
    DATA1.clear();
    Data+=(char)0x00;
    ComDevice->write(Data);
    ComDevice->waitForBytesWritten(1);
    while(DATA1.size()<1)
    {
        if(ComDevice->waitForReadyRead(1))
        {
           DATA1+=ComDevice->read(1);
        }
        i++;
        if(i>1000)
        {
            MessageBox1->setIcon(QMessageBox::Critical);
            MessageBox1->setText("Data get error");
            MessageBox1->setDefaultButton(QMessageBox::Ok);
            MessageBox1->show();
        }
    }
    i=0;
    DATA1.clear();
    Data.clear();
    Data+=(char)0x83;
    Data+=(char)0x03;
    ComDevice->write(Data);
    ComDevice->waitForBytesWritten(1);
    while(DATA1.size()<3)
    {
        if(ComDevice->waitForReadyRead(1))
        {
            DATA1+=ComDevice->readAll();
        }
        i++;
        if(i>1000)
        {
            MessageBox1->setIcon(QMessageBox::Critical);
            MessageBox1->setText("Data get error");
            MessageBox1->setDefaultButton(QMessageBox::Ok);
            MessageBox1->show();
        }

    }
    GetByte(SILow,ADCDATA)=DATA1[1];
    GetByte(SIHigh,ADCDATA)=DATA1[2];
    DATA1.clear();
    Data.clear();
}
Для настройки порта создал удобный удобный виджет. Далее приведу код данного виджета; основная инициализация происходит в ComInitDialog::OnOkButtonPress().
Код:
ComInitDialog::ComInitDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::ComInitDialog)
{
    ui->setupUi(this);
    //Настраиваю интерфейс
    ui->BRComboBox->setEditable(true);
    //Соединяю сигналы и слоты
    connect(ui->OkButton,SIGNAL(clicked()),this,SLOT(OnOkButtonPress()));
    connect(ui->CancelButton,SIGNAL(clicked()),this,SLOT(OnCancelButtonPress()));
    //ui->comboBox->setFrame(QFrame::HLine|QFrame::Raised);
    //ComDevice->setBaudRate()
    ComDevice=NULL;
}
ComInitDialog::~ComInitDialog()
{
    delete ui;
}
//Задаёт порт который необходимо настроить
void ComInitDialog::SetDevice(AbstractSerial *Device)
{
    ComDevice=Device;
    //Device->setReadBufferSize(500);
    //ui->BRComboBox->clear();
    //ui->BRComboBox->addItems(ComDevice->listBaudRate());
    ui->DataComboBox->clear();
    ui->DataComboBox->addItems(ComDevice->listDataBits());
    ui->DataComboBox->removeItem(0);
    ui->ParityComboBox->clear();
    ui->ParityComboBox->addItems(ComDevice->listParity());
    ui->ParityComboBox->removeItem(0);
    ui->StopBitComboBox->clear();
    ui->StopBitComboBox->addItems(ComDevice->listStopBits());
    ui->StopBitComboBox->removeItem(0);
    ui->FlowControlComboBox->clear();
    ui->FlowControlComboBox->addItems(ComDevice->listFlowControl());
    ui->FlowControlComboBox->removeItem(0);
}
//Задаёт порт который необходимо настроить и вызывает окно настройки порта
void ComInitDialog::InitDevice(AbstractSerial *Device)
{
    ComDevice=Device;
    show();
}
//Обработка нажатия на кнопку OK
void ComInitDialog::OnOkButtonPress()
{
    bool ok=true;
    if(ComDevice==NULL)
    {
        MessageBox1.setIcon(QMessageBox::Critical);
        MessageBox1.setText("ComDevice is null!!!");
        MessageBox1.setDefaultButton(QMessageBox::Ok);
        MessageBox1.show();
        return;
    }
    //Освобождаю порт если уже был занят
    if(ComDevice->isOpen()){ComDevice->close();}
    //Пытаюсь захватить выбранный порт
    ComDevice->setDeviceName(ui->PortComboBox->currentText());
    //Открываю порт для чтения и записи
    if(!ComDevice->open(AbstractSerial::ReadWrite))
    {
        MessageBox1.setIcon(QMessageBox::Critical);
        MessageBox1.setText("Can't open port!!!");
        MessageBox1.setDefaultButton(QMessageBox::Ok);
        MessageBox1.show();
        return;
    }
    if(!ComDevice->setBaudRate(ui->BRComboBox->currentText().toInt(&ok,10)))
    {
        ComDevice->listBaudRate();
        ComDevice->close();
        MessageBox1.setIcon(QMessageBox::Critical);
        MessageBox1.setText("baud rate set error!!!");
        MessageBox1.setDefaultButton(QMessageBox::Ok);
        MessageBox1.show();
        return;
    }
    if(!ComDevice->setDataBits(ui->DataComboBox->currentText()))
    {
        ComDevice->close();
        MessageBox1.setIcon(QMessageBox::Critical);
        MessageBox1.setText("DataBits set error!!!");
        MessageBox1.setDefaultButton(QMessageBox::Ok);
        MessageBox1.show();
        return;
    }

    if(!ComDevice->setParity(ui->ParityComboBox->currentText()))
    {
        ComDevice->close();
        MessageBox1.setIcon(QMessageBox::Critical);
        MessageBox1.setText("Parity set error!!!");
        MessageBox1.setDefaultButton(QMessageBox::Ok);
        MessageBox1.show();
        return;
    }
    //FlowControlComboBox
    if(!ComDevice->setFlowControl(ui->FlowControlComboBox->currentText()))
    {
        ComDevice->close();
        MessageBox1.setIcon(QMessageBox::Critical);
        MessageBox1.setText("FlowControl set error!!!");
        MessageBox1.setDefaultButton(QMessageBox::Ok);
        MessageBox1.show();
        return;
    }
    ComDevice->setReadBufferSize(10000);
    ComDevice->setTotalReadConstantTimeout(1000);
    ComDevice->setCharIntervalTimeout(1000);
    close();
}
//Обработка нажатия на кнопку Cancel
void ComInitDialog::OnCancelButtonPress()
{
    close();
}
ну и приведу код основной инициализации главного окна.
Код:
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    MessageBox1=new QMessageBox();
    MessageBox1->setParent(this);
    MessageBox1->hide();
    ComDevice = new AbstractSerial();
    ComDevice->setParent(this);
    //ComDevice->setCharIntervalTimeout(5000);
    DockPlot = new QwtDockPlot();
    DockPlot->setParent(this);
    addDockWidget(Qt::TopDockWidgetArea,DockPlot,Qt::Vertical);
    Curve1 = new QwtPlotCurve("ISENS5");
    Curve2 = new QwtPlotCurve("ISENS2");
    Curve3 = new QwtPlotCurve("ISENS7");
    Curve1->setRenderHint(QwtPlotItem::RenderAntialiased);
    Curve1->setPen(QPen(Qt::red));
    Curve2->setRenderHint(QwtPlotItem::RenderAntialiased);
    Curve2->setPen(QPen(Qt::blue));
    Curve3->setRenderHint(QwtPlotItem::RenderAntialiased);
    Curve3->setPen(QPen(Qt::yellow));
    Curve1Data = new QVector<QPointF>();
    Curve2Data = new QVector<QPointF>();
    Curve3Data = new QVector<QPointF>();
    Dialog1 = new ComInitDialog();
    Dialog1->SetDevice(ComDevice);
    //Dialog1->setParent(this);
    Dialog1->InitDevice(ComDevice);
    DataGetTaimer = new QTimer(this);

    X=0;
    connect(DockPlot,SIGNAL(SendToTransClicked()),this,SLOT(DockPlotSendToTransClicked()));
    connect(DockPlot,SIGNAL(TransOFFClicked()),this,SLOT(DockPlotTransOFFClicked()));
    connect(DockPlot,SIGNAL(StartClicked()),this,SLOT(DockPlotStartClicked()));
    connect(DockPlot,SIGNAL(StopClicked()),this,SLOT(onStopPress()));
    connect(DataGetTaimer,SIGNAL(timeout()),this,SLOT(onDataGetTaimer()));
    Curve1->attach(DockPlot->GetPlot());
    Curve2->attach(DockPlot->GetPlot());
    Curve3->attach(DockPlot->GetPlot());
}
вобщемто всё работает данные передаются и принимаются однако через какоето время комп уходит в перезагрузку. Так и не могу понять в чём дело. Подскажите пожалуйста.
Записан
kuzulis
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2812


Просмотр профиля
« Ответ #1 : Август 01, 2013, 13:49 »

1. Используй QtSerialPort

Оно уже есть в Qt5.1 по умолчанию. Также легко собирается и юзается для Qt4.8.x. (см. Wiki, ссылку на которую я привел).

QtSerialPort - это потомок QSerialDevice, поэтому особых проблем со сменой API быть не должно. Улыбающийся
QSerialDevice - уже давно больше не поддерживается и я даже отвечать на вопросы связанные с ним не буду. Точка!

2. Не используй блокирующее чтение/запись с waitForXXX(). Используй асинхронный I/O с сигналами readyRead(), bytesWritten()  и т.п.
« Последнее редактирование: Август 01, 2013, 13:53 от kuzulis » Записан

ArchLinux x86_64 / Win10 64 bit
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.079 секунд. Запросов: 23.