在Linux系统中如何打开串口?C语言实现 (linux c 打开串口)
当前,Linux操作系统已经成为在开发嵌入式系统、服务器以及超级计算机等领域中更流行的操作系统之一。作为一款开源系统,Linux具有强大的开放性和可定制性,同时也支持许多不同的编程语言。因此,在Linux中使用串口通信成为许多开发人员竞相使用的手段之一。下文将介绍如何在Linux系统中打开串口,以及如何基于C语言实现串口程序。
1.打开串口
在Linux系统中,对于串口设备的操作一般采用文件操作的方法,因此需要使用文件操作相关的函数打开串口设备。下面是一个基本的串口打开程序的实现,其中串口编号为/dev/ttyS0:
“`c
#include
#include
#include
int fd;
void openPort(char *portDevice)
{
fd=open(portDevice,O_RDWR|O_NOCTTY|O_NDELAY);
if(fd==-1)
{
printf(“openPort(): error when opening the device %s\n”,portDevice);
}
else
{
fcntl(fd,F_SETFL,0/*FASYNC*/);
printf(“openPort(): successfully opened the device %s\n”,portDevice);
}
}
int mn()
{
openPort(“/dev/ttyS0”);
return 0;
}
“`
在此程序中,使用了open(打开串口设备)函数打开串口设备文件,传入设备路径作为之一个参数。第二个参数使用了标准的串口设置,即O_RDWR|O_NOCTTY|O_NDELAY,可确保对设备的打开同时可以读写,不承认是否为端口控制终端设备,以及不阻塞读写。当函数返回为-1时,即表示未能成功打开该设备,否则则打印串口打开成功。
2.配置串口
串口打开后,需要进行相关的设置以配置串口。通过在Linux系统中设置来设置和控制串口的标准和速率等参数,下面的函数将串口配置为9600波特率,不使用停止位,不设置奇偶校验,不使用等待、分割和其他特殊字符。
“`c
#define BAUDRATE B9600
#define MODEMDEVICE “/dev/ttyS0”
#define _POSIX_SOURCE 1 /* POSIX compliant source */
static int set_interface_attribs (int fd, int speed, int parity)
{
struct termios tty;
memset (&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0)
{
printf(“set_interface_attribs(): error from tcgetattr\n”);
return -1;
}
cfsetospeed (&tty, speed);
cfsetispeed (&tty, speed);
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; // 8-bit characters
// disable IGNBRK for miatched 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)
{
printf(“set_interface_attribs(): error from tcsetattr\n”);
return -1;
}
return 0;
}
static void set_blocking (int fd, int should_block)
{
struct termios tty;
memset (&tty, 0, sizeof tty);
if (tcgetattr (fd, &tty) != 0)
{
printf(“set_blocking(): error from tcgetattr\n”);
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)
{
printf(“set_blocking(): error setting term attributes\n”);
}
}
“`
在此函数中,使用tcsetattr函数设置套接口参数。其中,函数的之一个参数为串口设备文件的文件描述符,以及需要设置的波特率、奇偶校验等参数。在本例中,将波特率设置为9600,停止位数为0,奇偶校验不配置。另外,方法中通过CLOCAL和CREAD标志控制本端口是否为本地串口,以及是否允许读操作。同时,将VMIN属性设置为0表示直接读取控制台中的内容,而不必等待它的输入,以达到同步操作的效果。
3.发送接收数据
在打开并设置好串口之后,需要使用C语言实现数据的读写操作。一般使用read(读取数据)和write(写入数据)函数来实现此目的。
“`c
static void send(int fd,char* text)
{
int len = strlen(text);
write(fd,text,len);
}
static void receive(int fd)
{
char buf[10];
read(fd,buf,sizeof(buf));
}
“`
在本例中,使用write函数将一个简短的文本字符串发送到串口,然后使用read函数接收数据并存储到缓冲区中,其中调用了initPort()函数。同时,读数据时可以设置超时时间以避免阻塞程序。
除此之外,还可以使用poll函数实现基于Linux系统的串口通信程序。poll函数可以同时监听多个文件描述符上的事件,或者等待指定时间。由于C库提供的函数比较原始,因此使用poll函数能够更好的控制程序的时间操作和性能。
“`c
struct pollfd fds[1];
fds[0].fd = fd;
fds[0].events = POLLIN;
while (1)
{
int ret = poll(fds, 1, 1000); // wt for up to 1000ms
if (ret
{
printf(“poll(): error during poll()\n”);
exit(-1);
}
else if (ret == 0)
{
printf(“poll(): timeout occurred, no data received\n”);
}
else
{
if (fds[0].revents & POLLIN)
{
char buf[256];
int n = read(fd, buf, sizeof buf);
if (n
{
printf(“read(): error reading input string”);
}
printf(“%.*s”,n,buf);
}
}
}
“`