如何从C中的串口打开,读取和写入
我对读写串口有些困惑。 我在Linux中有一个使用FTDI USB串行设备转换器驱动程序的USB设备。 当我插入时,它会创build:/ dev / ttyUSB1。
我认为它很容易在C中打开和读写。我知道波特率和奇偶校验信息,但似乎没有标准呢?
我是否错过了某些东西,或者有人能指出我的方向?
我很久以前写了这个,只是复制和粘贴每个项目所需的位。
#include <errno.h> #include <fcntl.h> #include <string.h> #include <termios.h> #include <unistd.h> int set_interface_attribs (int fd, int speed, int parity) { struct termios tty; memset (&tty, 0, sizeof tty); if (tcgetattr (fd, &tty) != 0) { error_message ("error %d from tcgetattr", errno); return -1; } cfsetospeed (&tty, speed); cfsetispeed (&tty, speed); tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit chars // disable IGNBRK for mismatched speed tests; otherwise receive break // as \000 chars tty.c_iflag &= ~IGNBRK; // disable break processing tty.c_lflag = 0; // no signaling chars, no echo, // no canonical processing tty.c_oflag = 0; // no remapping, no delays tty.c_cc[VMIN] = 0; // read doesn't block tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls, // enable reading tty.c_cflag &= ~(PARENB | PARODD); // shut off parity tty.c_cflag |= parity; tty.c_cflag &= ~CSTOPB; tty.c_cflag &= ~CRTSCTS; if (tcsetattr (fd, TCSANOW, &tty) != 0) { error_message ("error %d from tcsetattr", errno); return -1; } return 0; } void set_blocking (int fd, int should_block) { struct termios tty; memset (&tty, 0, sizeof tty); if (tcgetattr (fd, &tty) != 0) { error_message ("error %d from tggetattr", errno); return; } tty.c_cc[VMIN] = should_block ? 1 : 0; tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout if (tcsetattr (fd, TCSANOW, &tty) != 0) error_message ("error %d setting term attributes", errno); } ... char *portname = "/dev/ttyUSB1" ... int fd = open (portname, O_RDWR | O_NOCTTY | O_SYNC); if (fd < 0) { error_message ("error %d opening %s: %s", errno, portname, strerror (errno)); return; } set_interface_attribs (fd, B115200, 0); // set speed to 115,200 bps, 8n1 (no parity) set_blocking (fd, 0); // set no blocking write (fd, "hello!\n", 7); // send 7 character greeting usleep ((7 + 25) * 100); // sleep enough to transmit the 7 plus // receive 25: approx 100 uS per char transmit char buf [100]; int n = read (fd, buf, sizeof buf); // read up to 100 characters if ready to read
速度B115200
, B230400
, B9600
, B19200
, B38400
, B57600
, B1200
, B2400
, B4800
等。奇偶校验0
(表示无奇偶校验), PARENB|PARODD
(奇偶校验使用), PARENB
启用奇偶校验并使用偶数), PARENB|PARODD|CMSPAR
(标记奇偶校验)和PARENB|CMSPAR
(空间奇偶校验)。
“阻塞”设置端口上的read()
是否等待指定数量的字符到达。 设置没有阻塞意味着一个read()
返回,然而许多字符都可用而不需要等待更多,直到缓冲区限制。
附录:
CMSPAR
仅用于select标记和空间奇偶校验,这是不常见的。 对于大多数应用程序,可以省略。 只有定义了预处理器符号__USE_MISC
我的头文件/usr/include/bits/termios.h
才能定义CMSPAR
。 该定义发生(在features.h
)
#if defined _BSD_SOURCE || defined _SVID_SOURCE #define __USE_MISC 1 #endif
<features.h>
的介绍性评论说:
/* These are defined by the user (or the compiler) to specify the desired environment: ... _BSD_SOURCE ISO C, POSIX, and 4.3BSD things. _SVID_SOURCE ISO C, POSIX, and SVID things. ... */
对于符合POSIX标准的演示代码,如正确设置terminal模式和POSIX操作系统串行编程指南中所述,提供以下内容。
它基本上是从其他答案中得出的,但是不正确和误导性的评论已经得到纠正。
#include <errno.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <termios.h> #include <unistd.h> int set_interface_attribs(int fd, int speed) { struct termios tty; if (tcgetattr(fd, &tty) < 0) { printf("Error from tcgetattr: %s\n", strerror(errno)); return -1; } cfsetospeed(&tty, (speed_t)speed); cfsetispeed(&tty, (speed_t)speed); tty.c_cflag |= (CLOCAL | CREAD); /* ignore modem controls */ tty.c_cflag &= ~CSIZE; tty.c_cflag |= CS8; /* 8-bit characters */ tty.c_cflag &= ~PARENB; /* no parity bit */ tty.c_cflag &= ~CSTOPB; /* only need 1 stop bit */ tty.c_cflag &= ~CRTSCTS; /* no hardware flowcontrol */ /* setup for non-canonical mode */ tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); tty.c_oflag &= ~OPOST; /* fetch bytes as they become available */ tty.c_cc[VMIN] = 1; tty.c_cc[VTIME] = 1; if (tcsetattr(fd, TCSANOW, &tty) != 0) { printf("Error from tcsetattr: %s\n", strerror(errno)); return -1; } return 0; } void set_mincount(int fd, int mcount) { struct termios tty; if (tcgetattr(fd, &tty) < 0) { printf("Error tcgetattr: %s\n", strerror(errno)); return; } tty.c_cc[VMIN] = mcount ? 1 : 0; tty.c_cc[VTIME] = 5; /* half second timer */ if (tcsetattr(fd, TCSANOW, &tty) < 0) printf("Error tcsetattr: %s\n", strerror(errno)); } int main() { char *portname = "/dev/ttyUSB0"; int fd; int wlen; fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC); if (fd < 0) { printf("Error opening %s: %s\n", portname, strerror(errno)); return -1; } /*baudrate 115200, 8 bits, no parity, 1 stop bit */ set_interface_attribs(fd, B115200); //set_mincount(fd, 0); /* set to pure timed read */ /* simple output */ wlen = write(fd, "Hello!\n", 7); if (wlen != 7) { printf("Error from write: %d, %d\n", wlen, errno); } tcdrain(fd); /* delay for output */ /* simple noncanonical input */ do { unsigned char buf[80]; int rdlen; rdlen = read(fd, buf, sizeof(buf) - 1); if (rdlen > 0) { #ifdef DISPLAY_STRING buf[rdlen] = 0; printf("Read %d: \"%s\"\n", rdlen, buf); #else /* display hex */ unsigned char *p; printf("Read %d:", rdlen); for (p = buf; rdlen-- > 0; p++) printf(" 0x%x", *p); printf("\n"); #endif } else if (rdlen < 0) { printf("Error from read: %d: %s\n", rdlen, strerror(errno)); } /* repeat read to get full message */ } while (1); }
为了使程序将接收到的数据作为ASCII码处理,用符号DISPLAY_STRING编译程序,例如
cc -DDISPLAY_STRING demo.c