使用多路复用实现3个串口的通信

原创 2012年07月19日 19:52:07

如题,Linux环境下操作串口设备,实现多路复用。

串口配置函数:

/*
 * set_com_config.c
 *
 *  Created on: 2012-7-18
 *      Author: liwei.cai
 */
#include <termios.h>
int set_com_config(int fd, int baud_rate,
		int data_bits, char parity, int stop_bits)
{
	struct termios new_cfg, old_cfg;
	int speed;

	//保存并测试现在有串口参数设置,在这里如果串口号等出错,会有相关的出错信息
	if(tcgetattr(fd, &old_cfg) != 0)
	{
		perror("tcgetattr");
		return -1;
	}
	//设置字符大小
	new_cfg = old_cfg;
	cfmakeraw(&new_cfg);//配置为原始模式
	new_cfg.c_cflag &= ~CSIZE;

	//设置波特率
	switch(baud_rate)
	{
		case 2400:
		{
			speed = B2400;
		}
		break;
		case 4800:
		{
			speed = B4800;
		}
		break;
		case 9600:
		{
			speed = B9600;
		}
		break;
		case 19200:
		{
			speed = B19200;
		}
		break;
		case 38400:
		{
			speed = B38400;
		}
		break;
		default:
		case 115200:
		{
			speed = B115200;
		}
		break;
	}
	cfsetispeed(&new_cfg, speed);
	cfsetospeed(&new_cfg, speed);

	//设置数据位
	switch(data_bits)
	{
		case 7:
		{
			new_cfg.c_cflag |=CS7;
		}
		break;
		default:
		case 8:
		{
			new_cfg.c_cflag |=CS8;
		}
		break;
	}

	//设置奇偶校验位
	switch(parity)
	{
		default:
		case 'n':
		case 'N':
		{
			new_cfg.c_cflag &= ~PARENB;
			new_cfg.c_iflag &= ~INPCK;
		}
		break;

		case 'o':
		case 'O':
		{
			new_cfg.c_cflag |= (PARODD | PARENB);
			new_cfg.c_iflag |= INPCK;
		}
		break;
		case 'e':
		case 'E':
		{
			new_cfg.c_cflag |= PARENB;
			new_cfg.c_iflag &= ~PARODD;
			new_cfg.c_cflag |= INPCK;
		}
		break;

		case 's':
		case 'S':
		{
			new_cfg.c_cflag &= ~PARENB;
			new_cfg.c_iflag &= ~CSTOPB;
		}
		break;
	}

	//设置停止位
	switch(stop_bits)
	{
	default:
	case 1:
	{
		new_cfg.c_iflag &= ~CSTOPB;
	}
	break;

	case 2:
		new_cfg.c_iflag |= CSTOPB;
		break;
	}
	//设置等待时间和最小接受字符
	new_cfg.c_cc[VTIME] = 0;
	new_cfg.c_cc[VMIN] = 1;

	//处理未接受字符
	tcflush(fd, TCIFLUSH);
	//激活新配置
	if ((tcsetattr(fd, TCSANOW, &new_cfg)) != 0)
	{
		perror("tcsetattr");
		return -1;
	}
	return 0;
}
读取串口函数:

/*
 * open_port.c
 *
 *  Created on: 2012-7-18
 *      Author: liwei.cai
 */
//#include <termio.h>
//打开串口函数
int open_port(int com_port)
{
	int fd;
#if (COM_TYPE == GNR_COM) //使用普通串口
	char *dev[] = {"/dev/ttyS0", "/dev/ttyS1", "/dev/ttyS2"};
#else //使用USB转串口
	char *dev[] = {"/dev/ttyUSB0", "/dev/ttyUSB1", "/dev/ttyUSB2"};
#endif
	if ((com_port < 0) || (com_port > MAX_COM_NUM))
	{
		return -1;
	}
	//打开串口
	fd = open(dev[com_port -1], O_RDWR|O_NOCTTY|O_NDELAY);
	if(fd < 0)
	{
		perror("open serial port");
		return -1;
	}
	//恢复串口为阻塞状态
	if(fcntl(fd, F_SETFL, 0) < 0)
	{
		perror("fcntl F_SETFL\n");
	}
	//测试是否为终端设备
	if(isatty(STDIN_FILENO) == 0)
	{
		perror("standard input is not a terminal device");
	}
	return fd;
}
相关头文件:

/*
 * uart_api.h
 *
 *  Created on: 2012-7-18
 *      Author: liwei.cai
 */

#ifndef UART_API_H_
#define UART_API_H_

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <termios.h>

