Linux 串口通讯问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux 串口通讯问题相关的知识,希望对你有一定的参考价值。
本人编了一个Linux程序,串口1也就是ttyS0,可以打开,可以传输数据。但是用同样的程序,只把设备号ttyS0改成ttyS1(板子有4个COM口),接到串口2上,为什么就不能传输数据了。请教各位高手。。。。急。。。。
Linux系统通过这两个号唯一的确定一个驱动实例。一个实际存在的串口只能够存在一个驱动实例。大多数的驱动实例只支持单一现成的读写操作,所以不允许多个程序同时打开设备文件,典型的一种就是串口,它只允许一个程序打开。
一个驱动实例对应一组唯一的主设备号和次设备号,多个设备节点可以指向同一组设备号。
下面是结论:
不论如何更改ttyS0,串口只能打开一次。
可以通过简单的cp /dev/ttyS0 /dev/ttyS4将设备节点的名称复制为/dev/ttyS4,或者使用mv命令对名称进行修改,但是不能改变串口只能打开一次的状况。追问
ttyS0和ttyS1应该就是两个设备了,我不是把ttyS0设备复制了一下,而是改成另一个串口设备,Linux下不是默认有四个串口设备的吗?分别是ttyS0,ttyS1,ttys2, ttyS3.照理说应该都可以打开,并且传输数据的。。
追答多余的串口应该是被init进程托管了,可以查看/etc/inittab中有没有getty /dev/ttySx的内容,注释掉试试。
追问Ubuntu系统,没有inittab文件,应该不会无缘无故的被初始进程托管吧?
参考技术A 你的中端是否够com4中断是否打开
超过com4得看看中断是否够不够的话屏蔽掉一些pci的rom追问
Linux下串口默认是ttyS0,ttyS2对应中断4,ttyS1,ttyS3对应中断3。
追答复制文件是没有用的
追问不是复制,没有复制。
linux应用:串口模块编程
Linux下串口是比较常用的通讯接口,有直接用串口通讯的,也有用USB转串口通讯的,还有其它方式转串口的,但不管是以什么方式,以为在linux下可以说一切皆文件,操作文件设备基本都是一样的,都是使用open,read,write,ioctrl这几个函数进行操作,串口的应用编程也不例外,本例程中的串口程序是一个比较完善的串口模块,封装了比较丰富的API,包括串口波特率、数据位、校验位、停止位等参数设置的API,方便串口端口初始化以及读写参数,开发应用可以直接使用!
一、查看系统中的串口设备
如下所示:输入 ls /dev/tty 然后table键补全,会出现诸多tty设备,其中
/dev/ttyn是虚拟控制台
/dev/ttySn是串行端口(串口)
/dev/ttyUSB0是USB到串口的转换器
而本例中使用的就是USB到串口的转换器,所以需要操作的就是这个设备文件
二、串口设备初始化过程
1、首先打开该文件设备:
//后面可跟参数:O_NONBLOCK(非阻塞),O_RDWR(可读可写)
//O_WRONLY(只写),O_RDONLY(只读),O_NOCTTY(非控制终端)
int fd = open("/dev/ttyUSB0", O_RDWR|O_NOCTTY);//以可读可写方式打开,默认阻塞模式
2、 设置串口通讯速率:
/**
*@brief 设置串口通信速率
*@param fd 类型 int 打开串口的文件句柄
*@param speed 类型 int 串口速度
*@return void
*/
int set_speed(int fd, int speed)
int i;
int status;
struct termios Opt;
tcgetattr(fd, &Opt);
for ( i= 0; i < sizeof(spd_arr) / sizeof(int); i++)
if(speed == name_arr[i])
tcflush(fd, TCIOFLUSH);
cfsetispeed(&Opt, spd_arr[i]);
cfsetospeed(&Opt, spd_arr[i]);
status = tcsetattr(fd, TCSANOW, &Opt);
if (status != 0)
printf("tcsetattr failed");
return 1;
tcflush(fd,TCIOFLUSH);
printf("set_speed\\n");
return 0;
3、设置串口的数据位,停止位和效验位:
/**
*@brief 设置串口数据位,停止位和效验位
*@param fd 类型 int 打开的串口文件句柄
*@param databits 类型 int 数据位 取值为 7 或者8
*@param stopbits 类型 int 停止位 取值为 1 或者2
*@param parity 类型 int 效验类型 取值为N,E,O,,S
*/
int set_Parity(int fd, int databits, int parity, int stopbits, int RTSCTS)
struct termios options;
if ( tcgetattr( fd,&options) != 0)
perror("SetupSerial 1");
return -1;
options.c_cflag &= ~CSIZE;
switch (databits) /*设置数据位数*/
case 7:
options.c_cflag |= CS7;
break;
case 8:
options.c_cflag |= CS8;
break;
default:
fprintf(stderr,"Unsupported data size\\n");
return -1;
options.c_iflag |= INPCK;
cfmakeraw(&options);
//options.c_lflag |= (ICANON | ECHO | ECHOE);
//options.c_lflag &= ~(ICANON | ECHO | ECHOE);
//options.c_iflag &= ~(IXON | IXOFF);
switch (parity)
case 'n':
case 'N':
options.c_cflag &= ~PARENB; /* Clear parity enable */
options.c_iflag &= ~INPCK; /* Enable parity checking */
break;
case 'o':
case 'O':
options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/
break;
case 'e':
case 'E':
options.c_cflag |= PARENB; /* Enable parity */
options.c_cflag &= ~PARODD; /* 转换为偶效验*/
break;
case 'S':
case 's': /*as no parity*/
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
break;
default:
fprintf(stderr,"Unsupported parity\\n");
return -1;
/* 设置停止位*/
switch (stopbits)
case 1:
options.c_cflag &= ~CSTOPB;
break;
case 2:
options.c_cflag |= CSTOPB;
break;
default:
fprintf(stderr,"Unsupported stop bits\\n");
return -1;
/* Set rts/cts */
if (RTSCTS)
printf("Set rts/cts");
options.c_cflag |= CRTSCTS;
tcflush(fd,TCIFLUSH);
options.c_cc[VTIME] = 150; /* 设置超时15 seconds*/
options.c_cc[VMIN] = 0; /* Update the options and do it NOW */
if (tcsetattr(fd,TCSANOW,&options) != 0)
printf("SetupSerial failed");
return -1;
printf("set_Parity\\n");
return 0;
到这里串口初始化过程就结束了,就可以编写代码进行串口通讯测试了
三、串口通讯测试
串口通讯测试main.c代码如下,过程就是通过串口模块部分提供的api,初始化一个串口,然后对串口数据进行读取,读取不到数据的时候会阻塞,因为open设备文件的时候默认是阻塞模式。
#include "uart.h"
int main(int argc, char **argv)
char buff[512];
//打开串口0,波特率为1500000
int fd = serial_def_init(0, 1500000);
if(fd < 0) return 0;
while(1)
serial_read(fd, buff, sizeof(buff));
printf("read:%s\\n", buff);
close(fd);//关闭串口
return 0;
然后编译:gcc -o app main.c uart.c
我们看到编译后生成了app的文件,然后./app执行发现打开串口失败,这是因为我们的用户权限不够,一般打开硬件设备文件都需要root权限,所以我们可以以root用户权限去执行这个文件,如:sudo ./app
于是就正常执行了这个程序,能从串口成功读取到数据!
完整的串口模块程序链接:linux下串口模块程序-Linux文档类资源-CSDN下载
以上是关于Linux 串口通讯问题的主要内容,如果未能解决你的问题,请参考以下文章