linux uart串口编程

linux uart串口编程


/*
 * 初始化配置rs232串口设备
 * 参数 fd: 设备文件描述符
 *		speed: rs232串口设备波特率
 *		databits: rs232串口设备数据位位数
 *		parity: rs232串口设备数据奇偶校验设置
 *		stopbits: rs232串口设备数据停止位位数
 * 返回值: 配置成功返回零, 否则返回非零.
 *
 * */
int serial_port_init(int fd,int speed,int databits,char parity,int stopbits)
{
	struct termios oldtio,newtio;
	int status,i;

#ifdef DEBUG
	printf("%s fd = %d\n speed = %d\tdatabits = %d\tparity = %c\tstopbits = %d\n", __func__, fd, speed, databits, parity, stopbits);
#endif
#if 1
	/* 保存之前的串口配置 */
	bzero(&newtio,sizeof(struct termios));
	if(tcgetattr(fd,&oldtio)!=0){
		perror("tcgetattr ");
		return -1;
	}
	newtio=oldtio;
#endif

	newtio.c_cflag |= CLOCAL;	
	newtio.c_cflag |= CREAD;	
	newtio.c_cflag &= ~ISTRIP;	
#ifdef RAW_UART
	cfmakeraw(&newtio);
#endif

	/* 设置数据位数 */
	switch (databits){
		case 7: /* 七位数据位 */
			newtio.c_cflag &= ~CSIZE;	
			newtio.c_cflag |= CS7;
			break;
		case 8: /* 八位数据位 */
			newtio.c_cflag &= ~CSIZE;	
			newtio.c_cflag |= CS8;
			break;
		default:
			printf("%s unsupported data size\n", __func__);
			return -1;
	}
	/*设置校验位*/
	switch(parity){
		case 'n': /* 无校验位 */
		case 'N': /* 无校验位 */
			newtio.c_cflag &= ~PARENB;
			//newtio.c_cflag &= ~INPCK;
			break;
		case 'o':
		case 'O':
			newtio.c_cflag |= (PARODD | PARENB);  /* 设置为奇效验*/ 
			newtio.c_iflag |= INPCK;
			break;
		case 'e':
		case 'E':
			newtio.c_cflag |= PARENB;
			newtio.c_cflag &= ~PARODD;   /* 转换为偶效验*/  
			newtio.c_iflag |= INPCK;
			break;
		case 's':
		case 'S': 
			newtio.c_cflag &= ~PARENB;
			newtio.c_cflag &= ~CSTOPB;
			break;
		default:
			printf("%s unsupported parity\n", __func__);
			return -1;
	}
	/* 设置停止位 */   
	switch (stopbits)
	{
		case 1: /* 一个停止位 */
			newtio.c_cflag &= ~CSTOPB;
			break;
		case 2: /* 两个停止位 */
			newtio.c_cflag |= CSTOPB;
			break;
		default:
			printf("%s Unsupported stop bits\n", __func__);
			return -1;
	}
	/* 設置波特率 */
	switch(speed){
		case 9600:
			cfsetispeed(&newtio,B115200);
			cfsetospeed(&newtio,B115200);
			break;
		case 460800:
			cfsetispeed(&newtio,B460800);
			cfsetospeed(&newtio,B460800);
			break;
		case 115200:
			cfsetispeed(&newtio,B115200);
			cfsetospeed(&newtio,B115200);
			break;
		default:
			printf("%s not set speed fo serial port\n", __func__);
	}

	newtio.c_cc[VTIME]=0; /* 等待時間 */
	newtio.c_cc[VMIN]=1;

	tcdrain(fd); /* 使程序阻塞,直到缓冲区数据发送完 */
	tcflush(fd,TCIOFLUSH); /* 更新配置 */
	if ((tcsetattr(fd,TCSANOW,&newtio)) != 0){
		perror("tcsetattr ");
		return -1;
	}

	return 0;
}
 
/*
 * 打开rs232串口设备
 * 参数: device: rs232设备
 *		 speed: rs232设备的波特率
 *		 databits: rs232设备的数据位位数
 *		 parity: rs232设备的奇偶校验设置
 *		 stopbits: rs232设备的停止位位数
 * 返回值: fd: 设备文件描述符
 *
 * */
int serial_port_open(char *device, 
		int speed, int databits, 
		int parity, int stopbits)
{
	/* 打开rs232串口设备 */
	int fd = open(device, O_RDWR|O_NOCTTY|O_NDELAY);
	if(fd<=0){
		printf("open %s error !\n", device);
		exit(1);
	}
	/* 测试rs232设备 */
	if(fcntl(fd,F_SETFL,0)<0){
		perror("fcntl F_SETFL\n");
	}
	/* 测试rs232设备 */
	if(isatty(fd) == 0){
		perror("this is not a terminal device \n");
	}
	/* 初始化配置rs232串口设备 */
	if(serial_port_init(fd, speed, databits, parity, stopbits)!=0){
		printf("serial port init %s fail !\n", device);
		close(fd);
		exit(1);
	}
	
	return fd;
}

/*
 * 关闭rs232串口设备
 *
 * */
int serial_port_close(int fd)
{
	return close(fd);
}

/*
 * 从rs232串口设备读数据
 * 参数: fd: 设备文件描述符
 *		 buf: 数据将存到的缓冲区指针
 *		 len: 缓冲区的大小
 *
 * 返回值: num: 实际从rs232读到的数据长度
 *
 * */
int serial_port_read(int fd, char *buf, int len)
{
	int num = 0;

	/* 判断fd和buf的合法性 */
	if((fd > 0) && (buf != NULL)){
		/* 从rs232串口设备读数据 */
		num = read(fd, buf, len);
	}

	return num;
}

/*
 * 向rs232串口设备写数据
 * 参数: fd: 设备文件描述符
 *		 buf: 待写入的数据的数据缓冲区指针
 *		 len: 缓冲区的大小
 *
 * 返回值: num: 实际写入到rs23设备的数据长度
 
 * */
int serial_port_write(int fd, char *buf, int len)
{
	int num = 0;

	/* 判断fd和buf的合法性 */
	if((fd > 0) && (buf != NULL)){
		/* 向s232串口设备写数据 */
		num = write(fd, buf, len);
	}

	return num;
}


你可能感兴趣的:(linux,c/c++)