Ubuntu 17.04编译串口发送16进制数据包报了个神奇的错误
来源:互联网 发布:python 获取 roe 编辑:程序博客网 时间:2024/06/06 02:54
调试系统环境:Ubuntu 17.04 + Clion 17.1
今天在调试Ubuntu 系统通过串口发送16进制数据时,我发现了一个很神奇的问题现象。
先看看下面的代码:
//char *data = "hello world dhs!"; char data[9] = {0x11,0x22,0x33,0x11,0x22,0x33,0x11,0x22,0x33}; //data[0] = 0xAA; //int datalen = strlen(data); //send data //while (1) { for (int i = 0; i < 100; i++) { SendLen = PortSend(fd, data, 9); if (SendLen > 0) { printf("No %d send %d data.\n", i, SendLen); } else { printf("Error: send failed.\n"); } sleep(1); } }
然后在Clion 中进行编译,发现编译很完美,并能够通过 xgcom(一款Linux下的带GUI的串口调试助手)接收到16进制数据。
再看看以下代码:
//char *data = "hello world dhs!"; char data[2] = {0x11,0x22,0x33,0x11,0x22,0x33,0x11,0x22,0x88}; //data[0] = 0xAA; //int datalen = strlen(data); //send data //while (1) { for (int i = 0; i < 100; i++) { SendLen = PortSend(fd, data, 2); if (SendLen > 0) { printf("No %d send %d data.\n", i, SendLen); } else { printf("Error: send failed.\n"); } sleep(1); } }
然后再Clion中编译源代码时,就发现报错了,错误信息如下:
/home/dhs/桌面/serial_dhs/serail (cpp)/serial.cpp:305:66: error: narrowing conversion of ‘136’ from ‘int’ to ‘char’ inside { } [-Wnarrowing] char data[9] = {0x11,0x22,0x33,0x11,0x22,0x33,0x11,0x22,0x88}; ^CMakeFiles/serail.dir/build.make:62: recipe for target 'CMakeFiles/serail.dir/serial.cpp.o' failedmake[3]: *** [CMakeFiles/serail.dir/serial.cpp.o] Error 1CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/serail.dir/all' failedmake[2]: *** [CMakeFiles/serail.dir/all] Error 2CMakeFiles/Makefile2:79: recipe for target 'CMakeFiles/serail.dir/rule' failedmake[1]: *** [CMakeFiles/serail.dir/rule] Error 2Makefile:118: recipe for target 'serail' failedmake: *** [serail] Error 2经过我多次测试,终于发现了一个很神奇的错误现象。
当发送的16进制数据包中有数据大于255时,便会编译报错。
因此,我认为在串口发送16进制数据时可能使用了int数据类型作转换,也就是说在同类的程序中也很有可能会发生这种错误。
所以,我在此将其提出,一是想给自己一个警示,同时也是希望能够解决它的数据传输问题。(问题是我需要收发16进制数据形式的大小超过255.。。。)
最后,我把整个的代码贴出来如下(主要是在网上找改的程序):
#include <stdio.h> // printf #include <fcntl.h> // open #include <string.h> // bzero #include <stdlib.h> // exit #include <sys/times.h> // times #include <sys/types.h> // pid_t #include <termios.h> //termios, tcgetattr(), tcsetattr()#include <unistd.h>#include <sys/ioctl.h> // ioctl#define TTY_DEV "/dev/ttyUSB" //端口路径#define TIMEOUT_SEC(buflen,baud) (buflen*20/baud+2) //接收超时 #define TIMEOUT_USEC 0//串口结构typedef struct{ char prompt; //prompt after reciving data int baudrate; //baudrate char databit; //data bits, 5, 6, 7, 8 char debug; //debug mode, 0: none, 1: debug char echo; //echo mode, 0: none, 1: echo char fctl; //flow control, 0: none, 1: hardware, 2: software char tty; //tty: 0, 1, 2, 3, 4, 5, 6, 7 char parity; //parity 0: none, 1: odd, 2: even char stopbit; //stop bits, 1, 2 const int reserved; //reserved, must be zero}portinfo_t;typedef portinfo_t *pportinfo_t;/** * 打开串口,返回文件描述符 * pportinfo: 待设置的串口信息*/int PortOpen(pportinfo_t pportinfo);/** * 设置串口 * fdcom: 串口文件描述符, pportinfo: 待设置的串口信息*/int PortSet(int fdcom, const pportinfo_t pportinfo);/** * 关闭串口 * fdcom:串口文件描述符*/void PortClose(int fdcom);/** * 发送数据 * fdcom:串口描述符, data:待发送数据, datalen:数据长度 * 返回实际发送长度*/int PortSend(int fdcom, char *data, int datalen);/** * 接收数据 * fdcom:串口描述符, data:接收缓冲区, datalen:接收长度, baudrate:波特率 * 返回实际读入的长度*/int PortRecv(int fdcom, char *data, int datalen, int baudrate);/******************************************* * 获得端口名称 ********************************************/char *get_ptty(pportinfo_t pportinfo){ char *ptty; switch(pportinfo->tty){ case '0':{ ptty = TTY_DEV"0"; }break; case '1':{ ptty = TTY_DEV"1"; }break; case '2':{ ptty = TTY_DEV"2"; }break; } return(ptty);}/******************************************* * 波特率转换函数(请确认是否正确) ********************************************/int convbaud(unsigned long int baudrate){ switch(baudrate){ case 2400: return B2400; case 4800: return B4800; case 9600: return B9600; case 19200: return B19200; case 38400: return B38400; case 57600: return B57600; case 115200: return B115200; default: return B9600; }}/******************************************* * Setup comm attr * fdcom: 串口文件描述符,pportinfo: 待设置的端口信息(请确认) * ********************************************/int PortSet(int fdcom, const pportinfo_t pportinfo){ struct termios termios_old, termios_new; int baudrate, tmp; char databit, stopbit, parity, fctl; bzero(&termios_old, sizeof(termios_old)); bzero(&termios_new, sizeof(termios_new)); cfmakeraw(&termios_new); tcgetattr(fdcom, &termios_old); //get the serial port attributions /*------------设置端口属性----------------*/ //baudrates baudrate = convbaud(pportinfo->baudrate); cfsetispeed(&termios_new, baudrate); //填入串口输入端的波特率 cfsetospeed(&termios_new, baudrate); //填入串口输出端的波特率 termios_new.c_cflag |= CLOCAL; //控制模式,保证程序不会成为端口的占有者 termios_new.c_cflag |= CREAD; //控制模式,使能端口读取输入的数据 // 控制模式:flow control fctl = pportinfo-> fctl; switch(fctl){ case '0':{ termios_new.c_cflag &= ~CRTSCTS; //no flow control }break; case '1':{ termios_new.c_cflag |= CRTSCTS; //hardware flow control }break; case '2':{ termios_new.c_iflag |= IXON | IXOFF |IXANY; //software flow control }break; } //控制模式,data bits termios_new.c_cflag &= ~CSIZE; //控制模式,屏蔽字符大小位 databit = pportinfo -> databit; switch(databit){ case '5': termios_new.c_cflag |= CS5; case '6': termios_new.c_cflag |= CS6; case '7': termios_new.c_cflag |= CS7; default: termios_new.c_cflag |= CS8; } //控制模式 parity check parity = pportinfo -> parity; switch(parity){ case '0':{ termios_new.c_cflag &= ~PARENB; //no parity check }break; case '1':{ termios_new.c_cflag |= PARENB; //odd check termios_new.c_cflag &= ~PARODD; }break; case '2':{ termios_new.c_cflag |= PARENB; //even check termios_new.c_cflag |= PARODD; }break; } //控制模式,stop bits stopbit = pportinfo -> stopbit; if(stopbit == '2'){ termios_new.c_cflag |= CSTOPB; //2 stop bits } else{ termios_new.c_cflag &= ~CSTOPB; //1 stop bits } //other attributions default termios_new.c_oflag &= ~OPOST; //输出模式, 原始数据输出 termios_new.c_cc[VMIN] = 0; //控制字符, 所要读取字符的最小数量 termios_new.c_cc[VTIME] = 1; //控制字符, 读取第一个字符的等待时间 unit: (1/10)second tcflush(fdcom, TCIFLUSH); //溢出的数据可以接收,但不读 tmp = tcsetattr(fdcom, TCSANOW, &termios_new); //设置新属性,TCSANOW:所有改变立即生效 //tcgetattr(fdcom, &termios_old); return(tmp);}/******************************************* * Open serial port * tty: 端口号 ttyS0, ttyS1, .... * 返回值为串口文件描述符 ********************************************/int PortOpen(pportinfo_t pportinfo){ int fdcom; //串口文件描述符 char *ptty; ptty = get_ptty(pportinfo); //fdcom = open(ptty, O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY); fdcom = open(ptty, O_RDWR | O_NOCTTY | O_NONBLOCK); return (fdcom);}/******************************************* * Close serial port ********************************************/void PortClose(int fdcom){ close(fdcom);}/******************************************** * send data * fdcom: 串口描述符,data: 待发送数据,datalen: 数据长度 * 返回实际发送长度 *********************************************/int PortSend(int fdcom, char *data, int datalen){ int len = 0; len = write(fdcom, data, datalen); //实际写入的长度 if(len == datalen){ return (len); } else{ tcflush(fdcom, TCOFLUSH); return -1; }}/******************************************* * receive data * 返回实际读入的字节数 * ********************************************/int PortRecv(int fdcom, char *data, int datalen, int baudrate){ int readlen, fs_sel; fd_set fs_read; struct timeval tv_timeout; FD_ZERO(&fs_read); FD_SET(fdcom, &fs_read); tv_timeout.tv_sec = TIMEOUT_SEC(datalen, baudrate); tv_timeout.tv_usec = TIMEOUT_USEC; fs_sel = select(fdcom + 1, &fs_read, NULL, NULL, &tv_timeout); if(fs_sel){ readlen = read(fdcom, data, datalen); return(readlen); } else{ return(-1); } //return (readlen);}//*************************Test********************************* int main(int argc, char *argv[]) { int fd = -1, SendLen = 0, RecvLen = 0; struct termios termios_cur; char RecvBuf[10] = {0}; portinfo_t portinfo = { '0', // print prompt after receiving 9600, // baudrate: 9600 '8', // databit: 8 '0', // debug: off '1', // echo: on '1', // flow control: hardware '0', // default tty: COM1 '0', // parity: none '1', // stopbit: 1 0 // reserved }; /* if(argc != 2){ printf("Usage: <type 0 -- send 1 -- receive>\n"); printf(" eg:"); printf(" MyPort 0"); exit(-1); } */ fd = PortOpen(&portinfo); if (fd < 0) { printf("Error: open serial port error.\n"); exit(1); } PortSet(fd, &portinfo); //char *data = "hello world dhs!"; char data[9] = {0x11,0x22,0x33,0x11,0x22,0x33,0x11,0x22,0x88}; //data[0] = 0xAA; int datalen = strlen(data); //send data //while (1) { for (int i = 0; i < 100; i++) { SendLen = PortSend(fd, data, 9); if (SendLen > 0) { printf("No %d send %d data.\n", i, SendLen); } else { printf("Error: send failed.\n"); } sleep(1); } } PortClose(fd); /** for(;;) { RecvLen = PortRecv(fd, RecvBuf, 10, portinfo.baudrate); if(RecvLen>0){ for(i=0; i<RecvLen; i++){ printf("Receive data No %d is %x.\n", i, RecvBuf[i]); } printf("Total frame length is %d.\n", RecvLen); } else{ printf("E rror: receive error.\n"); } sleep(2); } */ return 0;}
阅读全文
0 0
- Ubuntu 17.04编译串口发送16进制数据包报了个神奇的错误
- Ubuntu 17.04编译串口发送16进制数据包报了个神奇的错误—续
- Python3 串口接收与发送16进制数据包
- 串口通信数据发送--字符发送和16进制发送--发送字节的间隔时间
- nRF24LE1 串口调试成功 发送数据包
- QT串口发送错误
- 串口网口16进制发送的和ASCII发送的区别
- 串口发送16进制数据
- 怎么把一个结构体的数据包通过串口发送出去?
- 神奇的编译原理
- 一份发送数据包的源代码
- 发送超过1500的数据包
- virtio-netdev 数据包的发送
- ip数据包的发送流程
- 一个数据包发送的旅程
- 神奇的'asdf;'错误
- PDU编码的短信终于通过串口成功发送了
- 读取arm串口时读到了发送的数据
- makefile基础教程
- git clone之后输入git status报错:没有找到.git文件
- XYNUOJ 找明星
- vs2013 error C4996: 'fopen': This function or variable may be unsafe.
- xutils的使用
- Ubuntu 17.04编译串口发送16进制数据包报了个神奇的错误
- XListview上拉刷新,下拉加载
- POJ2528 线段树 区间更新 离散化
- 华容道
- 思考接入sdk接口的提取
- POJ.1330 Nearest Common Ancestors (LCA 倍增)
- Windows服务器启动Tomcat时,设置编码和将控制台输出到log文件
- (Visual Studio)VS2015括号颜色更改
- QAQ & ORZ 的签到题