[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

QextSerialPort и потоки



Пишу программу, которая должна забирать данные с приборов по последовательному порту (8 цифровых датчиков веса производства HBM, если это важно). Для общения с портом используется QextSerialPort. Чтобы ожидание ответов не тормозило всю программу, создан второй поток (производный от QThread). В нём кроме порта также создаётся QTimer, сигнал от которого собственно и вызывает функции опроса. Оба объекта создаются уже в функции run(), которая, судя по документации, и должна выполняться в отдельном потоке. Заканчивается она вызовом exec(), чтобы сигналы от таймера обрабатывались. И всё было бы нормально, поток когда надо запускается, завершается, но ожидание ответов всё равно тормозит весь процесс. В чём может быть причина, и как это исправить? Попробовал собрать эту же программу под оффтопиком (XP SP2) - там не тормозит, всё чудесно работает. QT 4.3.0 ставил из исходников в /usr/local (если что не так, могу и пересобрать), система - Sarge. Если пройдут вложения - в них исходник этого модуля.
#include "serial.h"

int port_fd;    
//int must_stop;
//int f_rx, f_timeout;
//u_int8_t msg1 [100];

loadcells::loadcells(clbDialog *c1)
{         
//  must_stop=0;    
  clb1=c1;
  setWindowTitle (tr("Comm. setup"));
  editPortName = new QLineEdit(this);
  editN1 = new QLineEdit(this);
  editN2 = new QLineEdit(this);
  editN3 = new QLineEdit(this);
  editN4 = new QLineEdit(this);
  editN5 = new QLineEdit(this);
  editN6 = new QLineEdit(this);
  editN7 = new QLineEdit(this);
  editN8 = new QLineEdit(this);
  labelPortName = new QLabel(tr("Serial port name"), this);
  labelNN = new QLabel(tr("Adresses of loadcells"), this);  
  labelP1 = new QLabel(tr("Platform 1"), this);
  labelP2 = new QLabel(tr("Platform 2"), this);
  labelN1 = new QLabel(tr("Loadcell's N1 adress"), this);
  labelN2 = new QLabel(tr("Loadcell's N2 adress"), this);
  labelN3 = new QLabel(tr("Loadcell's N3 adress"), this);
  labelN4 = new QLabel(tr("Loadcell's N4 adress"), this);
  labelN5 = new QLabel(tr("Loadcell's N5 adress"), this);
  labelN6 = new QLabel(tr("Loadcell's N6 adress"), this);
  labelN7 = new QLabel(tr("Loadcell's N7 adress"), this);
  labelN8 = new QLabel(tr("Loadcell's N8 adress"), this);
  buttonStart = new QPushButton(tr("Start comm."), this);
  buttonStop = new QPushButton(tr("Stop comm."), this);
  buttonSave = new QPushButton(tr("Save"), this);
  buttonClose = new QPushButton(tr("Close"), this);
  checkAutostart = new QCheckBox(tr("Auto start comm."), this);
//  port1 = new QextSerialPort();
  layout1 = new QGridLayout(this);   
  tc1 = new threadComm(this);
  loadSettings();
  layout1->setSpacing(20);
  layout1->addWidget(labelNN,0,2);
  layout1->addWidget(labelP1,1,0);
  layout1->addWidget(labelP2,1,4);
  layout1->addWidget(labelN1,2,0);  
  layout1->addWidget(editN1,2,1); 
  layout1->addWidget(editN2,2,2);
  layout1->addWidget(labelN2,2,3);
  layout1->addWidget(labelN3,3,0); 
  layout1->addWidget(editN3,3,1); 
  layout1->addWidget(editN4,3,2); 
  layout1->addWidget(labelN4,3,3);
  layout1->addWidget(labelN5,2,4);  
  layout1->addWidget(editN5,2,5); 
  layout1->addWidget(editN6,2,6); 
  layout1->addWidget(labelN6,2,7);
  layout1->addWidget(labelN7,3,4); 
  layout1->addWidget(editN7,3,5); 
  layout1->addWidget(editN8,3,6); 
  layout1->addWidget(labelN8,3,7); 
  layout1->addWidget(labelPortName, 4, 0);
  layout1->addWidget(editPortName, 4, 1);
  layout1->addWidget(checkAutostart, 5, 0);
  layout1->addWidget(buttonStart, 6, 0); 
  layout1->addWidget(buttonStop, 6, 1);
  layout1->addWidget(buttonSave, 6, 6);
  layout1->addWidget(buttonClose, 6, 7);
  connect(buttonClose, SIGNAL(clicked()), this, SLOT(close()));  
  connect(buttonSave, SIGNAL(clicked()), this, SLOT(saveSettings()));   
  connect(buttonStart, SIGNAL(clicked()), tc1, SLOT(startC()));
  connect(buttonStop, SIGNAL(clicked()), tc1, SLOT(stopC())); 
  connect(tc1, SIGNAL(updated()), this, SLOT(updatedP()));
  if (checkAutostart->checkState()==Qt::Checked) tc1->startC();
//  connect(this, SIGNAL(tcStop()), tc1, SLOT(stop()));
}                         

void loadcells::updatedP()
{
  emit updated();
}

QString loadcells::getPortName()
{
  QString s1 = editPortName->text();
  return s1;
}

void loadcells::loadSettings()
{
  QSettings settings(QSettings::IniFormat, QSettings::UserScope, "CMA", "QVD"); //Debug
//  QSettings s1(QSettings::IniFormat, QSettings::SystemScope, "CMA", "QVD"); //Release
  editN1->setText(settings.value("comm/adress1", "0").toString());    
  editN2->setText(settings.value("comm/adress2", "0").toString());  
  editN3->setText(settings.value("comm/adress3", "0").toString());  
  editN4->setText(settings.value("comm/adress4", "0").toString());  
  editN5->setText(settings.value("comm/adress5", "0").toString());  
  editN6->setText(settings.value("comm/adress6", "0").toString());  
  editN7->setText(settings.value("comm/adress7", "0").toString());  
  editN8->setText(settings.value("comm/adress8", "0").toString());
  editPortName->setText(settings.value("comm/portName", " ").toString());
  if(settings.value("comm/autostart", "0").toString() == "0")checkAutostart->setCheckState(Qt::Unchecked);
  if(settings.value("comm/autostart", "0").toString() == "2")checkAutostart->setCheckState(Qt::Checked);
}

void loadcells::saveSettings()
{
  QSettings settings(QSettings::IniFormat, QSettings::UserScope, "CMA", "QVD"); //Debug
//  QSettings s1(QSettings::IniFormat, QSettings::SystemScope, "CMA", "QVD"); //Release
  settings.setValue("comm/adress1", editN1->text()); 
  settings.setValue("comm/adress2", editN2->text());
  settings.setValue("comm/adress3", editN3->text());
  settings.setValue("comm/adress4", editN4->text());
  settings.setValue("comm/adress5", editN5->text());
  settings.setValue("comm/adress6", editN6->text());
  settings.setValue("comm/adress7", editN7->text());
  settings.setValue("comm/adress8", editN8->text());
  settings.setValue("comm/portName", editPortName->text()); 
  settings.setValue("comm/autostart", checkAutostart->checkState ());
} 

//int init_port(char* portname) {
//  port_fd = open (portname, O_RDWR | O_NOCTTY | O_NDELAY);
//  if (port_fd == -1) return -1;
//  fcntl(port_fd, F_SETFL, 0);
//  struct termios options;
//  tcgetattr(port_fd, &options);
//  cfsetispeed(&options, B115200);
//  cfsetospeed(&options, B115200);
//  options.c_cflag |= (CLOCAL | CREAD);
//  options.c_cflag &= ~CSIZE;
//  options.c_cflag |= CS8;
//  options.c_cflag &= ~PARENB;
//  options.c_cflag &= ~CSTOPB;
///*  options.c_cflag |= CRTSCTS; */
//  options.c_cflag &= ~CRTSCTS;
//  options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG | IEXTEN);
//  options.c_oflag &= ~OPOST;
//  options.c_cc[VMIN]  = 0;
//  options.c_cc[VTIME] = 10;
//  options.c_iflag &= ~(IXON | IXOFF | IXANY | INLCR | ICRNL);
//  options.c_iflag &= ~(INPCK | ISTRIP | PARMRK | IGNCR);
//  options.c_iflag |= IGNPAR;
//  tcsetattr(port_fd, TCSANOW, &options);
//  tcflush (port_fd, TCIOFLUSH);
//  return 0;
//}

//void close_port (void) { close (port_fd); }


//void* u_timeout(){
////  f_timeout = 1;
//  pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
//  int count = 0;
//  while ((count < 1000) && (f_rx != 1)) { usleep (500); count++; };
////  usleep (500000);
//  f_timeout = 0;
//  return NULL;
//} 

//void* u_read(){
//  f_rx = 0;
//  int count_bytes=0;
//  msg1[0] = 1;
//  while ((f_timeout == 1)&&(count_bytes < msg1[0]+3)){
//    int len1 = read (port_fd, &msg1[count_bytes], 1);
////    if (len1 != -1)fprintf (stdout, "\n msg1[%X] = %X", count_bytes, msg1[count_bytes]);
//    if ((len1 != -1) && (count_bytes <= 30)) count_bytes += len1;
//  }
////  fprintf (stdout, "\n count_bytes = %X, f_timeout = %X", count_bytes, f_timeout);
////  }
//  if (f_timeout == 0) f_rx = -1;
//  else f_rx = 1;
//  return NULL;
//}
  
//Sending request, whaiting and testing answer
//Return codes:
//0 - OK
//-1 - Time-out
//-2 - Checksum error
//*/
//int req_ans(u_int8_t* req) {
//  pthread_t thread_read, thread_timeout;
//  f_timeout = 1;
//  pthread_create (& thread_read, NULL, &u_read, NULL);
//  pthread_create (& thread_timeout, NULL, &u_timeout, NULL);
//  int req_l = req[0]+3;
////  fprintf(stdout, "\n req = %X, %X, %X, %X, %X, %X, %X, %X, %X,", req[0], req[1], req[2], //req[3], req[4], req[5], req[6], req[7], req[8]);
////  fprintf(stdout, "\n req_l = %X", req_l);
//  int res = write (port_fd, req, req_l);
//  if (res == -1) {
//    pthread_join (thread_read, NULL);
//    pthread_join (thread_timeout, NULL);
//    return -1;
//  }
////  if (ans_l > 2) sleep (1);  
////  res = read (port_fd, ans, ans_l);
//  pthread_join (thread_read, NULL);
////  if (f_rx == 0) pthread_cancel (thread_timeout);
//  pthread_join (thread_timeout, NULL);
////  fprintf(stdout, "\n f_timeout = %X, f_rx = %X", f_timeout, f_rx);
////  if (f_rx != 1) return -1;
////  if (test_cs_msg (msg1) == 0) return 0;
////  return -2;
//  return -2;
//}
  
void threadComm::startC()
{
  start(QThread::LowestPriority);
  emit started();
}

threadComm::threadComm(loadcells *p2)
{       
  parent=p2;
}

void threadComm::stopC()
{  
  qDebug("Stop signal");
  exit(0);     
//  emit tcStop();
  if(wait(5000)==TRUE)qDebug("Normal exit");
  else qDebug("Timeout");
  emit stopped();
}  

QString loadcells::getNum(int i)
{
  QString res("0");
  switch(i)
  {
    case 1: { res=editN1->text(); break; }
    case 2: { res=editN2->text(); break; }
    case 3: { res=editN3->text(); break; }
    case 4: { res=editN4->text(); break; }
    case 5: { res=editN5->text(); break; }
    case 6: { res=editN6->text(); break; }
    case 7: { res=editN7->text(); break; }
    case 8: { res=editN8->text(); break; }
  }  
  return res;
}

void threadComm::run()
{
  port1= new QextSerialPort();
//  init_port((editPortName->text()).unicode());  
  port1->setPortName(parent->getPortName());
  port1->setBaudRate(BAUD9600);
  port1->setDataBits(DATA_8);
  port1->setFlowControl(FLOW_OFF);
  port1->setParity(PAR_EVEN);
  port1->setStopBits(STOP_1);
  port1->setTimeout(0,100);
  port1->setTextModeEnabled(FALSE);
  if(port1->open(QIODevice::ReadWrite) == TRUE)qDebug("Open TRUE");
  else qDebug("Open False");
  port1->reset();
  timer1 = new QTimer();
  connect(timer1, SIGNAL(timeout()), this, SLOT(update()));
  timer1->start(3000);
  exec();
  port1->close();
}  

void threadComm::update()
{  
  port1->write("S98;");
  port1->write("MSV?;");
  QString s1("S");
  QByteArray s2;
  
  s1+=parent->getNum(1);
  s1+=(";");
  port1->write(s1.toAscii());
  s2=port1->read(8);
  parent->setValue(s2.toFloat(),0);
  
  s1.truncate(1);
  s1+=parent->getNum(2);
  s1+=(";");
  port1->write(s1.toAscii());
  s2=port1->read(8);
  parent->setValue(s2.toFloat(),1);
  
  s1.truncate(1);
  s1+=parent->getNum(3);
  s1+=(";");
  port1->write(s1.toAscii());
  s2=port1->read(8);
  parent->setValue(s2.toFloat(),2);
  
  s1.truncate(1);
  s1+=parent->getNum(4);
  s1+=(";");
  port1->write(s1.toAscii());
  s2=port1->read(8);
  parent->setValue(s2.toFloat(),3);
  
  s1.truncate(1);
  s1+=parent->getNum(5);
  s1+=(";");
  port1->write(s1.toAscii());
  s2=port1->read(8);
  parent->setValue(s2.toFloat(),4);
  
  s1.truncate(1);
  s1+=parent->getNum(6);
  s1+=(";");
  port1->write(s1.toAscii());
  s2=port1->read(8);
  parent->setValue(s2.toFloat(),5);
  
  s1.truncate(1);
  s1+=parent->getNum(7);
  s1+=(";");
  port1->write(s1.toAscii());
  s2=port1->read(8);
  parent->setValue(s2.toFloat(),6);
  
  s1.truncate(1);
  s1+=parent->getNum(8);
  s1+=(";");
  port1->write(s1.toAscii());
  s2=port1->read(8);
  parent->setValue(s2.toFloat(),7);
  
  emit updated();
}

float loadcells::lastValue(int n1)
{
  return values[n1];
}

void loadcells::setValue(float i1, int n1)
{
  values[n1]=clb1->clb(i1*40/1000000, n1);
//  qDebug("loadcell 1 %f" ,values[n1]);
}

//void threadComm::stop()
//{
//  qDebug("Stop signal");
//  exit(0);
//}
//#include <termios.h>
//#include <stdio.h>
//#include <string.h>
//#include <unistd.h>
//#include <fcntl.h>
//#include <errno.h>
//#include <pthread.h>
//#include <stdlib.h>
#define _TTY_POSIX_

#include <QDialog>
#include <QLineEdit>
#include <QLabel>
#include <QGridLayout>
#include <QPushButton>
#include <QShowEvent>
#include <QSettings>
#include <QCheckBox>   
#include <QTimer>
#include <QThread>
#include "qextserialport/qextserialport.h"
#include "c16c.h"

//int init_port (char*);
//void close_port (void);
//int req_ans (u_int8_t*);

//extern int port_fd;
//extern u_int8_t msg1 [100];

//int rx (u_int8_t*, u_int8_t, u_int8_t*, int*, u_int8_t*, u_int8_t*);
//void create_msg (u_int8_t*, u_int8_t);
//void add_cs_msg (u_int8_t*);
//void add_data_msg (u_int8_t*, void*, u_int8_t);
//int tx_msg (u_int8_t*, int);

class loadcells;

class threadComm : public QThread
{
  Q_OBJECT    
  public:
    threadComm(loadcells *);
  public slots:
    void startC();
    void stopC();
  private slots:
    void update();
  signals:
    void started();
    void stopped();    
    void updated();
  protected:
    void run(); 
  private:
    QTimer *timer1;  
    QextSerialPort *port1;
    loadcells *parent;
    void update1(int);
};

class loadcells : public QDialog
{
  Q_OBJECT
public:
  loadcells(clbDialog*);
  QString getNum(int);
  float lastValue(int); //After calibration
  void setValue(float, int);
//  int lastError(); //0 - No error, 1...8 - no answer from loadsell 1..8, 9 - error opening serial port;
  QString getPortName();
private slots:   
    void saveSettings();      
    void loadSettings();    
    void updatedP();
//    void update();
//    void commStart();
//    void commStop();
signals:
//    void tcStop();   
    void started();
    void stopped();
    void updated();
//  void updated();
//  void error();  
private:
  QLineEdit *editPortName;
  QLineEdit *editN1;
  QLineEdit *editN2;
  QLineEdit *editN3;
  QLineEdit *editN4;
  QLineEdit *editN5;
  QLineEdit *editN6;
  QLineEdit *editN7;
  QLineEdit *editN8;
  QLabel *labelPortName; 
  QLabel *labelNN;
  QLabel *labelP1;
  QLabel *labelP2;
  QLabel *labelN1;
  QLabel *labelN2;
  QLabel *labelN3;
  QLabel *labelN4;
  QLabel *labelN5;
  QLabel *labelN6;
  QLabel *labelN7;
  QLabel *labelN8;
  QGridLayout *layout1;
  QPushButton *buttonStart;
  QPushButton *buttonStop;  
  QPushButton *buttonSave;  
  QPushButton *buttonClose;
  QCheckBox *checkAutostart;
  threadComm *tc1;
  QextSerialPort *port1;
  clbDialog *clb1;
  float values[8];
};

Reply to: