Linux serial port listener and interpreter?

2019-01-17 08:49发布

问题:

I'm using a serial device for a project, and what I'm trying to accomplish PC side, is listening for a command sent by the serial device, interpreting the query, running some code depending on the query, and transmitting back the result.

To be honest I tried out using PHP as the listener, and it works, unfortunately the infinite loop required to make the script act as a receiver, loads the CPU to 25%. So it's not really the best option.

I'm using cygwin right now, I'd like to create a bash script using linux native commands.

I can receive data by using:

cat /dev/ttyS2

And send a response with:

echo "command to send" > /dev/ttyS2

My question is, how do I make an automated listener to be able to receive and send data? The main issue I have, is actually how do I stop the cat /dev/ttyS2 command once information was received, put it into a variable which then I could compare with a switch, or a series of if else then blocks. Afterwards send back a response and start the cycle all over again?

Thanks

回答1:

Is this not what you're looking for?

while read -r line < /dev/ttyS2; do
  # $line is the line read, do something with it
  echo $result > /dev/ttyS2
done


回答2:

To remain fairly system independent, use a cross platform programming language: like Python, use a cross platform serial library like : pySerial and do the processing inside a script. I have used pySerial and I could run the script cross platform with almost no changes in source code. By using BASH you're limiting yourself a fair little.



回答3:

If you use right tools, it is possible to actually have your CPU usage to be exactly 0 when your device does not have any output.

To accomplish this, you should use some higher level language (Perl, Python, C/C++ would do, but not bash) and use select loop on top of file handle of your serial device. This is an example for Perl http://perldoc.perl.org/IO/Select.html, but you can use any other language as long as it has support for select() syscall.



回答4:

I would recommend to use C/C++ with Qt 5.1.1, it's really easy and if you are familiar with the framework it'll be a piece of cake!!! Here you can find more information and here more helpful examples, give it a try, it's really pain free!! Also you can develop on win and then port your code to linux...straight forward.

Declare an object like this:

QSerialPort mPort; //remember to #include <QtSerialPort/QSerialPort>
//also add QT += serialport to your .pro file

Then add this code:

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
{
    setupUi(this);


    connect(this->pushButton,SIGNAL(clicked()),this,SLOT(sendData()));

    mPort.setPortName("ttyS0");
    mPort.setBaudRate(QSerialPort::Baud115200);
    mPort.setParity(QSerialPort::EvenParity);

    if(!mPort.open(QSerialPort::ReadWrite))
    {
        this->label->setText(tr("unable to open port, %1").arg(mPort.error()));
    }

    connect(&(this->mPort),SIGNAL(readyRead()),this,SLOT(readData()));
}   

void MainWindow::sendData()
{

    QByteArray data = lineEdit->text().toLatin1();
    if(mPort.isOpen())
    {
        mPort.write(data);
    }
    else
    {
        this->label->setText(tr("port closed %1").arg( mPort.error()));

    }
}


void MainWindow::readData()
{

    QString newData;
    int bread=0;
    while(bread < mPort.bytesAvailable() ){
        newData += mPort.readAll();
        bread++;
    }
  this->textEdit->insertPlainText("\n" + newData);
}