- A+
所属分类:linux技术
在嵌入式应用领域中,串口是最为常见的一种硬件通信接口。因为其具备协议简单,硬件电路精简等优势使得串口基本成为MCU、计算机或嵌入式产品的标配接口。本文仅介绍在Linux系统下串口编程需要使用的API和一些应用技巧,关于串口的背景知识介绍,以及Windows系统下串口编程读者可以移步至其他文章。
Linux系统下串口的操作主要分为如下部分:
- 串口打开、关闭
- 串口参数设置
- 串口数据发送与接收
- 串口MODEM信号设置与读取
- 串口Break信号发送
可以熟练掌握并应用以上串口功能已经可以应对Linux系统上串口应用的大多数场景了,针对更高级的串口用法可以阅读《Linux串口编程-进阶篇》,包含Linux系统使用非标准波特率、同步等待Modem信号变化、串口参数VTIME和VMIN的作用、RS485串口功能开关等。为方便用户使用我们将以上串口操作均封装成了独立的函数,可以极大的节约开发时间。
1、串口打开
/** * libtty_open - open tty device * @devname: the device name to open * * In this demo device is opened blocked, you could modify it at will. */ static int libtty_open(const char *devname) { int fd = open(devname, O_RDWR | O_NOCTTY | O_NDELAY); int flags = 0; if (fd < 0) { perror("open device failed"); return -1; } /* 恢复串口为阻塞状态 */ flags = fcntl(fd, F_GETFL, 0); flags &= ~O_NONBLOCK; if (fcntl(fd, F_SETFL, flags) < 0) { printf("fcntl failed.n"); return -1; } /* 测试该设备是否为tty设备 */ if (isatty(fd) == 0) { printf("not tty device.n"); return -1; } else printf("tty device test ok.n"); return fd; }
Note:
- devname 参数为设备绝对路径,如:“/dev/ttyUSB0”
- O_NOCTTY标志用于通知系统,这个程序不会成为对应这个设备的控制终端。如果没有指定这个标志,那么任何一个输入(如SIGINT等)都将会影响用户的进程;
- O_NDELAY标志与O_NONBLOCK 等效,但这里不仅仅是设置为非阻塞,还用于通知系统,这个程序不关心 DCD 信号线所处的状态(即与设备相连的另一端是否激活或者停止)。如果用户指定了这一标志,则进程将会一直处在休眠状态,直到 DCD 信号线被激活;
2、串口关闭
/** * libtty_close - close tty device * @fd: the device handle * * The function return 0 if success, others if fail. */ static int libtty_close(int fd) { return close(fd); }
3、串口设置
/** * libtty_setopt - config tty device * @fd: device handle * @speed: baud rate to set * @databits: data bits to set * @stopbits: stop bits to set * @parity: parity to set * @hardflow: hardflow to set * * The function return 0 if success, or -1 if fail. */ static int libtty_setopt(int fd, int speed, int databits, int stopbits, char parity, char hardflow) { struct termios newtio; struct termios oldtio; int i; bzero(&newtio, sizeof(newtio)); bzero(&oldtio, sizeof(oldtio)); /* 先保存之前配置,以防后续步骤出错无法恢复 */ if (tcgetattr(fd, &oldtio) != 0) { perror("tcgetattr"); return -1; } newtio.c_cflag |= CLOCAL | CREAD; newtio.c_cflag &= ~CSIZE; /* 串口波特率设置*/ switch (speed): { case 1200: cfsetspeed(&newtio, B1200); break; case 2400: cfsetspeed(&newtio, B2400); break; case 4800: cfsetspeed(&newtio, B4800); break; case 9600: cfsetspeed(&newtio, B9600); break; case 19200: cfsetspeed(&newtio, B19200); break; case 38400: cfsetspeed(&newtio, B38400); break; case 57600: cfsetspeed(&newtio, B57600); break; case 115200: cfsetspeed(&newtio, B115200); break; case 230400: cfsetspeed(&newtio, B230400); break; case 460800: cfsetspeed(&newtio, B460800); break; case 921600: cfsetspeed(&newtio, B921600); break; default: