使用多路复用实现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;
}





Linux下多路复用式串口操作

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

串口多路复用收发数据

http://blog.chinaunix.net/uid-22477616-id-3513752.html 
  • duxiajianke
  • duxiajianke
  • 2014年10月15日 07:15
  • 678

linux串口通信协议编程详解

linux串口通信协议编程详解: 1.
  • niuxuheng
  • niuxuheng
  • 2014年09月17日 17:07
  • 10429

linux串口通信协议编程详解

linux串口通信协议编程详解: 1.串口通信协议拟定; 2.通信校验--CRC; 3.Linux多线程编程; 1.串口通信协议; 1.1协议拟定: 项目 长度 ...
  • dddxxxx
  • dddxxxx
  • 2015年01月20日 23:38
  • 1448

基于串口的简单通信协议

发一个基于串口的简单通信协议(在TMS320F2812上实现) 可变帧长 可选的CRC校验 基于状态机的接收机制 /* * ==== ...
  • e_wsq
  • e_wsq
  • 2013年11月04日 23:32
  • 1315

linux 下基于特定通信协议利用多线程同步通信机制实现的串口通信

/** *@Title:利用多线程同步通信机制实现串口通信 *@Introduce:主要完成根据特定的通信协议实现串口与PC上特定串口 * 通信软件的通信。测试版,只是完成主要框架,没有完全将协...
  • wanney216
  • wanney216
  • 2014年10月25日 10:57
  • 1469

RS232实现串口双向通讯

之前对接了一个pos机设备,设备使用了RS232进行通讯,现在也完成该需求并在线上运行使用当中了,此次对接实现的功能主要是应用程序向POS机设备发送应收金额和收费时间;至此想记录一下开发过程中遇到的问...
  • u014629817
  • u014629817
  • 2017年05月17日 10:50
  • 264

linux下的串口通信

一、串口的基本原理 1 串口通讯     串口通讯(Serial Communication),是指外设和计算机间,通过数据信号线、地线等,按位进行传输数据的一种通讯方式。     串口...
  • u013485792
  • u013485792
  • 2016年03月29日 16:16
  • 1134

Linux下串口通信详解(上)打开串口和串口初始化详解

linux下串口通信主要有下面几个步骤 串口通信流程图 下面我会一一介绍这几个步骤。 1.打开串口 代码(串口为ttyUSB0) //打开串口 int open_port(void) { in...
  • specialshoot
  • specialshoot
  • 2016年02月21日 17:03
  • 18310

android串口通信以及串口协议解析

一,android串口通信 串口通信采用一个第三方开源项目,实现串口数据收发。 1. 使用了http://code.google.com/p/android-serialport-api/的项目的se...
  • junfeng120125
  • junfeng120125
  • 2013年07月15日 10:10
  • 42427
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:使用多路复用实现3个串口的通信
举报原因:
原因补充:

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