Linux串口程序收发16进制数据错误

2019-07-13 09:15发布

问题描述: 在linux下面通过通过C实现串口程序网zigbee中写入16进制数,但是zigbee运行总是接受不到数据,然后通过IAR查看MT_UartProcessZToolData()函数中接收到的数据,发现当我发送0x01时,zigbee接收到的数据为0x81,发送0xfe时,zigbee接收到也是0xfe,但是写写回串口,linux接收到的是0x7f 。数据的最高位出现了问题,然后再x86中使用串口调试工具并未出现这样的状况,所以锁定我linux中串口程序有问题。最后是c_iflag设置错误 /* *Uart.c *串口初始化 */ #include "Uart.h" #include #include #include #include #include #include #include #include #include #include #include /* 宏定义 */ #ifdef DEBUG #define A_OUT printf("%s:%s:%d:", __FILE__, __FUNCTION__,__LINE__);fflush(stdout); #define Printf(fmt, arg...) A_OUT printf(fmt, ##arg) #else #define A_OUT #define Printf(fmt, arg...) #endif /* 全局变量 */ int SerialFd;//保存串口文件描述符 /* ****************************************************************************************** ** 函数名称 : int HW_Uart_Config (int nSpeed, int nBits, char nEvent, int nStop) ** 函数功能 : 设置串口参数 ** 入口参数 : ** nSpeed:波特率 ** nBits:数据位 ** nEvent:奇偶校验位 ** nStop:停止位 ** 出口参数 : -1 设置失败 ** 0 设置成功 ** 函数说明 : 设置串口详细参数 ****************************************************************************************** */ int HW_Uart_Config (int nSpeed, int nBits, char nEvent, int nStop) { struct termios newtio, oldtio; /*tcgetattr(SerialFd,&options)得到与SerialFd指向对象的相关参数, 并将它们保存于oldtio,该函数,还可以测试配置是否正确,该串口是否 可用等。若调用成功,函数返回值为0,若调用失败,函数返回值为1.*/ if (tcgetattr (SerialFd, &oldtio) != 0) { perror ("SetupSerial 1"); return -1; } bzero (&newtio, sizeof (newtio)); //CLOCAL:修改控制模式,保证程序不会占用串口 //CREAD:修改控制模式,使得能够从串口中读取输入数据 newtio.c_cflag |= CLOCAL | CREAD; //设置数据位 newtio.c_cflag &= ~CSIZE; //屏蔽其他标志位 switch (nBits) { case 7: newtio.c_cflag |= CS7; break; case 8: newtio.c_cflag |= CS8; break; } //设置奇偶校验 switch (nEvent) { case 'o': case 'O': //设置为奇校验 newtio.c_cflag |= PARENB; newtio.c_cflag |= PARODD; newtio.c_iflag |= (INPCK | ISTRIP); break; case 'e': case 'E': //设置为偶校验 newtio.c_iflag |= (INPCK | ISTRIP); newtio.c_cflag |= PARENB; newtio.c_cflag &= ~PARODD; break; case 'n': //无奇偶校验位。 case 'N': newtio.c_iflag &= ~INPCK ;//导致数据收发错误是由于这里设置错误, 将c_iflag看出C_cflag newtio.c_cflag &= ~PARENB; // newtio.c_cflag &= ~INPCK;//导致收发数据错误 break; case 'S': case 's': /*as no parity */ newtio.c_cflag &= ~PARENB; newtio.c_cflag &= ~CSTOPB; break; default : return -1; } //设置串口输入波特率和输出波特率 switch (nSpeed) { case 2400: cfsetispeed (&newtio, B2400); cfsetospeed (&newtio, B2400); break; case 4800: cfsetispeed (&newtio, B4800); cfsetospeed (&newtio, B4800); break; case 9600: cfsetispeed (&newtio, B9600); cfsetospeed (&newtio, B9600); break; case 115200: cfsetispeed (&newtio, B115200); cfsetospeed (&newtio, B115200); break; case 460800: cfsetispeed (&newtio, B460800); cfsetospeed (&newtio, B460800); break; default: return -1; } // 设置停止位 switch(nStop) { case 1: newtio.c_cflag &= ~CSTOPB; break; case 2: newtio.c_cflag |= CSTOPB; break; default: return -1; } //设置等待时间和最小接收字符 newtio.c_cc[VTIME] = 0; //读取一个字符等待1*(1/10)s newtio.c_cc[VMIN] = 0; //读取字符的最少个数 //如果不是开发终端之类的,只是串口传输数据, //而不需要串口来处理,那么使用原始模式(Raw Mode)方式来通讯 newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/ newtio.c_oflag &= ~OPOST; /*Output*/ //如果发生数据溢出,接收数据,但是不再读取 tcflush (SerialFd, TCIFLUSH); //激活配置 (将修改后的termios数据设置到串口中) if ((tcsetattr (SerialFd, TCSANOW, &newtio)) != 0) { perror ("com set error"); return -1; } Printf("set done! "); return 0; } /* ****************************************************************************************** ** 函数名称 : int HW_Uart_Open (const char* DevicePath) ** 函数功能 : 打开串口设备 ** 入口参数 : DevicePath: 打开串口的绝对路径 ** 出口参数 : -1 打开失败 ** 打开成功 返回描述符 ** 函数说明 : 以非阻塞的方式打开串口设备 ****************************************************************************************** */ int HW_Uart_Open (const char* DevicePath) { SerialFd = open( DevicePath, O_RDWR | O_NOCTTY | O_NDELAY ); if (-1 == SerialFd) { perror ("Can't Open Serial Port /dev/ttySAC0"); return (-1); } #if 0 if ( fcntl (SerialFd, F_SETFL, 0) < 0 ) Printf ("fcntl failed! "); else Printf ("fcntl=%d ", fcntl (SerialFd, F_SETFL, 0)); if ( 0 == isatty (STDIN_FILENO) ) Printf ("standard input is not a terminal device "); else Printf ("isatty success! "); Printf ("SerialFd-open=%d ", SerialFd); #endif return SerialFd; } /* ****************************************************************************************** ** 函数名称 : int HW_Uart_Close (int SerialFd) ** 函数功能 : 关闭串口设备 ** 入口参数 : SerialFd: 文件描述符 ** 出口参数 : void ** 函数说明 : 无 ****************************************************************************************** */ void HW_Uart_Close(int SerialFd) { close(SerialFd); }