tcsetattr fd: input/output error
本菜鸟打算使用linux 下串口1接收来自51单片机的信息。
串口未接上时,程序运行无误,但是一旦串口接上,实施通信,便出现了如题的错误tcsetattr fd: input/output error
实在不解,求大神们解释。linux代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <string.h>
#define SERIAL_PORT "/dev/ttyS0" //串口地址
#define PORT_SPEED 9600 //串口波特率
#define DATABITS 8 //数据位
#define STOPBITS 1 //停止位
#define PARITY 'n' //校验方式 (不校验)
int speed_arr[] = {B38400, B19200, B9600, B4800, B2400, B1200, B300,B38400, B19200, B9600, B4800, B2400, B1200, B300,};
int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200, 9600, 4800, 2400, 1200, 300,};
void setSpeed(int, int, struct termios);
int setParity(int, int, int, int, struct termios);
int main()
{
int fd;
int i;
int len;
int n;
char read_buf[256];
char write_buf[256];
/*#
这个变量被用来提供一个健全的线路设置集 合, 如果这个端口在被用户初始化前
使用. 驱动初始化这个变量使用一个标准的数值集
struct termios{
unsigned short c_iflag; // 输入模式标志
unsigned short c_oflag; //输出模式标志
unsigned short c_cflag; // 控制模式标志
unsigned short c_lflag; //区域模式标志或本地模式标志或局部模式
unsigned char c_line; //行控制line discipline
unsigned char c_cc[NCC]; // 控制字符特性
};
*/
struct termios opt; //定义termios结构
//打开串口,默认为阻塞读方式
//#O_RDWR:可读写方式打开;O_NOCTTY:若打开的文件为终端机设备时则不会把该终端机当做进程控制终端机
fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY |O_NDELAY);
if(fd == -1)
{
perror("open serial failed!\n");
exit(1);
}
//设置波特率
setSpeed(fd, PORT_SPEED, opt);
//设置数据位、停止位和校验位
setParity(fd, DATABITS, STOPBITS, PARITY, opt);
printf("configure complete\n");
if(tcsetattr(fd, TCSANOW, &opt) != 0)
{
perror("serial error");
return -1;
}
printf("start send and receive data\n");
printf("wait...\n");
while(1)
{
while((read(fd, read_buf, sizeof(read_buf))) > 0 )
{
printf("recv: \n", read_buf);
printf("wait...\n");
}
/*n = 0;
len = 0;
bzero(read_buf, sizeof(read_buf));
bzero(write_buf, sizeof(write_buf));
while((n = read(fd, read_buf, sizeof(read_buf))) > 0 )
{
for(i = len; i < (len + n); i++)
{
write_buf[i] = read_buf[i - len];
}
len += n;
}
write_buf[len] = '\0';
printf("Len %d \n", len);
printf("%s \n", write_buf);
n = write(fd, write_buf, len);
printf("write %d chars\n",n);
sleep(2);
*/
}
close(fd);
}
/************************************
*setSpeed
* 设置波特率(38400, 19200, 9600, 4800, 2400, 1200, 300)
*@para
* fd 文件标识。
* speed 波特率。
* struct termios termios结构变量
************************************/
void setSpeed(int fd, int speed, struct termios Opt)
{
int i;
if(tcgetattr(fd, &Opt) != 0) //获取与终端相关的参数; #并将获得信息保存在 opt 变量中
//if(tcgetattr(STDIN_FILENO, &Opt) != 0)
{
perror("tcgetattr fd\n");
return;
}
//识别波特率
for(i = 0; i < sizeof(speed_arr) / sizeof(int); i++)
{
if(speed == name_arr[i])
{
tcflush(fd, TCIOFLUSH);
//设置波特率
cfsetispeed(&Opt, speed_arr[i]);
cfsetospeed(&Opt, speed_arr[i]);
//设置数据接收方式
if(tcsetattr(fd, TCSANOW, &Opt) != 0)
{
perror("tcsetattr fd");
exit(0);
}
tcflush(fd, TCIOFLUSH);
}
}
}
int openPort(int comPort)
{
int fd;
#if(COM_TYPE == GNR_COM)
char *dev[] = {""}
}
/************************************
*setParity
* 数据位、停止位和校验位
*@para
* fd 文件标识。
* databits 数据位。(8 | 7)
* stopbits 停止位。(1 | 2)
* parity 校验位。(n:无校验位 | o:奇校验 | e:偶校验 | s:空格)
*@return
* 1:设置失败 0:设置成功
************************************/
int setParity(int fd, int databits, int stopbits, int parity, struct termios Opt)
{
if(tcgetattr(fd, &Opt) != 0)
{
perror("tcgetattr fd");
return 1;
}
Opt.c_cflag |= (CLOCAL | CREAD); //一般必设置的标志
switch(databits) //设置数据位数
{
case 7:
Opt.c_cflag &= ~CSIZE;
Opt.c_cflag |= CS7;
break;
case 8:
Opt.c_cflag &= ~CSIZE;
Opt.c_cflag |= CS8;
break;
default:
fprintf(stderr, "Unsupported data size.\n");
return 1;
}
switch(parity) //设置校验位
{
case 'n':
Opt.c_cflag &= ~PARENB; //清除校验位
Opt.c_iflag &= ~INPCK; //enable parity checking
break;
case 'o':
Opt.c_cflag |= PARENB; //enable parity
Opt.c_cflag |= PARODD; //奇校验
Opt.c_iflag |= INPCK; //disable parity checking
break;
case 'e':
Opt.c_cflag |= PARENB; //enable parity
Opt.c_cflag &= ~PARODD; //偶校验
Opt.c_iflag |= INPCK; //disable pairty checking
break;
case 's':
Opt.c_cflag &= ~PARENB; //清除校验位
Opt.c_cflag &= ~CSTOPB; //空格
Opt.c_iflag |= INPCK; //disable pairty checking
break;
default:
fprintf(stderr, "Unsupported parity.\n");
return 1;
}
switch(stopbits) //设置停止位
{
case 1:
Opt.c_cflag &= ~CSTOPB;
break;
case 2:
Opt.c_cflag |= CSTOPB;
break;
default:
fprintf(stderr, "Unsupported stopbits.\n");
return 1;
}
Opt.c_cflag |= (CLOCAL | CREAD);
Opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
Opt.c_oflag &= ~OPOST;
Opt.c_oflag &= ~(ONLCR | OCRNL); //添加的
Opt.c_iflag &= ~(ICRNL | INLCR);
Opt.c_iflag &= ~(IXON | IXOFF | IXANY); //添加的
tcflush(fd, TCIFLUSH);
Opt.c_cc[VTIME] = 0; //设置超时为15sec
Opt.c_cc[VMIN] = 0; //Update the Opt and do it now
if(tcsetattr(fd, TCSANOW, &Opt) != 0)//设置数据接收方式
{
perror("tcsetattr fd");
return 1;
}
return 0;
}