linux下的串口通信_Ubuntu
代码(回环测试)
#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>
#define SERIAL_NAME "/dev/ttyUSB0"
#define SERIAL0_NAME "/dev/ttyAMA0"
#define SERIAL1_NAME "/dev/ttyAMA1"
#define SERIAL2_NAME "/dev/ttyAMA2"
int serial_open(char *devName)
{
int fd = -1;
fd = open(devName, O_RDWR|O_NOCTTY|O_NDELAY);
if (-1 == fd)
{
printf("Can't Open %s",devName);
return(-1);
}
else
{
printf("open %s",devName);
}
if(fcntl(fd, F_SETFL, 0)<0)
{
printf("fcntl failed!\n");
return(-1);
}
else
{
printf("fcntl=%d\n",fcntl(fd, F_SETFL,0));
}
if(isatty(fd )==0)
{
printf("standard input is not a terminal device\n");
return(-1);
}
else
{
printf("isatty success!\n");
}
printf("fd=%d\n",fd);
return fd ;
}
int serial_set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
{
struct termios newtio,oldtio;
if ( tcgetattr( fd,&oldtio) != 0)
{
perror("SetupSerial 1");
return -1;
}
bzero( &newtio, sizeof( newtio ) );
newtio.c_cflag |= CLOCAL | CREAD;
newtio.c_cflag &= ~CSIZE;
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[VTIME] = 0;
newtio.c_cc[VMIN] = 0;
tcflush(fd,TCIFLUSH);
if((tcsetattr(fd,TCSANOW,&newtio))!=0)
{
printf("com set error");
return -1;
}
printf("set done!\n");
return 0;
}
void main(void)
{
int fd=-1;
int nread=0;
unsigned char rbuff[512];
if((fd=serial_open(SERIAL2_NAME))<0)
{
printf("open_port error");
return;
}
if((serial_set_opt(fd,4800,8,'N',1))<0)
{
printf("set_opt error");
return;
}
write(fd,"hello world \r\n",sizeof("hello world \r\n"));
while(1)
{
// printf("hello world \r\n");
// write(fd,"hello world \r\n",sizeof("hello world \r\n"));
// sleep(1);
nread = 0;
memset(rbuff,0,sizeof(rbuff));
nread=read(fd,rbuff,sizeof(rbuff));
if(nread != 0)
{
printf("rbuff:%s(%d)\r\n",rbuff,nread);
write(fd,rbuff,nread);
}
}
close(fd);
return;
}
相关函数
==============================================================================
1.open
所在头文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
函数
int open(const char * pathname, int flags);
int open(const char * pathname, int flags, mode_t mode);
参数说明
参数:pathname
const char * pathname //指向欲打开的文件路径字符串
参数:flags
标志 | 说明 |
---|---|
O_RDONLY | 以只读方式打开文件 |
O_WRONLY | 以只写方式打开文件 |
O_RDWR | 以可读写方式打开文件. 上述三种flags是互斥的, 也就是不可同时使用, 但可与下列的flags利用OR( |
O_CREAT | 若欲打开的文件不存在则自动建立该文件. |
O_EXCL | 如果O_CREAT 也被设置, 此指令会去检查文件是否存在. 文件若不存在则建立该文件, 否则将导致打开文件错误. 此外, 若O_CREAT 与O_EXCL 同时设置, 并且欲打开的文件为符号连接, 则会打开文件失败. |
O_NOCTTY | 如果欲打开的文件为终端机设备时, 则不会将该终端机当成进程控制终端机. |
O_TRUNC | 若文件存在并且以可写的方式打开时, 此flags会令文件长度清为0, 而原来存于该文件的资料也会消失. |
O_APPEND | 当读写文件时会从文件尾开始移动, 也就是所写入的数据会以附加的方式加入到文件后面. |
O_NONBLOCK | 以不可阻断的方式打开文件, 也就是无论有无数据读取或等待, 都会立即返回进程之中. |
O_NDELAY | 同O_NONBLOCK. |
O_SYNC | 以同步的方式打开文件. |
O_NOFOLLOW | 如果参数pathname 所指的文件为一符号连接, 则会令打开文件失败. |
O_DIRECTORY | 如果参数pathname 所指的文件并非为一目录, 则会令打开文件失败。注:此为Linux2. 2 以后特有的flags, 以避免一些系统安全问题. |
参数:mode
标志 | 可选值 | 说明 |
---|---|---|
S_IRWXU | 00700 权限 | 代表该文件所有者具有可读、可写及可执行的权限. |
S_IRUSR | S_IREAD, 00400 权限 | 代表该文件所有者具有可读取的权限. |
S_IWUSR | S_IWRITE, 00200 权限 | 代表该文件所有者具有可写入的权限. |
S_IXUSR | S_IEXEC, 00100 权限 | 代表该文件所有者具有可执行的权限. |
S_IRWXG | 00070 权限 | 代表该文件用户组具有可读、可写及可执行的权限. |
S_IRGRP | 00040 权限 | 代表该文件用户组具有可读的权限. |
S_IWGRP | 00020 权限 | 代表该文件用户组具有可写入的权限. |
S_IXGRP | 00010 权限 | 代表该文件用户组具有可执行的权限. |
S_IRWXO | 00007 权限 | 代表其他用户具有可读、可写及可执行的权限. |
S_IROTH | 00004 权限 | 代表其他用户具有可读的权限 |
S_IWOTH | 00002 权限 | 代表其他用户具有可写入的权限. |
S_IXOTH | 00001 权限 | 代表其他用户具有可执行的权限. |
返回值
返回0 :表示成功,
返回-1:只要有一个权限被禁止则返回-1
错误代码
错误代码 | 说明 |
---|---|
EEXIST | 参数pathname 所指的文件已存在, 却使用了O_CREAT 和O_EXCL flags. |
EACCESS | 参数pathname 所指的文件不符合所要求测试的权限. |
EROFS | 欲测试写入权限的文件存在于只读文件系统内. |
EFAULT | 参数pathname 指针超出可存取内存空间. |
EINVAL | 参数mode 不正确. |
ENAMETOOLONG | 参数 pathname 太长. |
ENOTDIR | 参数pathname 不是目录. |
ENOMEM | 核心内存不足. |
ELOOP | 参数pathname 有过多符号连接问题. |
EIO I/O | 存取错误. |
附加说明:使用 access()作用户认证方面的判断要特别小心, 例如在access()后再作open()空文件可能会造成系统安全上的问题.
==============================================================================
2.isatty
所在头文件
#include <unistd.h>
函数
int isatty(int desc);
参数说明
参数:pathname
参数 desc 文件描述符
返回值
如果参数 desc 所代表的文件描述符为一终端机则返回1, 否则返回0.
==============================================================================