前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++随笔(五)三种实现串口通信的方式

C++随笔(五)三种实现串口通信的方式

作者头像
Pulsar-V
发布2019-08-08 09:33:42
6.7K0
发布2019-08-08 09:33:42
举报
文章被收录于专栏:Pulsar-VPulsar-V

要说最好用的是select的形式,防止漏掉发送过来的数据,缺点是需要单开一条线程独立出来串口服务用来接收数据 一般比较大的工程里还是结合着libevent来用吧。 一般形式

代码语言:javascript
复制
#include <stdio.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>


int set_serial(int fd,int nSpeed,int nBits,char nEvent,int nStop)
{
    struct termios newttys1,oldttys1;

     /*保存原有串口配置*/
     if(tcgetattr(fd,&oldttys1)!=0) 
     {
          perror("Setupserial 1");
          return -1;
     }
     bzero(&newttys1,sizeof(newttys1));
     newttys1.c_cflag|=(CLOCAL|CREAD ); /*CREAD 开启串行数据接收,CLOCAL并打开本地连接模式*/

     newttys1.c_cflag &=~CSIZE;/*设置数据位*/
     /*数据位选择*/   
     switch(nBits)
     {
         case 7:
             newttys1.c_cflag |=CS7;
             break;
         case 8:
             newttys1.c_cflag |=CS8;
             break;
     }
     /*设置奇偶校验位*/
     switch( nEvent )
     {
         case '0':  /*奇校验*/
             newttys1.c_cflag |= PARENB;/*开启奇偶校验*/
             newttys1.c_iflag |= (INPCK | ISTRIP);/*INPCK打开输入奇偶校验;ISTRIP去除字符的第八个比特  */
             newttys1.c_cflag |= PARODD;/*启用奇校验(默认为偶校验)*/
             break;
         case 'E':/*偶校验*/
             newttys1.c_cflag |= PARENB; /*开启奇偶校验  */
             newttys1.c_iflag |= ( INPCK | ISTRIP);/*打开输入奇偶校验并去除字符第八个比特*/
             newttys1.c_cflag &= ~PARODD;/*启用偶校验*/
             break;
         case 'N': /*无奇偶校验*/
             newttys1.c_cflag &= ~PARENB;
             break;
     }
     /*设置波特率*/
    switch( nSpeed )  
    {
        case 2400:
            cfsetispeed(&newttys1, B2400);
            cfsetospeed(&newttys1, B2400);
            break;
        case 4800:
            cfsetispeed(&newttys1, B4800);
            cfsetospeed(&newttys1, B4800);
            break;
        case 9600:
            cfsetispeed(&newttys1, B9600);
            cfsetospeed(&newttys1, B9600);
            break;
        case 115200:
            cfsetispeed(&newttys1, B115200);
            cfsetospeed(&newttys1, B115200);
            break;
        default:
            cfsetispeed(&newttys1, B9600);
            cfsetospeed(&newttys1, B9600);
            break;
    }
     /*设置停止位*/
    if( nStop == 1)/*设置停止位;若停止位为1,则清除CSTOPB,若停止位为2,则激活CSTOPB*/
    {
        newttys1.c_cflag &= ~CSTOPB;/*默认为一位停止位; */
    }
    else if( nStop == 2)
    {
        newttys1.c_cflag |= CSTOPB;/*CSTOPB表示送两位停止位*/
    }

    /*设置最少字符和等待时间,对于接收字符和等待时间没有特别的要求时*/
    newttys1.c_cc[VTIME] = 0;/*非规范模式读取时的超时时间;*/
    newttys1.c_cc[VMIN]  = 0; /*非规范模式读取时的最小字符数*/
    tcflush(fd ,TCIFLUSH);/*tcflush清空终端未完成的输入/输出请求及数据;TCIFLUSH表示清空正收到的数据,且不读取出来 */

     /*激活配置使其生效*/
    if((tcsetattr( fd, TCSANOW,&newttys1))!=0)
    {
        perror("com set error");
        return -1;
    }

    return 0;
}

SINGAL信号形式

代码语言:javascript
复制
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/signal.h>
#include<fcntl.h>
#include<termios.h>
#include<errno.h>
#include <cstring>

