/**
*串口模块
*模块功能:串口的基本操作,打开和关闭操作,
*同时支持四个串口操作
* Author:Lzy
* Greate Date:2012.10.18
*/
#include/*标准输入输出定义*/
#include
#include/*标准函数库定义*/
#include/*Unix标准函数定义*/
#include/*数据类型,比如一些XXX_t的那种*/
#include/*定义了一些返回值的结构,没看明白*/
#include/*文件控制定义*/
#include/*PPSIX终端控制定义*/
#include/*错误号定义*/
#include"uart.h"
staticintfd_uart[MAXNUM_UART] = {-1, -1, -1, -1};//保存串口打开的文件句柄
/**
*打开串口
*返回:0成功1失败 ff已经打开
*/
intappuart_open(unsignedintport)
{
if(port >= MAXNUM_UART)
return1;
if(fd_uart[port]==-1)
{
if(port==0)
fd_uart[port]= open("/dev/ttyS0", O_RDWR
| O_NONBLOCK);
elseif(port==1)
fd_uart[port] = open("/dev/ttyS1", O_RDWR
| O_NONBLOCK);
elsefd_uart[port]= open("/dev/ttyS2", O_RDWR
| O_NONBLOCK);
}
// if(fd_uart[port] == -1)
// fd_uart[port] = open(UART_DEV[port], O_RDWR | O_NONBLOCK); //不阻塞打开串口
if(-1 ==
fd_uart[port])//检查串口打开是否成功
return1;
return0;
}
/**
*关闭串口
*/
voidappuart_close(unsignedintport)
{
if((port >= MAXNUM_UART) || (-1 == fd_uart[port]))
return;
close(fd_uart[port]);
fd_uart[port]
= -1;
}
/**
*设置串口通信速率
* port->打开串口的文件句柄speed->串口速度
*/
voidappuart_set_speed(unsignedintport,intspeed)
{
intspeed_arr[] ={ B115200, B57600, B38400, B19200, B9600,
B4800, B2400, B1200, B600, B300, };
intname_arr[] ={ 115200, 57600, 38400, 19200, 9600, 4800, 2400, 1200, 600, 300, };
inti,
status, fd;
structtermios Opt;
if(port >= MAXNUM_UART)
return;
fd
= fd_uart[port];
if(fd
< 0)
return;
tcgetattr(fd,
&Opt);
for(i
= 0; i
/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
*/
intappuart_set_parity(unsignedintport,intdatabits,intstopbits,charparity)
{
structtermios options;
intfd;
if(port >= MAXNUM_UART)
return-1;
fd
= fd_uart[port];
if(fd
< 0)
return-1;
if(tcgetattr(fd, &options) != 0)
return-1;
options.c_iflag=
0;
options.c_cflag&= ~CSIZE;
/*设置数据位数*/
switch(databits)
{
case5:
options.c_cflag|= CS5;
break;
case6:
options.c_cflag|= CS6;
break;
case7:
options.c_cflag|= CS7;
break;
case8:
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)
{
case1:
options.c_cflag&= ~CSTOPB;
break;
case2:
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;
}
return0;
}
/**
*设置串口
*参数:串口 速度 数据位停止位 奇偶较检位
*/
voidappuart_set(unsignedintport,intspeed,intdatabits,intstopbits,charparity)
{
appuart_set_speed(port,
speed);
appuart_set_parity(port,
databits, stopbits, parity);
}
/**
*数据发送
*/
intappuart_send(unsignedintport,char*buf,intlen)
{
intfd;
if(port >= MAXNUM_UART)
return1;
fd
= fd_uart[port];
if(fd
< 0)
return1;
write(fd,
buf, len);
return0;
}
/**
*接收字符串数据
*/
intappuart_recv(unsignedintport,unsignedchar*buf,intlen)
{
intfd,
rtn;
if(port >= MAXNUM_UART)
return-1;
fd
= fd_uart[port];
if(fd
< 0)
return-1;
rtn
= read(fd, buf, len);
if(rtn <= 0)
return0;
returnrtn;
}
/**
*获得串口的文件句柄
*/
intappuart_getfd(unsignedintport)
{
if(port > MAXNUM_UART)
return-1;
returnfd_uart[port-1];
}
/**
*函数功能: 打开串口模块
* pcComName(入口):"COM1","COM2","COM3","COM4",串口名称
* phDevHandel(出口):设备句柄
*返回值: 0x00-->打开成功
* : 0x89-->设备已经打开
* : 0x8E-->内存分配失败
* : 0x01-->其它错误
*/
intST_OpenRS232
(char* pcComName,int*phDevHandel)
{
intport, ret;
port
= atoi(pcComName + 3) - 1;
if(port>=0
&& port < MAXNUM_UART)
{
if(fd_uart[port]<0)
fd_uart[port]=appuart_open(port);
else
return0x89;
*phDevHandel
= port;
}
else
return0x8e;
return0x00;
}
/**
*函数功能:
关闭串口模块
*
pcComName(入口):设备句柄
*
phDevHandel(出口):设备句柄
*返回值: 0x00-->关闭成功
*/
intST_CloseRS232
(int*phDevHandle)
{
appuart_close(*phDevHandle);
*phDevHandle = -1;
return0x00;
}
/**
*函数功能:设置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-->其他错误(操作系统错误等)
*/
intST_InitRS232(inthDevHandel,unsignedcharucBPS,unsignedcharucPAR,unsignedcharucDBS)
{
intgprs_baudrate[] = {1200, 2400, 4800, 9600, 14400, 28800, 19200, 57600, 115200,
38400 };
intbaud, port;
port=hDevHandel;
baud = gprs_baudrate[ucBPS - 1];
appuart_set(port, baud, 8, 1,'N');
return0;
}
/**
*函数功能:清除RS232的接收缓冲区
* hDevHandel:设备句柄
*返回值: 0x00-->成功: 0x8C-->设备未打开:
0x8D-->串口无法使用: 0x01-->其他错误(操作系统错误等)
*/
intST_ClearRS232(inthDevHandel)
{
charbuf[1024];
appuart_recv(hDevHandel, buf, 1024);
return0x00;
}
/**
*函数功能:从指定设备读数据。提供毫秒级读写,当时时间的精度为10Ms,即小于10Ms按照0处理
*入口hDevHandel:设备句柄uiLength:计划接收长度,若接收长度为0默认接收成功
* uiTimeout:超时时间(单位:毫秒):0表示按缺省的超时等待时间。若为负数,则一直等待。缺省的超时为1小时
*出口pvBuf:接收缓冲区*puiRetLen:实际接收的长度
*返回值: 0x00-->读设备或接收成功: 0x8C-->设备未打开:
0x8B-->参数错误(pvBuf或puiRetLen为空指针): 0x01-->读设备或接收失败或打开方式错误
*/
intST_ReadRS232Ms
(inthDevHandel,unsignedintuiLength,intuiTimeOut,char*pvBuf,unsignedint*puiRetLen)
{
intport = hDevHandel;
intrtn
= 0, i, len=0;
inttimes = uiTimeOut;
if(uiTimeOut==0)
times=3600*60;
for(i
= 0; i < times; i++)
{
if(len >= uiLength)
break;
while((rtn = appuart_recv(port, pvBuf, uiLength)) > 0)
{
*pvBuf
+= rtn;
len
+= rtn;
if(len >= uiLength)
break;
usleep(1000*1);
}
usleep(1000
*1);
}
*puiRetLen
= len;
if(len == 0)
return1;
return0;
}
/**
*函数功能:往指定设备写数据
* hDevHandel:设备句柄
* pvBuf:发送缓冲区
* uiLength:发送长度;若发送长度为0默认成功
* uiTimeout:超时时间(单位:毫秒):0表示按缺省的超时等待时间。若为负数,则一直等待。缺省的超时为1小时
*返回值: 0x00-->写设备或发送成功: 0x8C-->设备未打开:
0x8B-->参数错误(pvBuf为空): 0x01-->写设备或发送失败或打开方式错误
* : 'G'---->发送成功未确认
*/
intST_WriteRS232Ms(inthDevHandel,unsignedintuiLength,intuiTimeOut,char*pvBuf)
{
intport = hDevHandel;
intrtn
= 0;
intlen
= strlen(pvBuf);
if(len
> uiLength)
len = uiLength;
print_hexbuf(pvBuf, uiLength);//按16进制格式打印
字符数据 至屏幕
rtn
= appuart_send(port, pvBuf, len);
returnrtn;
}