Win32串行通信库(LibSp)是一个软件开发包,是一个基于Windows串行通讯API的静态链接库。 LibSp使用标准的Windows API与任何串口设备通讯。 LibSp支持如下功能: 可控制任何连接到串行RS232端口的设备。可用于GUI模式或控制台模式的程序。可同时控制多个端口(创建多个端口句柄)。包括硬件和软件流控制。兼容RS232,RS485串行端口。完全线程安全。支持在Windows 95/98/Me/NT/2000/XP/Vista/Windows 7下使用以回调函数形式,支持异步通讯事件通知机制。
简单使用示例如下:
// TestMyLibPs.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "TestMyLibPs.h"
#include "libsp.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#pragma comment(lib, "libsp.lib")
#pragma comment(linker, "/NODEFAULTLIB:libc.lib")
/
// The one and only application object
CWinApp theApp;
using namespace std;
void OnError(HANDLE hCom, int ErrorCode) // 错误通知回调函数
{
switch(ErrorCode)
{
case EVENT_ERROR_FRAME:
cout<<_T("硬件帧错误")<<endl;
break;
case EVENT_ERROR_OVERRUN:
cout<<_T("字符缓冲区溢出")<<endl;
break;
case EVENT_ERROR_RXOVER:
cout<<_T("接收缓冲区溢出")<<endl;
break;
case EVENT_ERROR_RXPARITY:
cout<<_T("硬件校验错误")<<endl;
break;
case EVENT_ERROR_TXFULL:
cout<<_T("发送缓冲区满")<<endl;
break;
default:
cout<<_T("不明错误代码: ")<<(int*)ErrorCode<<endl;
break;
}
}
void OnRecData(HANDLE hCom, size_t Count) // 接受到数据回调函数
{
cout<<_T("接收到一个字符")<<endl;
if(Count)
{
char* pBuf = (char*)malloc((Count + 1) * sizeof(char)) ;
__try
{
memset(pBuf, 0, Count + 1);
ComRd(hCom, pBuf, Count);
cout<<pBuf<<" -- "<<Count<<endl;
}
__finally
{
if(pBuf)
free(pBuf);
}
}
}
void OnRecChar(HANDLE hCom, size_t Count) // 接受到特定字符回调函数
{
cout<<_T("接收到用户指定字符")<<endl;
if(Count)
{
char* pBuf = (char*)malloc((Count + 1) * sizeof(char)) ;
__try
{
memset(pBuf, 0, Count + 1);
ComRd(hCom, pBuf, Count);
cout<<pBuf<<" -- "<<Count<<endl;
ComWrt(hCom, pBuf, Count);
}
__finally
{
if(pBuf)
free(pBuf);
}
}
}
void OnCts(HANDLE hCom, BOOL bCtsON) // CTS信号改变通知回调函数
{
cout<<_T("接收到 CTS 信号")<<endl;
if(bCtsON)
{
cout<<_T("CTS")<<" -- "<<_T("ON")<<endl;
}
else
cout<<_T("CTS")<<" -- "<<_T("OFF")<<endl;
}
void OnDrs(HANDLE hCom, BOOL bCrsON) // DRS信号改变通知回调函数
{
cout<<_T("接收到 DRS 信号")<<endl;
if(bCrsON)
{
cout<<_T("DRS")<<" -- "<<_T("ON")<<endl;
}
else
cout<<_T("DRS")<<" -- "<<_T("OFF")<<endl;
}
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
cerr << _T("Fatal Error: MFC initialization failed") << endl;
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.
char** pSerialPortName = NULL; // 端口字符串数组
size_t SerialPortNum = 0; // 端口数量
cout<<_T(" LIBSP Version: ")<<ComLibVer()<<endl; // 显示LibSp版本
if( GetComs(&pSerialPortName, &SerialPortNum) >= 0 ) // 获得本机串口信息
{
cout<<_T("本机发现 ")<<SerialPortNum<<_T(" 个串行端口,名称如下:")<<endl;
for(size_t i = 0; i < SerialPortNum; i++)
{
cout<<pSerialPortName[i]<<endl;
}
if(pSerialPortName)
FreeComs(pSerialPortName);
return 0;
}
CONFIG PsCfg; //声明LibSp串口配置结构变量
memset(&PsCfg, 0, sizeof(PsCfg)); //字段全部清零,这样某些你不希望填写的字段可以取默认值
PsCfg.pFnArray.OnReceiveChar_EVENT = OnRecChar; // 关心的事件,填写回调函数地址
// PsCfg.pFnArray.OnReceiveData_EVENT = OnRecData; // 不关心的可以不填
PsCfg.pFnArray.OnCtsStatusChange_EVENT = OnCts;
PsCfg.pFnArray.OnDsrStatusChange_EVENT = OnDrs;
// PsCfg.pFnArray.OnError_EVENT = OnError;
PsCfg.mask = SPCF_PORTNAME | SPCF_BAUDRATE | SPCF_PARITY |
SPCF_DATABITS | SPCF_STOPBITS | SPCF_FLOWCONT |
SPCF_NULLDISCARD | SPCF_EVENTCHAR; // 掩码,表示以下字段哪些有效。如果仅仅使用SPCF_PORTNAME则其他参数都自动取默认值
PsCfg.bDataBits = 8; // 8数据位
PsCfg.bParity = 0; // 无校验
PsCfg.bStopBits = 0; // 1停止位(注意哦)
PsCfg.dwBaudRate = 115200; // 波特率 115200
PsCfg.pszPortName = "COM3"; // 通讯端口名,注意这里用的是字符串不同于cvi的数字
PsCfg.flowControl = NoFlowControl; // 无流控
PsCfg.fDiscardNull = 0; // 取默认值
PsCfg.EventChar = 'T'; // 事件字符
HANDLE hCom = OpenComCfg( &PsCfg ); // 打开串口
if( hCom > 0 )
{
cout<<_T("串行端口 ")<<PsCfg.pszPortName<<_T("打开成功")<<endl;
char* szTitleString = _T("FASM LibSp Win32 SerialPort Library COOL!");
ComWrt(hCom, szTitleString, strlen(szTitleString)); // 些测试字串
while(getchar())
{
CloseCom(hCom); // 关闭串口
break;
}
}
}
return nRetCode;
}
下载cvi例子: