Chinaunix首页 | 论坛 | 博客
  • 博客访问: 7676238
  • 博文数量: 961
  • 博客积分: 15795
  • 博客等级: 上将
  • 技术积分: 16612
  • 用 户 组: 普通用户
  • 注册时间: 2010-08-07 14:23
文章分类

全部博文(961)

文章存档

2016年(1)

2015年(61)

2014年(41)

2013年(51)

2012年(235)

2011年(391)

2010年(181)

分类: 嵌入式

2013-01-15 10:02:31

/**
 * 实现向AU9540模块收发串口数据
 * 为了程序的可移植性,此文件的API和手持POS里串口部分API保持一致
 *
 * Greate Date:2013.1.4
 */
#include       /*标准输入输出定义*/
#include 
#include      /*标准函数库定义*/
#include      /*Unix 标准函数定义*/
#include   /*数据类型,比如一些XXX_t的那种*/
#include    /*定义了一些返回值的结构,没看明白*/
#include       /*文件控制定义*/
#include     /*PPSIX 终端控制定义*/
#include       /*错误号定义*/

#define UART_DEV    "/dev/ttyS0"
#define DELAY_TIME	50	/*延时时间50MS*/
#define M_Delay(mSec)	usleep(mSec*1000)	/*MS延时*/
static int g_UartFd = 0;	// 保存串口打开的文件句柄

/**
 * 功 能:设置串口通信速率
 * 输入参数:port->打开串口的文件句柄   speed->串口速度
 * 输出参数:
 * 返回值: 一直成功
 * 开发人员:
 * 修改记录:Lzy	2013-1-14
 */
void au_appuart_set_speed(unsigned int port, int speed)
{
	int speed_arr[] = { B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, B600, B300, };
	int name_arr[] = { 115200, 57600, 38400, 19200, 9600, 4800, 2400, 1200, 600, 300, };
	int i, status, fd;
	struct termios Opt;

	fd = port;
	tcgetattr(fd, &Opt);

	for (i = 0; i < sizeof(speed_arr) / sizeof(int); i++)
	{
		if (speed == name_arr[i])
		{
			/**
			 * tcflush函数刷清(抛弃)输入缓存(终端驱动程序已接收到,但用户程序尚未读)或输出缓存(用户程序已经写,但尚未发送)。
			 * queue参数应是下列三个常数之一:
			 * TCIFLUSH刷清输入队列。
			 * TCOFLUSH刷清输出队列。
			 * TCIOFLUSH刷清输入、输出队列。
			 */
			tcflush(fd, TCIOFLUSH);		//设置前flush
			cfsetispeed(&Opt, speed_arr[i]);
			cfsetospeed(&Opt, speed_arr[i]);

			/**
			 *通过tcsetattr函数把新的属性设置到串口上。
			 * tcsetattr(串口描述符,立即使用或者其他标示,指向termios的指针)
			 */
			status = tcsetattr(fd, TCSANOW, &Opt);
			if (status != 0)
			{
				perror("tcsetattr fd1");
				return;
			}
			tcflush(fd, TCIOFLUSH);	 //设置后flush
		}
	}
}

/**
 * 功     能:设置串口数据位,停止位和效验位
 * 输入参数:
 *  		 fd-> 打开的串口文件句柄
 *  		databits  数据位   取值 为 7 或者8
 *  		stopbits  停止位   取值为 1 或者2
 *  		parity    效验类型  取值为N,E,O,,S
 * 输出参数:
 * 返回值: 0 成功
 * 开发人员:
 * 修改记录:Lzy	2013-1-14
 */
int au_appuart_set_parity(unsigned int port, int databits, int stopbits, char parity)
{
	struct termios options;
	int fd;

	fd = port;
	if (tcgetattr(fd, &options) != 0)
		return -1;

	options.c_iflag = 0;
	options.c_cflag &= ~CSIZE;

	/*设置数据位数*/
	switch (databits)
	{
	case 5:
		options.c_cflag |= CS5;
		break;
	case 6:
		options.c_cflag |= CS6;
		break;
	case 7:
		options.c_cflag |= CS7;
		break;
	case 8:
		options.c_cflag |= CS8;
		break;
	default:
		return -1;
	}

	switch (parity)
	{
	case 'n':
	case 'N':
		options.c_cflag &= ~PARENB; /* Clear parity enable */
		options.c_iflag &= ~INPCK; /* Enable parity checking */
		break;
	case 'o':
	case 'O':
		options.c_cflag |= (PARODD | PARENB); /* */
		options.c_iflag |= INPCK; /* Disnable parity checking */
		break;
	case 'e':
	case 'E':
		options.c_cflag |= PARENB; /* Enable parity */
		options.c_cflag &= ~PARODD; /* */
		options.c_iflag |= INPCK; /* Disnable parity checking */
		break;
	case 'S':
	case 's': /*as no parity*/
		options.c_cflag &= ~PARENB;
		options.c_cflag &= ~CSTOPB;
		break;
	default:
		return -1;
	}

	/* 设置停止位*/
	switch (stopbits)
	{
	case 1:
		options.c_cflag &= ~CSTOPB;
		break;
	case 2:
		options.c_cflag |= CSTOPB;
		break;
	default:
		return -1;
	}

	options.c_iflag &= ~(INLCR | IGNCR | ICRNL | IUCLC); /* 输入参数的设置 */
	options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /* 不需要回车直接发送*/
	options.c_oflag &= ~OPOST; /* 输出参数的设置 */

	tcflush(fd, TCIFLUSH);
	options.c_cc[VTIME] = 0; /*  设置超时15 seconds*/
	options.c_cc[VMIN] = 0; /* Update the options and do it NOW */
	if (tcsetattr(fd, TCSANOW, &options) != 0)
	{
		perror("SetupSerial 3");
		return -1;
	}

	return 0;
}

/**
 * 功     能:设置串口
 * 输入参数:串口 速度 数据位  停止位 奇偶较检位
 * 输出参数:
 * 返回值: 0 成功
 * 开发人员:
 * 修改记录:Lzy	2013-1-14
 */
void au_appuart_set(unsigned int port, int speed, int databits, int stopbits, char parity)
{
	au_appuart_set_speed(port, speed);
	au_appuart_set_parity(port, databits, stopbits, parity);
}

/**
 * 函数功能: 打开串口模块
 * pcComName( 入口):"COM1","COM2","COM3","COM4",串口名称
 * phDevHandel( 出口):设备句柄
 * 返回值: 0x00-->打开成功
 * 		   : 0x89-->设备已经打开
 * 		   : 0x8E-->内存分配失败
 * 		   : 0x01-->其它错误
 */
int AU_OpenRS232(char *pcComName, int *phDevHandel)
{
	g_UartFd = open(UART_DEV, O_RDWR | O_NOCTTY/*| O_NONBLOCK , 0*/);	// 不阻塞打开串口
	if (g_UartFd < 0) 	// 检查串口打开是否成功
	{
		perror("open uart");
		return 1;
	}
	*phDevHandel = g_UartFd;

	return 0x00;
}

/**
 *  函数功能: 关闭串口模块
 *  pcComName( 入口):设备句柄
 *  phDevHandel( 出口):设备句柄
 *  返回值: 0x00-->关闭成功
 */
int AU_CloseRS232(int *phDevHandle)
{
	close(g_UartFd);
	*phDevHandle = g_UartFd = -1;
	return 0x00;
}

