标签:style blog http 使用 os io 数据 for
希望这套API可以帮助有需要的人!
如果您有异议,请给出理由,让我可以改善存在的问题,谢谢。
如果您在使用中发现问题,请及时联系我。
我承认在用C++写 C,纯粹为了封装方便,如果是这个原因要喷我,那我替您先喷了..
虽说是跨平台但我测试的平台有限。
windows7 x32使用vs2008编译运行成功
Ubuntu12.04 x32 使用gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) 编译运行成功
arm-linux-gcc [ gcc version 4.3.3 (Sourcery G++ Lite 2009q1-203) ] 交叉编译成功
关于Linux下使用欢迎参考我的一篇短文
http://my.oschina.net/mlgb/blog/300925
#ifndef SERIALPORT_H_
#define SERIALPORT_H_
#include <stddef.h>
#ifdef _WIN32
#include <Windows.h>
typedef HANDLE serial_t;
#elif defined __linux__
typedef int serial_t;
#endif
enum COMPARAM
{
CHECK_NONE, //无校验
CHECK_ODD, //奇校验
CHECK_EVEN, //偶校验
STOP_1, //停止位1
STOP_1_5, //停止位1.5
STOP_2, //停止位2
DATA_7, //数据位7
DATA_8 //数据位8
};
enum COMIO
{
COM_IN, //输入选项
COM_OUT //输出选项
};
class SerialPort
{
public:
SerialPort(void);
~SerialPort(void);
/*
*打开串口
*Param:
* [IN]port COM端口
* [IN]opt Windows平台 是否启用重叠IO
* Linux平台 是否启用非阻塞方式
* */
bool
open(int port,bool opt = false);
/*
*关闭串口
* */
void
close();
/*
*设置串口属性
*Param:
* [IN]rate 波特率
* [IN]check_bit 校验位
* [IN]stop_bit 停止位(linux无1.5)
* [IN]data_bit 数据位
* */
bool
set_attribute( size_t rate,
COMPARAM check_bit = CHECK_NONE,
COMPARAM stop_bit = STOP_1,
COMPARAM data_bit = DATA_8);
/*
*设置超时
*Param:
* [IN]write_ms 写超时(单位 毫秒)
* [IN]read_ms 读超时(单位 毫秒)
* [IN]flag Windows下指定间隔延迟
Linux下指定非规范模式的最小字符数
*Other
* linux在非阻塞模式下设置超时无效
* 超时设置为0时“效果”等同于非阻塞模式
* read超时返回0
* */
bool
set_timeout(size_t write_ms,size_t read_ms,int flag = 0);
/*
*发送数据
*Param:
* [IN]sendBuf 发送数据缓存
* [IN]len 发送数据长度
*/
int
send(const char* sendBuf,size_t len);
/*
*接收数据
*Param:
* [OUT]recvBuf 接收数据缓存
* [IN] len 接收数据长度
*/
int
recv(char* recvBuf,size_t len);
/*
*终止IO操作
*Param:
* [IN]mode 指定需要操作的IO
*/
void
abort(COMIO mode);
/*
*清空缓冲区数据
*Param:
* [IN]mode 指定需要操作的IO
*/
void
clear_buff(COMIO mode);
/*
*开放使用和平台相关的高级IO操作
*如:
*LINUX下的select和poll模型
*WIN32下的Overlapped模型
* */
serial_t
get_serial_handle();
#ifdef _WIN32
/*
*获取接收缓冲区数据长度
*/
size_t
peek();
#endif
#ifdef __linux__
/*
*设置LINUX下串口阻塞方式
*Param:
* [IN]isBlock 是否阻塞
*/
bool
set_block(bool isBlock);
#endif
private:
serial_t m_hSerial;//串口句柄/描述符
};
#endif //SERIALPORT_H_
#include "SerialPort.h"
#include <stdio.h>
#ifdef _WIN32
#define INVALID_SERRAL INVALID_HANDLE_VALUE
#elif defined __linux__
#include <unistd.h>
#include <fcntl.h> //open close
#include <termios.h>//struct termios
#define INVALID_SERRAL -1
size_t t_raw_rate[] =
{
50, 75, 110, 134, 150,
200, 300, 600, 1200, 1800,
2400, 4800, 9600, 19200, 38400,
57600, 115200, 230400, 460800, 500000,
576000, 921600, 1000000, 1152000, 1500000,
2000000, 2500000, 3000000, 3500000, 4000000
};
size_t t_unix_rate[] =
{
B50, B75, B110, B134, B150,
B200, B300, B600, B1200, B1800,
B2400, B4800, B9600, B19200, B38400,
B57600, B115200, B230400, B460800, B500000,
B576000, B921600, B1000000, B1152000, B1500000,
B2000000, B2500000, B3000000, B3500000, B4000000
};
#endif
SerialPort::SerialPort(void)
{
m_hSerial = INVALID_SERRAL;
}
SerialPort::~SerialPort(void)
{
this->close();
}
bool
SerialPort::open(int port,bool opt)
{
char com[16]={0};
#ifdef _WIN32
#ifdef WINCE
sprintf(com,"COM%d:",port);
#else
sprintf(com,"COM%d",port);
#endif
DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
if(opt)
{
dwFlagsAndAttributes |= FILE_FLAG_OVERLAPPED;
}
m_hSerial = CreateFile(com, GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
dwFlagsAndAttributes,
NULL);
#elif defined __linux__
#ifdef __arm__
sprintf(com,"/dev/ttySAC%d",port-1);
#else
sprintf(com,"/dev/ttyS%d",port-1);
#endif
int flags = O_RDWR | O_NOCTTY;
if(opt)
{
flags |= O_NDELAY;
}
m_hSerial = ::open(com,flags);
#endif
return (m_hSerial != INVALID_SERRAL)?true:false;
}
void
SerialPort::close()
{
if(m_hSerial != INVALID_SERRAL)
{
#ifdef _WIN32
CloseHandle(m_hSerial);
#elif defined __linux__
::close(m_hSerial);
#endif
m_hSerial = INVALID_SERRAL;
}
}
bool
SerialPort::set_attribute( size_t rate,
COMPARAM check_bit,
COMPARAM stop_bit,
COMPARAM data_bit)
{
if(m_hSerial == INVALID_SERRAL) return false;
#ifdef _WIN32
DCB dcb = {0};
dcb.BaudRate = rate;
dcb.fParity = TRUE;
dcb.fBinary = FALSE;
if(check_bit == CHECK_NONE)
{
dcb.fParity = FALSE;
dcb.Parity = NOPARITY;
}
else if(check_bit == CHECK_ODD)
{
dcb.Parity = ODDPARITY;
}
else if(check_bit == CHECK_EVEN)
{
dcb.Parity = EVENPARITY;
}
if(stop_bit == STOP_1)
{
dcb.StopBits = ONESTOPBIT;
}
else if(stop_bit == STOP_1_5)
{
dcb.StopBits = ONE5STOPBITS;;
}
else if(stop_bit == STOP_2)
{
dcb.StopBits = TWOSTOPBITS;
}
if(data_bit == DATA_8)
{
dcb.StopBits = 8;
}
else if(data_bit == DATA_7)
{
dcb.StopBits = 7;
}
if( ! SetCommState(m_hSerial,&dcb) )
{
return false;
}
SetupComm(m_hSerial,50/*IN BUF*/,50/*OUT BUFF*/);
PurgeComm(m_hSerial,PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
#elif defined __linux__
struct termios com_cfg = {0};
size_t raw_rate = 0;
size_t i=0;
for(i=0; i< sizeof(t_raw_rate)/sizeof(size_t) ; i++)
{
if(t_raw_rate[i] == rate)
{
raw_rate = t_unix_rate[i];
break;
}
}
if(!raw_rate)
{
return false;
}
else
{
cfsetispeed(&com_cfg,raw_rate);//IN speend;
cfsetospeed(&com_cfg,raw_rate);//OUT speend;
}
switch(check_bit)
{
case CHECK_NONE:
com_cfg.c_cflag &= ~PARENB;
com_cfg.c_iflag &= ~INPCK;
break;
case CHECK_ODD:
com_cfg.c_cflag |= (PARODD|PARENB);
com_cfg.c_iflag |= INPCK;
break;
case CHECK_EVEN:
com_cfg.c_cflag |= PARENB;
com_cfg.c_iflag &= ~PARODD;
com_cfg.c_iflag |= INPCK;
break;
default:
return false;
}
switch(stop_bit)
{
case STOP_1:
com_cfg.c_cflag &= ~CSTOPB;
break;
case STOP_1_5:
com_cfg.c_cflag &= ~CSTOPB;//Linux没有1.5停止位
break;
case STOP_2:
com_cfg.c_cflag |= CSTOPB;
break;
default:
return false;
}
switch(data_bit)
{
case DATA_8:
com_cfg.c_cflag &= ~CSIZE;
com_cfg.c_cflag |= CS8;
break;
case DATA_7:
com_cfg.c_cflag &= ~CSIZE;
com_cfg.c_cflag |= CS7;
break;
default:
return false;
}
tcflush(m_hSerial,TCIOFLUSH);
com_cfg.c_cc[VTIME] = 0;
com_cfg.c_cc[VMIN] = 1;
if( tcsetattr(m_hSerial,TCSANOW,&com_cfg) )
{
return false;
}
#endif
return true;
}
bool
SerialPort::set_timeout(size_t write_ms,size_t read_ms,int flag)
{
if(m_hSerial == INVALID_SERRAL) return false;
#ifdef _WIN32
COMMTIMEOUTS to;
memset(&to,0,sizeof(to));
/* 读间隔超时。 接收时,两字符间最大的时延。
* 将ReadIntervalTimeout设置为0, 则不使用间隔超时, 只考虑总超时设置
* */
to.ReadIntervalTimeout = flag;
to.WriteTotalTimeoutMultiplier = 1;//写每字节的超时
to.WriteTotalTimeoutConstant = write_ms;//写串口数据的固定超时
// TIMEOUT = WriteTotalTimeoutMultiplier Bytecount + WriteTotalTimeoutConstant
to.ReadTotalTimeoutMultiplier = 1; //读取每字节的超时
to.ReadTotalTimeoutConstant = read_ms; //读串口数据的固定超时
// TIMEOUT = ReadTotalTimeoutMultiplier * Bytecount + ReadTotalTimeoutConstant
return (SetCommTimeouts(m_hSerial,&to) == TRUE)?true:false;
#elif defined __linux__
struct termios com_cfg = {0};
tcgetattr(m_hSerial,&com_cfg);//get old setting
com_cfg.c_cc[VTIME] = read_ms*0.01;//超时单位 百毫秒
com_cfg.c_cc[VMIN] = flag;//最少可读数据 超时有效必须是0
printf("[SET] VTIME(%d),VMIN(%d)\n",com_cfg.c_cc[VTIME],com_cfg.c_cc[VMIN]);
return (!tcsetattr(m_hSerial,TCSANOW,&com_cfg) )?true:false;
#endif
}
#ifdef __linux__
bool
SerialPort::set_block(bool isBlock)
{
if(m_hSerial == INVALID_SERRAL) return false;
if(isBlock)
{
printf("[SET] block mode\n");
return ( -1 == fcntl(m_hSerial,F_SETFL,0) )?false:true;
}
else
{
printf("[SET] no block mode\n");
return ( -1 == fcntl(m_hSerial,F_SETFL,FNDELAY) )?false:true;
}
return true;
}
#endif
int
SerialPort::send(const char* sendBuf,size_t len)
{
if(m_hSerial == INVALID_SERRAL) return 0;
#ifdef _WIN32
DWORD write_len = 0;
WriteFile(m_hSerial,sendBuf,len,&write_len,NULL);
return write_len;
#elif defined __linux__
return write(m_hSerial,sendBuf,len);
#endif
}
int
SerialPort::recv(char* recvBuf,size_t len)
{
if(m_hSerial == INVALID_SERRAL) return 0;
#ifdef _WIN32
DWORD read_len = 0;
ReadFile(m_hSerial,recvBuf,len,&read_len,NULL);
return read_len;
#elif defined __linux__
return read(m_hSerial,recvBuf,len);
#endif
}
void
SerialPort::abort(COMIO mode)
{
if(m_hSerial != INVALID_SERRAL)
{
if(mode == COM_IN)
{
#ifdef _WIN32
//中断所有读操作并立即返回,即使读操作还没有完成
PurgeComm(m_hSerial,PURGE_RXABORT);
#elif defined __linux__
tcflush(m_hSerial,TCIOFF);//挂起输入
#endif
}
else if(mode == COM_OUT)
{
#ifdef _WIN32
//中断所有写操作并立即返回,即使写操作还没有完成
PurgeComm(m_hSerial,PURGE_TXABORT);
#elif defined __linux__
tcflush(m_hSerial,TCOOFF);//挂起输出
#endif
}
}
}
void
SerialPort::clear_buff(COMIO mode)
{
if(m_hSerial != INVALID_SERRAL)
{
if(mode == COM_IN)
{
#ifdef _WIN32
PurgeComm(m_hSerial,PURGE_RXCLEAR);
#elif defined __linux__
tcflush(m_hSerial,TCIFLUSH);
#endif
}
else if(mode == COM_OUT)
{
#ifdef _WIN32
PurgeComm(m_hSerial,PURGE_TXCLEAR);
#elif defined __linux__
tcflush(m_hSerial,TCOFLUSH);
#endif
}
}
}
serial_t
SerialPort::get_serial_handle()
{
return m_hSerial;
}
#ifdef _WIN32
size_t
SerialPort::peek()
{
if(m_hSerial == INVALID_SERRAL)
{
return 0;
}
DWORD dwErrorFlags;
COMSTAT ComStat;
ClearCommError( m_hSerial, &dwErrorFlags, &ComStat );
return ComStat.cbInQue;
}
#endif
标签:style blog http 使用 os io 数据 for
原文地址:http://my.oschina.net/mlgb/blog/301567