#define BUFFER_SIZE 1024
#define HOST_COM_PORT 1
#define TARGET_COM_PORT 2
#define MAX_COM_NUM 3

#include "open_port.c"
#include "set_com_config.c"


#endif /* UART_API_H_ */

功能主函数:

/*
 * main.c
 *
 *  Created on: 2012-7-19
 *      Author: liwei.cai
 */
#include <poll.h>
#include "uart_api.h"
int main(void)
{
	struct pollfd fds[MAX_COM_NUM];
	char buf[BUFFER_SIZE];
	int i, res, real_read, maxfd;

	//首先按照一定的权限打开两个源文件

	if((fds[0].fd = open_port(COM_1)) < 0) //串口1 接受数据
	{
		printf("Open COM1 error!\n");
		return 1;
	}
	if (set_com_config(fds[0].fd,115200, 8, 'N', 1) < 0)//配置串口1
	{
		perror("set_com_config3");
		return 1;
	}

	if((fds[1].fd = open_port(COM_2)) < 0)
	{
		printf("Open COM2 error!\n");
		return 1;
	}
	if (set_com_config(fds[1].fd,115200, 8, 'N', 1) < 0)//配置串口2
	{
		perror("set_com_config3");
		return 1;
	}

	if((fds[2].fd = open_port(COM_3)) < 0)
	{
		printf("Open COM3 error!\n");
		return 1;
	}
	if (set_com_config(fds[2].fd,115200, 8, 'N', 1) < 0)//配置串口3
	{
		perror("set_com_config3");
		return 1;
	}

	//取出两个文件描述符中的较大者
	for(i = 0; i < MAX_COM_NUM; i++)
	{
		fds[i].events = POLLIN;
	}
	//循环测试该文件描述符是否准备就绪,并调用select函数对象相关文件描述符做对应操作
	while(fds[0].events || fds[1].events
			|| fds[2].events)
	{
		if(poll(fds, MAX_COM_NUM,0) < 0)
		{
			printf("Poll error!\n");
			return 1;
		}
		for (i = 0; i < MAX_COM_NUM; i++)
		{
			if (fds[i].revents)
			{
				memset(buf, 0, BUFFER_SIZE);
				real_read = read (fds[i].fd, buf, BUFFER_SIZE);
				if (real_read < 0)
				{
					if (errno != EAGAIN)
					{
						return 1;
					}
				}
				else if (!real_read)
				{
					close(fds[i].fd);
					fds[i].events = 0;
				}
				else
				{
					buf[real_read] = '\0';
					//printf("%s", buf);
					if (i == 0)
					{
						write(fds[1].fd, buf, strlen(buf));
						write(fds[2].fd, buf, strlen(buf));
					}
					else
					{
						write(fds[0].fd, buf, strlen(buf));
					}

					if ((buf[0] == 'q') || (buf[0] == 'Q'))
					{
						return 1;
					}
				}// end of if real_read
			} //end of if revents
		} //end of for
	} //end of while
	return 0;
}





版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

关于串口复用造成的意外及总结

前两天测试人员发现,在测试运行的产品中,有两个运行不正常。于是对出现异常的产品进行了重点检测。 开始怀疑是产品中的无线模块信号不好,造成一段时间后就连接断掉。于是使用了一个测试好用的无线模块,测试发...
  • tietao
  • tietao
  • 2014-03-15 10:04
  • 2026

串口多路复用收发数据

http://blog.chinaunix.net/uid-22477616-id-3513752.html 

Linux下多路复用式串口操作

1.实验目的   通过编写多路复用式串口读写,进一步理解多路复用函数的用法,同时更加熟练地掌握Linux设备文件的读写方法。   2.实验内容   本实验中,实现两台机器(宿主机和目...

Linux串口编程(中断方式和select方式)

Linux下的串口编程,在嵌入式开发中占据着重要的地位,因为很多的嵌入式设备都是通过串口交换数据的。在没有操作系统的我们可以使用UART的中断来出来数据的接受和发送,而在Linux操作系统下,我们也可...

STC89C52串口的复用

reference:《微计算机信息》1998 年第14 卷第4 期             MCS-51 单片机串行口的一种复用  杨秋海 叶林 孙键 一 环境...

使用poll实现的io多路复用服务端和客户端

使用poll实现的io多路复用服务端和客户端。 客户端通过子进程创建多个客户端连接。 客户端每隔1秒向服务端发送一个时间戳, 服务端接收到时间戳以后,保存在本地的文件中, 一个客户端对应一个存储文件,...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)