/**
 * 函数功能:设置RS232口的通讯方式
 * hDevHandel:设备名称
 * ucBPS: 0x01-->对应1200波特率			 *	  : 0x02-->对应2400波特率		 *	  : 0x03-->对应4800波特率
 *	  : 0x04-->对应9600波特率			 *	  : 0x05-->对应14400波特率		 *	  : 0x06-->对应28800波特率
 *	  : 0x07-->对应19200波特率			 *	  : 0x08-->对应57600波特率		 *	  : 0x09-->对应115200波特率
 *	  : 0x0A-->对应38400波特率
 *	  ucPAR:'N'-->无效验(缺省)         :'E'-->偶效验         :'O'-->奇效验
 *	  ucDBS: 0x07-->7位数据位, 0x08-->8位数据位(缺省)
 *	  返回值: 0x00-->成功		   : 0x8C-->设备未打开		   : 0x8B-->参数错误(ucBPS,ucPAR或者ucDBS值错误)
 *		   : 0x8D-->串口无法使用		   : 0x01-->其他错误(操作系统错误等)
 */
int AU_InitRS232(int hDevHandel, unsigned char ucBPS, unsigned char ucPAR, unsigned char ucDBS)
{
	int gprs_baudrate[] = { 1200, 2400, 4800, 9600, 14400, 28800, 19200, 57600, 115200, 38400 };
	int baud, port;

	port = hDevHandel;
	baud = gprs_baudrate[ucBPS - 1];

	au_appuart_set(port, baud, 8, 1, 'N');

	return 0;
}

/**
 * 函数功能:从指定设备读数据。提供毫秒级读写,当时时间的精度为10Ms,即小于10Ms按照0处理
 * 入口hDevHandel:设备句柄	    uiLength:计划接收长度,若接收长度为0默认接收成功
 * uiTimeout:超时时间(单位:毫秒):0表示按缺省的超时等待时间。若为负数,则一直等待。缺省的超时为1小时
 * 出口pvBuf:接收缓冲区	    *puiRetLen:实际接收的长度
 * 返回值: 0x00-->读设备或接收成功		   : 0x8C-->设备未打开		   : 0x8B-->参数错误(pvBuf或puiRetLen为空指针)		   : 0x01-->读设备或接收失败或打开方式错误
 */
int AU_ReadRS232Ms(int hDevHandel, unsigned int uiLength, int uiTimeOut, unsigned char *pvBuf, unsigned int *puiRetLen)
{
	int rtn = 0, len = 0;

	/* 串口数据的读取,uiTimeOut为超时时间,池uiTimeOut=0时则一直等待	 */
	do
	{
		rtn = read(hDevHandel, pvBuf, uiLength);
		if (rtn < 0)
		{
			perror("read\n");
			return rtn;
		}
		else if (rtn == 0) /* 没有读到数据*/
		{
			if (len > 0) /* 数据接收完成 */
				break;

			if (uiTimeOut > 0) /* 超时时间处理*/
			{
				if (uiTimeOut-- <= 1) /* 超时时间到*/
					break;
			}
			M_Delay(DELAY_TIME);
		}
		else
		{
			len += rtn; /* 长度增加 */
			pvBuf += rtn; /* 存储位置移动 */
			M_Delay(DELAY_TIME);
		}

	} while (uiTimeOut >= 0);

	*puiRetLen = len;

	return 0;
}

/**
 * 函数功能:往指定设备写数据
 * hDevHandel:设备句柄
 * pvBuf:发送缓冲区
 * uiLength:发送长度;若发送长度为0默认成功
 * uiTimeout:超时时间(单位:毫秒)  :0表示按缺省的超时等待时间。若为负数,则一直等待。缺省的超时为1小时
 * 返回值: 0x00-->写设备或发送成功		   : 0x8C-->设备未打开		   : 0x8B-->参数错误(pvBuf为空)		   : 0x01-->写设备或发送失败或打开方式错误
 * 		   : 'G'---->发送成功未确认
 */
int AU_WriteRS232Ms(int hDevHandel, unsigned int uiLength, int uiTimeOut, unsigned char *pvBuf)
{
	int rtn = 0;

	rtn = write(hDevHandel, pvBuf, uiLength);

	return rtn;
}
阅读(7149) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~