#define FALSE -1
#define TRUE 0
#define flag 1
#define noflag 0
int wait_flag = noflag;
int STOP = 0;
int res;
int speed_arr[] = {B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400, B19200, B9600, B4800, B2400, B1200, B300,};
int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200, 9600, 4800, 2400, 1200, 300,};

void set_speed(int fd, int speed) {
    int i;
    int status;
    struct termios Opt;
    tcgetattr(fd, &Opt);
    for (i = 0; i < sizeof(speed_arr) / sizeof(int); i++) {
        if (speed == name_arr[i]) {
            tcflush(fd, TCIOFLUSH);
            cfsetispeed(&Opt, speed_arr[i]);
            cfsetospeed(&Opt, speed_arr[i]);
            status = tcsetattr(fd, TCSANOW, &Opt);
            if (status != 0) {
                perror("tcsetattr fd1");
                return;
            }
            tcflush(fd, TCIOFLUSH);
        }
    }
}

int set_Parity(int fd, int databits, int stopbits, int parity) {
    struct termios options;
    if (tcgetattr(fd, &options) != 0) {
        perror("SetupSerial 1");
        return (FALSE);
    }
    options.c_cflag &= ~CSIZE;
    switch (databits) {
        case 7:
            options.c_cflag |= CS7;
            break;
        case 8:
            options.c_cflag |= CS8;
            break;
        default:
            fprintf(stderr, "Unsupported data size\n");
            return (FALSE);
    }
    switch (parity) {
        case 'n':
        case 'N':
            options.c_cflag &= ~PARENB; /* Clear parity enable */ options.c_iflag &= ~INPCK; /* Enable parity checking */ break;
        case 'o':
        case 'O':
            options.c_cflag |= (PARODD | PARENB);
            options.c_iflag |= INPCK; /* Disnable parity checking */ break;
        case 'e':
        case 'E':
            options.c_cflag |= PARENB; /* Enable parity */ options.c_cflag &= ~PARODD;
            options.c_iflag |= INPCK; /* Disnable parity checking */ break;
        case 'S':
        case 's': /*as no parity */ options.c_cflag &= ~PARENB;
            options.c_cflag &= ~CSTOPB;
            break;
        default:
            fprintf(stderr, "Unsupported parity\n");
            return (FALSE);
    }
    switch (stopbits) {
        case 1:
            options.c_cflag &= ~CSTOPB;
            break;
        case 2:
            options.c_cflag |= CSTOPB;
            break;
        default:
            fprintf(stderr, "Unsupported stop bits\n");
            return (FALSE);
    } /* Set input parity option */ if (parity != 'n') options.c_iflag |= INPCK;
    tcflush(fd, TCIFLUSH);
    options.c_cc[VTIME] = 150;
    options.c_cc[VMIN] = 0; /* Update the options and do it NOW */ if (tcsetattr(fd, TCSANOW, &options) != 0) {
        perror("SetupSerial 3");
        return (FALSE);
    }
    return (TRUE);
}

void signal_handler_IO(int status) {
    printf("received SIGIO signale.\n");
    wait_flag = noflag;
}

int main() {
    printf("This program updates last time at %s %s\n", __TIME__, __DATE__);
    printf("STDIO COM1\n");
    int fd;
    struct sigaction saio;
    fd = open("/dev/ttyUSB0", O_RDWR);
    if (fd == -1) { perror("serialport error\n"); }
    else {
        printf("open ");
        printf("%s", ttyname(fd));
        printf(" succesfully\n");
    }
    saio.sa_handler = signal_handler_IO;
    sigemptyset(&saio.sa_mask);
    saio.sa_flags = 0;
    saio.sa_restorer = NULL;
    sigaction(SIGIO, &saio,
              NULL); //allow the process to receive SIGIO
    fcntl(fd, F_SETOWN,
          getpid()); //make the file descriptor asynchronous
    fcntl(fd, F_SETFL, FASYNC);
    set_speed(fd, 9600);
    if (set_Parity(fd, 8, 1, 'N') == FALSE) {
        printf("Set Parity Error\n");
        exit(0);
    }
    char buf[254]={0};
    while (STOP == 0) {
        usleep(100000); /* after receving SIGIO ,wait_flag = FALSE,input is availabe and can be read */
        if (wait_flag == 0) {
            memset(buf, 0, sizeof(buf));
            res = read(fd, buf, 254);
            if ((int) buf[0] == 85) {
                for (int i = 0; i < 254; i++) {
                    std::cout << std::hex << (int) buf[i] << " ";
                }
                std::cout << std::endl;
            }
//            printf("nread=%d,%s\n", res,buf);
//            if (res ==1)
//             STOP = 1; /*stop loop if only a CR was input */
            wait_flag = flag; /*wait for new input */
        }
    }
    close(fd);
    return 0;
}

