mini2440下串口读写

时间:2022-01-07 04:26:20

折腾这个折腾了好几天的时间,功夫不负有心人,终于还是折腾出来了。关于串口的实现,涉及的比较多,不过也没有想象中的那么难。之所以折腾那么就,主要还是犯了一个很低级的出错,就是在读数据的时候老出错(写数据老早就可以了,幸庆自己还有那么一点完美主义)。一开是使用的是网上广泛流传的那个文件包叫“qextserialport-1.2win-alpha”,用到了里面的几个文件。 posix_qextserialport.h qextserialbase.h qetserialport.h 以及其对应的.cpp文件。 这些文件里面已经写好了对串口的初始化,打开,关闭,读写等等。可是我觉得内容太多,很多功能和我要实现的简单收发功能不相关。   

在这里用到的关于串口的分别是:termios,tcgetattr,tcsetattr,tcsendbreak,tcdrain,tcflush,tcflow,cfmakeraw,
cfgetospeed,cfgetispeed,cfsetispeed,cfsetospeed。
分别对其进行分析:
其原型为:

int tcgetattr(int fd, struct termios *termios_p);

int tcsetattr(int fd, int optional_actions, struct termios *termios_p);

int tcsendbreak(int fd, int duration);

int tcdrain(int fd);

int tcflush(int fd, int queue_selector);

int tcflow(int fd, int action);

int cfmakeraw(struct termios *termios_p);

speed_t cfgetispeed(struct termios *termios_p);

speed_t cfgetospeed(struct termios *termios_p);

int cfsetispeed(struct termios *termios_p, speed_t speed);

int cfsetospeed(struct termios *termios_p, speed_t speed);

作用:

tcgetattr() 得到与 fd 指向的对象相关的参数,将它们保存于 termios_p 引用的 termios 结构中。函数可以从后台进程中调用;但是,终端属性可能被后来的前台进程所改变。

tcsetattr() 设置与终端相关的参数 (除非需要底层支持却无法满足)。

tcsendbreak() 传送连续的 0 值比特流,持续一段时间,如果终端使用异步串行数据传输的话。如果 duration 是 0,它至少传输 0.25 秒,不会超过 0.5 秒。如果 duration 非零,它发送的时间长度由实现定义。

如果终端并非使用异步串行数据传输,tcsendbreak() 什么都不做。

tcdrain() 等待直到所有写入 fd 引用的对象的输出都被传输。

tcflush() 丢弃要写入 引用的对象,但是尚未传输的数据,或者收到但是尚未读取的数据,取决于 queue_selector 的值:

刷新收到的数据但是不读 刷新写入的数据但是不传送 同时刷新收到的数据但是不读,并且刷新写入的数据但是不传送。

tcflow() 挂起 fd 引用的对象上的数据传输或接收,取决于 action 的值:

挂起输出 重新开始被挂起的输出 发送一个 STOP 字符,停止终端设备向系统传送数据 发送一个 START 字符,使终端设备向系统传输数据 。
cfmakeraw()设置终端属性,就是设置termios结构中的各个参数。
cfgetospeed() 返回 termios 结构中存储的输出波特率。
cfsetospeed() 设置  termios 结构中存储的输出波特率为 speed,必须是这样的格式“B115200”。
cfsetispeed() 设置 termios 结构中存储的输入波特率为 speed。如果输入波特率被设为0,实际输入波特率将等于输出波特率。

 

