赞
踩
RAW模式与非RAW模式
RAW 模式:
简单的来说,就是发送端发动的二进制码原封不动的被接收端接收。
若干年前使用Windows下的串口调试助手对单片机串口进行调试就是使用的 RAW 模式, 单片机发送的数据被原封不动的发送给 PC 端,PC 端发送的数据也同样原封不动的发送回单片机。
非RAW模式:
非RAW模式下,系统会对串口收到的数据中某些具有特殊意义的字符或组合进行转义。这种工作模式的典型是在 Linux 下使用 minicom 配置交换机或串口登录其他Linux系统。、
- #include <stdio.h>
- #include <string.h>
- #include <sys/types.h>
- #include <errno.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <termios.h>
- #include <stdlib.h>
-
- /* set_opt(fd,115200,8,'N',1) */
- int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
- {
- struct termios newtio,oldtio;
-
- if ( tcgetattr( fd,&oldtio) != 0) { /*0 代表成功 -1代表失败 tcgetattr( fd,&oldtio) != 0 这一步只是用于保存历史文件信息*/
- perror("SetupSerial 1");
- return -1;
- }
-
- bzero( &newtio, sizeof( newtio ) );/* void bzero(void *s, int n); s为内存(字符串)指针,n 为需要清零的字节数*/
- newtio.c_cflag |= CLOCAL | CREAD;
- newtio.c_cflag &= ~CSIZE;
-
- newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/
- newtio.c_oflag &= ~OPOST; /*Output*/
-
- switch( nBits ) //设置数据位
- {
- case 7:
- newtio.c_cflag |= CS7;
- break;
- case 8:
- newtio.c_cflag |= CS8;
- break;
- }
-
- switch( nEvent )
- {
- case 'O': //奇校验
- newtio.c_cflag |= PARENB;
- newtio.c_cflag |= PARODD;
- newtio.c_iflag |= (INPCK | ISTRIP);
- break;
- case 'E': //偶校验
- newtio.c_iflag |= (INPCK | ISTRIP);
- newtio.c_cflag |= PARENB;
- newtio.c_cflag &= ~PARODD;
- break;
- case 'N': //不启用
- newtio.c_cflag &= ~PARENB;
- break;
- }
-
- 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;
- default:
- cfsetispeed(&newtio, B9600);
- cfsetospeed(&newtio, B9600);
- break;
- }
-
- if( nStop == 1 ) //停止位
- newtio.c_cflag &= ~CSTOPB;
- else if ( nStop == 2 )
- newtio.c_cflag |= CSTOPB;
-
- newtio.c_cc[VMIN] = 1; /* 读数据时的最小字节数: 没读到这些数据我就不返回! */
- newtio.c_cc[VTIME] = 0; /* 等待第1个数据的时间:
- * 比如VMIN设为10表示至少读到10个数据才返回,
- * 但是没有数据总不能一直等吧? 可以设置VTIME(单位是10秒)
- * 假设VTIME=1,表示:
- * 10秒内一个数据都没有的话就返回
- * 如果10秒内至少读到了1个字节,那就继续等待,完全读到VMIN个数据再返回
- */
-
- tcflush(fd,TCIFLUSH);/*清空终端未完成的输入/输出请求及数据 flush操作一般在打开或者复位串口设备时进行操作。*/
-
- if((tcsetattr(fd,TCSANOW,&newtio))!=0) /*使用tcsetattr函数将修改后的终端参数设置到标准输入中 TCSANOW:不等数据传输完毕就立即改变属性。*/
- {
- perror("com set error");
- return -1;
- }
- //printf("set done!\n");
- return 0;
- }
-
- int open_port(char *com)
- {
- int fd;
- //fd = open(com, O_RDWR|O_NOCTTY|O_NDELAY);
- fd = open(com, O_RDWR|O_NOCTTY);/*O_NOCTTY 不要控制权*/
- if (-1 == fd){
- return(-1);
- }
-
- if(fcntl(fd, F_SETFL, 0)<0) /* 设置串口为阻塞状态
- *对于read,block指当串口输入缓冲区没有数据的时候,
- *read函数将会阻塞在这里,移植到串口输入缓冲区中有数据可读取,read读到了需要的字节数之后,返回值为读到的字节数;
- */
- {
- printf("fcntl failed!\n");
- return -1;
- }
-
- return fd;
- }
-
-
- /*
- * ./serial_send_recv <dev>
- */
- int main(int argc, char **argv)
- {
- int fd;
- int iRet;
- char c;
-
- /* 1. open */
-
- /* 2. setup
- * 115200,8N1
- * RAW mode
- * return data immediately
- */
-
- /* 3. write and read */
-
- if (argc != 2)
- {
- printf("Usage: \n");
- printf("%s </dev/ttySAC1 or other>\n", argv[0]);
- return -1;
- }
-
- fd = open_port(argv[1]);
- if (fd < 0)
- {
- printf("open %s err!\n", argv[1]);
- return -1;
- }
-
- iRet = set_opt(fd, 115200, 8, 'N', 1);
- if (iRet)
- {
- printf("set port err!\n");
- return -1;
- }
-
- printf("Enter a char: ");
- while (1)
- {
- scanf("%c", &c);
- iRet = write(fd, &c, 1);
- iRet = read(fd, &c, 1);
- if (iRet == 1)
- printf("get: %02x %c\n", c, c);/*X 表示以十六进制形式输出 02 表示不足两位,前面补0输出;如果超过两位,则实际输出*/
- else
- printf("can not get data\n");
- }
-
- return 0;
- }
-
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。