select阻塞形式

代码语言:javascript
复制
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/signal.h>
#include<fcntl.h>
#include<termios.h>
#include<errno.h>
#include <cstring>
#include <vector>

#define FALSE -1
#define TRUE 0
#define flag 1
#define noflag 0
int wait_flag = noflag;
int STOP = 0;
int res;
int speed_arr[] = {B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400, B19200, B9600, B4800, B2400, B1200, B300,};
int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200, 9600, 4800, 2400, 1200, 300,};

struct STime stcTime;
struct SAcc stcAcc;
struct SGyro stcGyro;
struct SAngle stcAngle;
struct SMag stcMag;
struct SDStatus stcDStatus;
struct SPress stcPress;
struct SLonLat stcLonLat;
struct SGPSV stcGPSV;

void set_speed(int fd, int speed) {
    int i;
    int status;
    struct termios Opt;
    tcgetattr(fd, &Opt);
    for (i = 0; i < sizeof(speed_arr) / sizeof(int); i++) {
        if (speed == name_arr[i]) {
            tcflush(fd, TCIOFLUSH);
            cfsetispeed(&Opt, speed_arr[i]);
            cfsetospeed(&Opt, speed_arr[i]);
            status = tcsetattr(fd, TCSANOW, &Opt);
            if (status != 0) {
                perror("tcsetattr fd1");
                return;
            }
            tcflush(fd, TCIOFLUSH);
        }
    }
}

int set_Parity(int fd, int databits, int stopbits, int parity) {
    struct termios options;
    if (tcgetattr(fd, &options) != 0) {
        perror("SetupSerial 1");
        return (FALSE);
    }
    options.c_cflag &= ~CSIZE;
    switch (databits) {
        case 7:
            options.c_cflag |= CS7;
            break;
        case 8:
            options.c_cflag |= CS8;
            break;
        default:
            fprintf(stderr, "Unsupported data size\n");
            return (FALSE);
    }
    switch (parity) {
        case 'n':
        case 'N':
            options.c_cflag &= ~PARENB; /* Clear parity enable */ options.c_iflag &= ~INPCK; /* Enable parity checking */ break;
        case 'o':
        case 'O':
            options.c_cflag |= (PARODD | PARENB);
            options.c_iflag |= INPCK; /* Disnable parity checking */ break;
        case 'e':
        case 'E':
            options.c_cflag |= PARENB; /* Enable parity */ options.c_cflag &= ~PARODD;
            options.c_iflag |= INPCK; /* Disnable parity checking */ break;
        case 'S':
        case 's': /*as no parity */ options.c_cflag &= ~PARENB;
            options.c_cflag &= ~CSTOPB;
            break;
        default:
            fprintf(stderr, "Unsupported parity\n");
            return (FALSE);
    }
    switch (stopbits) {
        case 1:
            options.c_cflag &= ~CSTOPB;
            break;
        case 2:
            options.c_cflag |= CSTOPB;
            break;
        default:
            fprintf(stderr, "Unsupported stop bits\n");
            return (FALSE);
    } /* Set input parity option */
    if (parity != 'n') options.c_iflag |= INPCK;
    tcflush(fd, TCIFLUSH);
    options.c_cc[VTIME] = 150;
    options.c_cc[VMIN] = 0; /* Update the options and do it NOW */ if (tcsetattr(fd, TCSANOW, &options) != 0) {
        perror("SetupSerial 3");
        return (FALSE);
    }
    return (TRUE);
}

void signal_handler_IO(int status) {
    printf("received SIGIO signale.\n");
    wait_flag = noflag;
}

class DATA {
    DATA(char type) {

    }
};