下面是我的程序:

 fd_gps = ::open("/dev/ttySAC1", O_RDWR | O_NOCTTY | O_NONBLOCK); //打开串口1
    if (fd_gps<0)
    {
             perror("open serial error!/n");
    }

    tcgetattr(fd_gps,&gps_opt); //初始化
    bzero(&gps_opt, sizeof(gps_opt));

    cfsetispeed(&gps_opt,B9600); //设置波特率 uartbiit[baud]
    cfsetospeed(&gps_opt,B9600);

    gps_opt.c_cflag |=(CLOCAL|CREAD);//忽略MODEM控制线,打开接受者
    gps_opt.c_cflag &= ~CRTSCTS;
    gps_opt.c_cflag &= ~CSIZE;
    gps_opt.c_cflag |= CS8;   //设置8数据位
    gps_opt.c_cflag &= ~PARENB; //无奇偶校检
    gps_opt.c_cflag &= ~CSTOPB;

    //不是开发终端之类的,只是串口传输数据,而不需要串口来处理
    gps_opt.c_oflag &= ~(OPOST); //选择原始数据输出
    gps_opt.c_lflag &= ~(ICANON|ISIG|ECHO|ECHOE);//设置原始输入模式
    gps_opt.c_iflag &= ~(INPCK|BRKINT|ICRNL|ISTRIP|IXON);

    gps_opt.c_cc[VMIN] = 0; //指定了最少读取的字符数,如果设置为0,那么VTIME 就指定了读取每个字符的等待时间
    gps_opt.c_cc[VTIME] = 0;

    tcflush(fd_gps,TCIOFLUSH);//刷新
    if (tcsetattr(fd_gps,TCSANOW,&gps_opt) != 0)    //装载初始化参数
    {
       perror("Setup Serial Error!/n");
       ::close(fd_gps);
    }

    readgpstimer = new QTimer(this);
    connect(readgpstimer,SIGNAL(timeout()),this,SLOT(readgpsCom()));
    //关联定时器计满信号和相应的槽函数
    readgpstimer->start(100);
    //定时器开始计时,其中100表示100ms
}

void DriveInfo::open_gprscom()
{

    fd_gprs = ::open("/dev/ttySAC2", O_RDWR | O_NOCTTY | O_NONBLOCK); //打开串口2
    if (fd_gprs<0)
    {
             perror("open serial error!/n");
    }

    tcgetattr(fd_gprs,&gprs_opt); //初始化
    bzero(&gprs_opt, sizeof(gprs_opt));//置字符串前sizeof个字为零

    cfsetispeed(&gprs_opt,B115200); //设置波特率 uartbiit[baud]
    cfsetospeed(&gprs_opt,B115200);

    gprs_opt.c_cflag |=(CLOCAL|CREAD);//忽略MODEM控制线,打开接受者
    gprs_opt.c_cflag &= ~CRTSCTS;
    gprs_opt.c_cflag &= ~CSIZE;
    gprs_opt.c_cflag |= CS8;   //设置8数据位
    gprs_opt.c_cflag &= ~PARENB; //无奇偶校检
    gprs_opt.c_cflag &= ~CSTOPB;

    //不是开发终端之类的,只是串口传输数据,而不需要串口来处理
    gprs_opt.c_oflag &= ~(OPOST); //选择原始数据输出
    gprs_opt.c_lflag &= ~(ICANON|ISIG|ECHO|ECHOE);//设置原始输入模式
    gprs_opt.c_iflag &= ~(INPCK|BRKINT|ICRNL|ISTRIP|IXON);

    gprs_opt.c_cc[VMIN] = 0; //指定了最少读取的字符数,如果设置为0,那么VTIME 就指定了读取每个字符的等待时间
    gprs_opt.c_cc[VTIME] = 0;

    tcflush(fd_gprs,TCIOFLUSH);//刷新
    if (tcsetattr(fd_gprs,TCSANOW,&gprs_opt) != 0)    //装载初始化参数
    {
       perror("Setup Serial Error! /n");
       ::close(fd_gprs);
    }


    readgprstimer = new QTimer(this);
    connect(readgprstimer,SIGNAL(timeout()),this,SLOT(readgprsCom()));
    //关联定时器计满信号和相应的槽函数
    readgprstimer->start(100);
    //定时器开始计时,其中100表示100ms

 

此程序在mini2440下正常收发数据。