linux虚拟串口

Linux下的虚拟终端(可用于在本机上模拟串口进行调试)

http://blog.sina.com.cn/s/blog_6cb543ef0100x90j.html

Linux虚拟串口 及 Qt串口通信

https://www.xuebuyuan.com/1053146.html

Python语言:


#! /usr/bin/env python
#coding=utf-8

import pty
import os
import select

def mkpty():
    # 打开伪终端
    master1, slave = pty.openpty()
    slaveName1 = os.ttyname(slave)
    master2, slave = pty.openpty()
    slaveName2 = os.ttyname(slave)
    print '\nslave device names: ', slaveName1, slaveName2
    return master1, master2

if __name__ == "__main__":

    master1, master2 = mkpty()
    while True:
        rl, wl, el = select.select([master1,master2], [], [], 1)
        for master in rl:
            data = os.read(master, 128)
            print "read %d data." % len(data)
            if master==master1:
                os.write(master2, data)
            else:
                os.write(master1, data)


      程序名叫mkptych.py,在终端里运行“python mkptych.py &”,这样就可以生成一个基于pty(伪终端)的虚拟端口对,两个设备名会显示在终端里。然后就可以利用这两个设备名在本机上进行虚拟串口之类的调试,使用完后用ps查看这个python进程的pid号,然后kill掉即可。
      下面编写一个用上述虚拟串口的使用程序:
      //receive.c
      #include <stdio.h>
      #include <string.h>
      #include <malloc.h>
      #include <sys/types.h>
      #include <sys/stat.h>
      #include <fcntl.h>
      #include <unistd.h>
      #include <termios.h>
      #include <math.h>

      #define MAX_BUFFER_SIZE 512

      int fd, s;

      int open_serial()
      {
            //这里的/dev/pts/2是使用mkptych.py虚拟的两个串口名字之一
            fd = open("/dev/pts/2", O_RDWR|O_NOCTTY|O_NDELAY);
            if(fd == -1)
            {
                  perror("open serial port error!\n");
                  return -1;
            }

            printf("open /dev/ttyS0.\n");
            return 0;
      }

      int main()
      {
            char hd[MAX_BUFFER_SIZE], *rbuf;
            int flag_close, retv;
            struct termios opt;

            retv = open_serial();
            if(retv < 0)
            {
                  printf("Open serrial port error!\n");
                  return -1;
            }

            tcgetattr(fd, &opt);
            cfmakeraw(&opt);
            cfsetispeed(&opt, B9600);
            cfsetospeed(&opt, B9600);
            tcsetattr(fd, TCSANOW, &opt);
            rbuf = hd;
            printf("Ready for receiving data...\n");

            while(1)
            {
                  while((retv = read(fd, rbuf, 1)) > 0)
                        printf( "%c ", *rbuf);
            }

            printf("\n");
            flag_close = close(fd);
            if(flag_close == -1)
                  printf("Close the device failure!\n");

            return 0;
      }

      //send.c
      #include <stdio.h>
      #include <string.h>
      #include <malloc.h>
      #include <sys/types.h>
      #include <sys/stat.h>
      #include <fcntl.h>
      #include <unistd.h>
      #include <termios.h>

      #define MAX_BUFFER_SIZE 512

      int fd, flag_close;

      int open_serial()
      {
            //这里的/dev/pts/1是使用mkptych.py虚拟的两个串口名字之一
            fd = open("/dev/pts/1", O_RDWR | O_NOCTTY | O_NONBLOCK);
            if(fd == -1)
            {
                  perror("open serial port error!\n");
                  return -1;
            }

            printf("Open serial port success!");
            return 0;
      }

      int main(int argc, char* argv[])
      {
            char sbuf[] = {"Hello, this is a serial port test!\n"};
            int retv;
            struct termios option;

            retv = open_serial();
            if(retv < 0)
            {
                  perror("open serial port error!\n");
                  return -1;
            }

            printf("Ready for sending data...\n");

            tcgetattr(fd, &option);
            cfmakeraw(&option);

            cfsetispeed(&option, B9600);
            cfsetospeed(&option, B9600);

            tcsetattr(fd, TCSANOW, &option);

            int length = sizeof(sbuf);
            retv = write(fd, sbuf, length);
            if(retv == -1)
            {
                  perror("Write data error!\n");
                  return -1;
            }

            printf("The number of char sent is %d\n", retv);
            return 0;
      }
      编译运行即可,呵呵

Linux虚拟串口 及 Qt串口通信

由于手上没有可以测试的串口设备,因此发了点时间找了一个Linux下的虚拟串口工具:http://fayaa.com/code/view/8500/

这个工具打开了两个伪终端,然后读两个口子的数据,如果是从1号口来的,就往2号口写入数据,从2号口来的就写到1号口。

经过我的修改后变成了这个样子:

#! /usr/bin/env python

#coding=utf-8

import pty
import os
import select

def mkpty():
    #
    master1, slave = pty.openpty()
    slaveName1 = os.ttyname(slave)
    master2, slave = pty.openpty()
    slaveName2 = os.ttyname(slave)
    print '/nslave device names: ', slaveName1, slaveName2
    return master1, master2

if __name__ == "__main__":

    master1, master2 = mkpty()
    while True:       
        rl, wl, el = select.select([master1,master2], [], [], 1)
        for master in rl:
            data = os.read(master, 128)
            if master==master1:
                print "read %d data:" % len(data)
                print data
                #os.write(master2, data)
            else:
                print "to write %d data:" % len(data)
                print data.strip()
                os.write(master1, data.strip())
改变后 我们让1号口为读入口(串口设备读入数据的口子),2号口为写出口(串口向外面写数据)

将其保存为com.py

#python com.py

slave device names:  /dev/pts/1 /dev/pts/2
意思是pts/1为1号口 pts/2为2号口

另建一个终端 #cd /dev/pts/

#echo 456 > 2

就会向2号口写数据,如果我们没有其他程序读串口的数据的话,那么就会出现4行数:

to write 5 data:
456
read 3 data:
456
那么我们只要用程序读/dev/pts/1就可以模拟串口通信了

============================================================

Qt下的串口通讯

Qt没有自带串口模块,只有第三方库

http://wenku.baidu.com/view/55849f4ffe4733687e21aa99.html

这篇文章介绍了简单的Qt串口通信

学着他的例子也做了一个程序,核心代码:

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    com = new QextSerialPort("/dev/pts/1", QextSerialPort::Polling);
    com->open(QextSerialPort::ReadWrite);
    com->setBaudRate(BAUD9600);
    com->setDataBits(DATA_8);
    com->setParity(PAR_NONE);
    com->setStopBits(STOP_1);
    com->setFlowControl(FLOW_OFF);
    com->setTimeout(10);

    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(readCOM()));
    timer->start(20);

}

void MainWindow::readCOM()
{
    if (com->bytesAvailable() > 1)
        ui->showText->insertPlainText(com->readAll());
}

void MainWindow::on_btnSend_clicked()
{
    com->write(ui->edit->text().toAscii().data());
}

运行结果:

Qt向串口写数据

linux虚拟串口

收到数据:

linux虚拟串口

 

串口向Qt写数据(下面那个终端控制)

linux虚拟串口

==========================================================

注意:1号口和2号口的方向问题很难分清楚,暂时这样理解了没必要深究

           windows下的虚拟串口工具为VSPM,是Telnet管理的,建议先研究这个