int main() {


    std::vector<DATA> info;
    printf("This program updates last time at %s %s\n", __TIME__, __DATE__);
    printf("STDIO COM1\n");
    int fd;
    fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
    if (fd == -1) { perror("serialport error\n"); }
    else {
        printf("open ");
        printf("%s", ttyname(fd));
        printf(" succesfully\n");
    }
    set_speed(fd, 9600);
    if (set_Parity(fd, 8, 1, 'N') == FALSE) {
        printf("Set Parity Error\n");
        exit(0);
    }
    char buf;
    fd_set rd;
    int nread = 0;
//    char buffer[5] = {char(0xff), char(0xaa), char(0x03), char(0x05), char(0x00)};
//    write(fd, buffer, 5);
    int lock = true;
    std::vector<char> data_st;
    while (1) {
        FD_ZERO(&rd);
        FD_SET(fd, &rd);
        while (FD_ISSET(fd, &rd)) {
            if (select(fd + 1, &rd, NULL, NULL, NULL) < 0) {
                perror("select error\n");
            } else {
                while ((nread = read(fd, &buf, sizeof(buf))) > 0) {
                    std::cout << std::hex << (int) buf << std::endl;
                    if (lock && buf != 0x55) {
                        lock=true;
                        continue;
                    } else {
                        lock= false;
//                        data_st.insert(data_st.begin(), (long) 0x55);
                        data_st.push_back((long) buf);
                        if (data_st.size() == 11) {
                            char t_buf[11];
                            std::vector<char>::iterator it;
                            int i = 0;
                            long sum = 0;
                            for (it = data_st.begin(); it < data_st.end(); it++) {
                                t_buf[i] = *it;
                                sum = (long) *it;
                                i++;
                            }
                            data_st.clear();
                            if (sum == (2 * long(t_buf[11]))) {

                            }
                            switch (t_buf[1]) {
                                case 0x51:
                                    memcpy(&stcAcc, &t_buf[2], 8);
                                    std::cout << "0x51 加速度"
                                              << " ax: " << (float) stcAcc.a[0] / 32768 * 16.0 * 9.8
                                              << " ay: " << (float) stcAcc.a[1] / 32768 * 16.0 * 9.8
                                              << " az: " << (float) stcAcc.a[2] / 32768 * 16.0 * 9.8
                                              << " T: " << (float) (stcAcc.T) / 100
                                              << std::endl;
                                    break;
                                case 0x52:
                                    memcpy(&stcGyro, &t_buf[2], 8);
                                    break;
                                case 0x53:
                                    memcpy(&stcAngle, &t_buf[2], 8);
                                    std::cout << "0x53 角度"
                                              << " agx: " << (float) stcAngle.Angle[0] / 32768 * 180
                                              << " agy: " << (float) stcAngle.Angle[1] / 32768 * 180
                                              << " az: " << (float) stcAngle.Angle[2] / 32768 * 180
                                              << " T: " << (float) (stcAngle.T) / 100
                                              << std::endl;
                                    break;
                                case 0x54:
                                    memcpy(&stcMag, &t_buf[2], 8);
                                    std::cout << "0x54 磁场"
                                            " cx: " << (float)stcMag.h[0] <<
                                              " cy: " << (float)stcMag.h[1] <<
                                              " cz: " << (float)stcMag.h[2] <<
                                              " cT:  " << (float)stcMag.T/100
                                              << std::endl;

                                    break;
                                case 0x55:
                                    memcpy(&stcDStatus, &t_buf[2], 8);
                                    std::cout << "0x55" << std::endl;
                                    break;
                                case 0x56:
                                    memcpy(&stcPress, &t_buf[2], 8);
                                    std::cout << "0x56" << std::endl;
                                    break;
                                case 0x57:
                                    memcpy(&stcLonLat, &t_buf[2], 8);
                                    std::cout << "0x57" << std::endl;
                                    break;
                                case 0x58:
                                    memcpy(&stcGPSV, &t_buf[2], 8);
                                    std::cout << "0x58" << std::endl;
                                    break;
                            }

//                            std::vector<char>::iterator it;
//                            for(it=data_st.begin();it<data_st.end();it++){
//                                std::cout<<std::hex<<(int)*it<<" ";
//                            }
//                            std::cout<<std::endl;
//                            exit(0);
                        }
                    }
                }
            }
        }
    }
    close(fd);
    return 0;
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档