VC++ API串口通讯只能发送一次数据,无法接受

zhouyj-csdn 2018-05-28 10:03:19
本人接触这个不久,问题可能有点小儿科,是这样的,我仿照CSerialPort类写了一个类,可是有很多问题,我是用串口通讯助手来测试发送接收数据的。
1, ClosePort 中SetEvent(m_hShutdownEvent);为什么不能直接触发ThreadPro_C1中的MsgWaitForMultipleObjects。
2,只能发送一次,第二次发送没反应。
希望有大神可以帮我指出我的错误,谢谢了。


CCom_C1::CCom_C1(void)
: m_strData(_T(""))
,m_nTimeOut(10000)
,m_bSending(FALSE)
, m_hWnd(NULL)
{
hComm = NULL;
m_nPort= 0;
m_nBaud= 0;
m_nData= 0;
m_nParity= 0;
m_nStop = 0;

m_bComOpen= FALSE;
m_bThreadAlive = FALSE;
///初始化异步结构体
m_ov.Offset = 0;
m_ov.OffsetHigh = 0;

// create events
m_ov.hEvent = NULL;
m_hWriteEvent = NULL;
m_hShutdownEvent = NULL;
// create events
m_ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
m_hWriteEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
m_hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

m_hEventArray[0] = m_hShutdownEvent; // highest priority
m_hEventArray[1] = m_hWriteEvent;
m_hEventArray[2] = m_ov.hEvent;

InitializeCriticalSection(&m_csCommunicationSync);
}

CCom_C1::~CCom_C1(void)
{
// close Handles
if (m_hShutdownEvent != NULL)
{
CloseHandle(m_hShutdownEvent);
}
if (m_ov.hEvent != NULL)
{
CloseHandle(m_ov.hEvent);
}
if (m_hWriteEvent != NULL)
{
CloseHandle(m_hWriteEvent);
}
//释放临界资源
DeleteCriticalSection(&m_csCommunicationSync);
}

BOOL CCom_C1::OpenPort(HWND hWnd)
{
if(!IsWindow(hWnd)) return false;
if (IsOpen())
{
return true;
}

m_hWnd = hWnd;
m_bSending = FALSE;
m_strData = _T("");
m_strData.Empty();



//进入临界区
EnterCriticalSection(&m_csCommunicationSync);
CString szCom;
szCom.Format(_T("\\\\.\\COM%d"), m_nPort);
hComm = CreateFile(szCom.GetBuffer(50),
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL|
FILE_FLAG_OVERLAPPED, // Async I/O
NULL);
if(hComm==INVALID_HANDLE_VALUE)
{
DWORD dwErr= GetLastError();
::MessageBox(NULL,_T("Cannot Open Communication Port.Please Check Communication Port Setting Whether Correctly."),_T("PLC Com Port Error"),MB_OK+MB_ICONERROR);
m_bComOpen=false;
return FALSE;
}

DCB m_dcb;
memset(&m_dcb,0,sizeof(m_dcb));
if(GetCommDCB(&m_dcb))///获取当前DCB参数
{
if (!SetCommDCB(&m_dcb))//设置新参数
{
//错误处理
CloseHandle(hComm);
hComm=NULL;
m_bComOpen =false;
return FALSE;
}
}
else//错误处理,不能获取当前配置
{
CloseHandle(hComm);
hComm=NULL;
m_bComOpen =false;
return FALSE;
}

COMMTIMEOUTS m_CommTimeouts;
if(GetCommTimeouts(hComm, &m_CommTimeouts))
{
m_CommTimeouts.ReadIntervalTimeout =MAXDWORD;//指定了在接收字符间的最大时间,如果超过了这个时间,ReadFile立即返回
m_CommTimeouts.ReadTotalTimeoutConstant = 0;//表示读数据总时间常量
m_CommTimeouts.ReadTotalTimeoutMultiplier = 0;//表示平均读一个字节的时间上限
m_CommTimeouts.WriteTotalTimeoutConstant = 2000;//表示写数据总超时常量
m_CommTimeouts.WriteTotalTimeoutMultiplier =50;//表示平均写一个字节的时间上限
}
else
{
m_bComOpen =false;
return FALSE;
}
//给定串口读与操作限时
if(!SetCommTimeouts(hComm, &m_CommTimeouts))
{
TRACE(_T("SetCommTimeouts Error!"));
CloseHandle(hComm);
hComm=NULL;
m_bComOpen =false;
return FALSE;
}
// 设置串口缓冲区,输入/输出大小(字节数)
SetupComm(hComm, 1024, 1024);
// 用来指定程序接收特定的串口事件_收到字符放入缓冲区
SetCommMask(hComm, EV_RXCHAR) ;//监视串口中有无数据,一旦就激活WaitCommEvent。(设置我们关心的事件)
//刷清缓冲区,终止读写并清空接收和发送
PurgeComm(hComm, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ) ;
LeaveCriticalSection(&m_csCommunicationSync);

m_bComOpen=true;
m_Thread = ::CreateThread(NULL, 0, ThreadProc_C1, this, 0, NULL);
m_bThreadAlive=TRUE;

return TRUE;
}

void CCom_C1::ClosePort()
{
MSG message;

if (!IsOpen())//当端口未打开时
{
return;
}
m_bSending = FALSE;
m_bThreadAlive=FALSE;

//设置所有事件无效无效
SetCommMask(hComm, 0);
//清空所有将要读的数据
PurgeComm( hComm, PURGE_RXCLEAR |PURGE_RXABORT|PURGE_TXCLEAR|PURGE_TXABORT);

if (SuspendThread(m_Thread)!=-1)
{
ResumeThread(m_Thread);
}
do
{
SetEvent(m_hShutdownEvent);//通知关闭系统
Sleep(1000);
if (::PeekMessage(&message, m_hWnd, 0, 0, PM_REMOVE))
{
::TranslateMessage(&message);
::DispatchMessage(&message);
}
} while (m_bThreadAlive);


//关闭串口句柄
if(hComm = INVALID_HANDLE_VALUE)
{
m_bComOpen =false;
}
else
{
CloseHandle(hComm);
hComm = NULL;
}


}

void CCom_C1::WriteChar(CCom_C1* pThis)
{
DWORD dwStartTime = 0;
while(pThis->m_bThreadAlive)
{
PC1_CMD_SEND_INFO pCmdInfo = pThis->GetNextCmd();
if(pCmdInfo)
{
pThis->m_nCmdSending = pCmdInfo->nCmd;

PBYTE sendData=(LPBYTE)pCmdInfo->szCmd;
int sendLen= strlen(pCmdInfo->szCmd);
DWORD BytesSend=0;
DWORD dwError;
COMSTAT m_comstat;
EnterCriticalSection(&pThis->m_csCommunicationSync);
ResetEvent(pThis->m_hWriteEvent);
// Initailize variables
pThis->m_ov.Offset = 0;
pThis->m_ov.OffsetHigh = 0;

PurgeComm(pThis->hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
ClearCommError(pThis->hComm,&dwError,&m_comstat);
if (!WriteFile(pThis->hComm,sendData, sendLen,&BytesSend,&pThis->m_ov))
{
DWORD dwError = GetLastError();
}
GetOverlappedResult(pThis->hComm,&pThis->m_ov,&BytesSend,TRUE); // Wait flag
LeaveCriticalSection(&pThis->m_csCommunicationSync);
delete []pCmdInfo->szCmd;
pCmdInfo->szCmd = NULL;
delete pCmdInfo;
}
}
}

//响应函数
void CCom_C1::ReceiveStr(CCom_C1* pThis)
{
DWORD dwRealRead;
DWORD dwError;
DWORD dwWantRead;
COMSTAT m_comstat;

for (;;)
{
EnterCriticalSection(&pThis->m_csCommunicationSync);
//防止死锁
if (WaitForSingleObject(pThis->m_hShutdownEvent, 0) == WAIT_OBJECT_0)
return;

if(pThis->m_nCmdSending == C1_No)//此时没有任何指令
{
pThis->ClearReadBuffer();
return;
}
pThis->m_bSending = true;//发送接受进行时
ClearCommError(pThis->hComm,&dwError,&m_comstat);
dwWantRead=m_comstat.cbInQue;
if (m_comstat.cbInQue == 0 || m_comstat.cbInQue == 0xcccccccc)
{
break;
}
//如果遇到'\0',那么数据会被截断,实际数据全部读取只是没有显示完全,这个时候使用memcpy才能全部获取
char RXBuff[512];
memset(RXBuff,0,sizeof(char)*512);
dwWantRead = min(dwWantRead,512);
RXBuff[dwWantRead] = '\0';//附加字符串结束符
ReadFile(pThis->hComm,RXBuff,dwWantRead,&dwRealRead,&pThis->m_ov);
pThis->m_strData += RXBuff;
GetOverlappedResult(pThis->hComm,&pThis->m_ov,&dwRealRead,TRUE);
::PostMessage(pThis->m_hWnd , WM_PEEKCOMDATA, MAKEWPARAM(0,pThis->m_nCmdSending), 1); //工作线程中不要修改主界面,发送消息响应
LeaveCriticalSection(&pThis->m_csCommunicationSync);

pThis->ClearReadBuffer();
pThis->m_strData = _T("");
pThis->m_bSending = false;
}
}

DWORD WINAPI CCom_C1::ThreadProc_C1(LPVOID lParam)//LPVOID没有类型的指针
{
CCom_C1 * pThis = (CCom_C1 *) lParam;
DWORD BytesTransfered = 0;
DWORD Event;
DWORD CommEvent;
DWORD dwError = 0;
COMSTAT comstat;

BOOL bResult = TRUE;

if (pThis->hComm) // check if the port is opened
{
PurgeComm(pThis->hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
}

for (;;)
{
bResult = WaitCommEvent(pThis->hComm, &Event, &pThis->m_ov);///表示该函数是异步的
if (!bResult)
{
switch (dwError = GetLastError())
{
case ERROR_IO_PENDING: ///正常情况,没有字符可读 erroe code:997
{
break;
}
case ERROR_INVALID_PARAMETER:///系统错误 erroe code:87
{
break;
}
case ERROR_ACCESS_DENIED:///拒绝访问 erroe code:5
{
pThis->hComm = INVALID_HANDLE_VALUE;
TCHAR Temp[200] = { 0 };
_stprintf_s(Temp, 200, _T("COM%d ERROR_ACCESS_DENIED,WaitCommEvent() Error Code:%d"), pThis->m_nPort, GetLastError());
::MessageBox(NULL, Temp, _T("COM WaitCommEvent Error"), MB_ICONERROR);
break;
}
case ERROR_INVALID_HANDLE:///打开串口失败 erroe code:6
{
pThis->hComm = INVALID_HANDLE_VALUE;
::MessageBox(NULL, _T("Open COM Failed"), _T("COM Error"), MB_ICONERROR);
break;
}
case ERROR_BAD_COMMAND:///连接过程中非法断开 erroe code:22
{
pThis->hComm = INVALID_HANDLE_VALUE;
TCHAR Temp[200] = {0};
_stprintf_s(Temp, 200, _T("COM%d ERROR_BAD_COMMAND,WaitCommEvent() Error Code:%d"), pThis->m_nPort, GetLastError());
::MessageBox(NULL, Temp, _T("COM WaitCommEvent Error"), MB_ICONERROR);
break;
}
default:///发生其他错误,其中有串口读写中断开串口连接的错误(错误22)
{
//发生错误时,将串口句柄置为无效句柄
pThis->hComm = INVALID_HANDLE_VALUE;
::MessageBox(NULL, _T("COM Other Problem"), _T("COM Error"), MB_ICONERROR);
break;
}
}
}
else ///WaitCommEvent()能正确返回
{
bResult = ClearCommError(pThis->hComm, &dwError, &comstat);
if (comstat.cbInQue == 0)
continue;

} // end if bResult

Event = MsgWaitForMultipleObjects(3, ///3个事件
pThis->m_hEventArray, ///事件数组
FALSE, ///有一个事件发生就返回
INFINITE,
QS_ALLEVENTS);///超时时间

if (Event >= WAIT_OBJECT_0 && Event < WAIT_OBJECT_0 + 3)
{
for (int i = Event - WAIT_OBJECT_0 - 1; i < 3; i++)
{
if (WaitForSingleObject(pThis->m_hEventArray[i], 0) == WAIT_OBJECT_0)
{
switch (Event)
{
case WAIT_OBJECT_0 + 0:
{
///关断事件,关闭串口
CloseHandle(pThis->hComm);
pThis->hComm = NULL;
pThis->m_bThreadAlive = FALSE;
pThis->m_bComOpen=false;
pThis->RemoveAllCmdFromList();
::ExitThread(1000);

break;
}
case WAIT_OBJECT_0 + 1: // write event 发送数据
{
// Write character event from port
WriteChar(pThis);
break;
}
case WAIT_OBJECT_0 + 2: // read event 将定义的各种消息发送出去
{
GetCommMask(pThis->hComm, &CommEvent);
if (CommEvent & EV_RXCHAR) //接收到字符,并置于输入缓冲区中
{
ReceiveStr(pThis);
}
break;
}
} // end switch
}
}
}
}
return 0;
}
...全文
1307 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
sevancheng 2018-06-22
  • 打赏
  • 举报
回复
WaitForMultipleObjects
这不是鸭头 2018-06-22
  • 打赏
  • 举报
回复
串口类都烂大街了还用自己写?
tiger波波 2018-06-15
  • 打赏
  • 举报
回复
ClosePort 中SetEvent(m_hShutdownEvent);为什么不能直接触发ThreadPro_C1中的MsgWaitForMultipleObjects。 -------------------- 你的程序是不是占用CPU很高?你的for循环里边没有Sleep,貌似别的线程插不进去手。你试下加个Sleep试试。 for(...) { ..... ..... Sleep(10); }
新人码农 2018-05-28
  • 打赏
  • 举报
回复
CSerialPort没试过,我用的是Win32API函数,https://blog.csdn.net/cjdxzy2010/article/details/6120391
赵4老师 2018-05-28
  • 打赏
  • 举报
回复
百度搜相关关键字。
目录 前言 第1章 Windows CE及开发环境概述 1.1 Windows CE概述 1.1.1 Windows CE嵌入式系统概述 1.1.2 Windows CE版本 1.1.3 Windows CE 6.0概述 1.1.4 嵌入式开发流程 1.2 开发环境概述 1.2.1 Visual Studio 2005的Visual C++——Windows CE开发环境概述 1.2.2 示例程序HelloWorld 1.3 Windows CE附带远程工具概述 第2章 图形编程 2.1 设备环境类 2.2 图形对象类(GDI) 2.3 绘制各种图形 2.4 绘制位图 2.4.1 CDC绘图函数描述 2.4.2 动画效果 2.4.3 抓屏 2.4.4 图形显示特技 2.5 显示压缩格式图片 2.5.1 SHLoadImageFile方法 2.5.2 Imaging技术 2.6 简单二维曲线示例 2.6.1 二维曲线类C2Dgraph的创建 2.6.2 使用二维曲线类C2DGraph绘制曲线 第3章 对话框控件 3.1 常用控件 3.1.1 微调按钮 3.1.2 滑动条 3.1.3 进度条 3.1.4 列表视图控件 3.1.5 树控件 3.2 创建图形显示控件 3.3 创建LED数字显示控件 第4章 进程 4.1 进程 4.1.1 进程概述 4.1.2 进程创建 4.1.3 进程终止 4.1.4 其他进程函数 4.1.5 “进程列举并管理”实例 4.2 进程间通讯 第5章 线程 5.1 线程 5.1.1 线程概述 5.1.2 线程优先级 5.1.3 线程API函数 5.2 线程同步 5.2.1 未使用线程同步 5.2.2 利用事件同步 5.2.3 利用互斥同步 5.2.4 利用临界区同步 5.2.5 利用信号量同步 第6章 文件 6.1 文件基本操作 6.2 文件综合操作示例 6.3 内存映射文件 6.3.1 内存映射文件概述 6.3.2 利用内存映射文件实现进程间通讯 6.4 文件系统管理 6.5 注册表编程 6.5.1 注册表简介 6.5.2 注册表API函数 6.5.3 注册表操作举例 第7章 多媒体编程 7.1 Direct Show介绍 7.1.1 DirectShow技术框架 7.1.2 过滤器(Filter) 7.1.3 Filter Graph Manager 7.1.4 Pin 7.1.5 DirectShow 接口定义介绍 7.2 媒体播放器示例 7.3 摄像头捕捉示例 7.3.1 摄像头捕捉概述 7.3.2 摄像头捕捉示例 第8章 Windows CE基础数据库编程 8.1 EDB概述 8.1.1 装配数据卷 8.1.2 卸载数据库卷 8.1.3 创建数据库 8.1.4 创建会话对象 8.1.5 打开数据库 8.1.6 事务操作 8.1.7 删除数据库 8.1.8 枚举数据库卷以及数据库 8.1.9 查找或移动记录 8.1.10 写记录 8.1.11 读取记录 8.1.12 删除记录 8.1.13 流操作 8.2 数据库操作综合示例 第9章 SQLCE数据库编程 9.1 SQL Server FOR CE的介绍 9.1.1 SQLCE简介 9.1.2 SQL Server CE 3.0的安装 9.1.3 SQLCE 3.0连接配置 9.2 OLEDB 编程访问SQLCE 3.0 9.2.1 OLE DB 概述 9.2.2 OLEDB 编程 9.3 SQLCE远程数据访问 9.3.1 Pull(拉数据) 9.3.2 Push(推数据) 9.3.3 Submit(远程T-SQL操作) 9.4 远程数据访问综合示例 第10章 串口编程 10.1 串口概述 10.2 串口编程API函数介绍 10.3 CE串口综合示例 10.4 GPS编程示例 第11章 网络编程概述 11.1 套接字编程基础 11.1.1 WinSock初始化和释放 11.1.2 创建套接字 11.1.3 关闭套接字 11.1.4 绑定套接字 11.1.5 监听套接字 11.1.6 等待连接 11.1.7 建立连接 11.1.8 发送数据 11.1.9 接收数据 11.1.10 设置套接字模式 11.1.11 Select I/O模型 11.2 PING编程 11.2.1 PING编程概述 11.2.2 PING编程示例 11.3 RAS拨号编程 11.3.1 建立拨号连接 11.3.2 关闭拨号连接 11.3.3 列举已建立的活动连接 11.3.4 列举电话簿条目 第12章 UDP编程 12.1 UDP编程概述 12.2 UDP编程示例 第13章 TCP编程 13.1 TCP编程概述 13.2 TCP客户端示例 13.3 TCP服务器端示例 第14章 DLL编程 14.1 DLL概述 14.2 DLL的调用 14.2.1 静态调用 14.2.2 动态调用 14.3 DLL的创建 14.3.1 Windows CE DLL的创建 14.3.2 基于MFC的Regular DLL的创建 14.3.3 资源DLL 第15章 COM编程 15.1 COM基本知识概述 15.1.1 什么是COM 15.1.2 什么是接口 15.1.3 COM基本结构 15.2 使用ATL创建COM示例 15.2.1 ATL对COM支持概述 15.2.2 ATL创建COM对象示例 15.2.3 创建客户端调用CEComServer 15.3 可连接点对象及示例 15.3.1 可连接点对象概述 15.3.2 连接点示例 15.4 创建ActiveX控件 15.4.1 ActiveX概述 15.4.2 使用MFC向导创建一个简单的ActiveX控件
短信猫:又称GSM MODEM,GSM猫,无线猫,短信模块,GSM模块,短信设备。根据集成模块的个数不同,又分为单猫和猫池两种。 短信猫是什么?短信猫其实是一种支持GSM无线通讯的工业级调制解调器,一般基于法国WAVECOM或德国SIEMENS(西门子)GSM模块,插入国内移动通信运营商的SIM卡后即可接入运营商GSM网络,实现无线GSM通话、短信、数据等功能。与手机相比,实际上核心模块一致,只是手机多了屏幕、键盘以及软件界面支持,而短信猫是在PC上通过串口通讯用AT指令去控制的,但两者能完成的短信收发功能是完全相同的。 随着手机及短信的普及,越来越多的行业开始发展企业短信应用,短信猫设备凭借其低成本、稳定可靠的点对点通信、方便快捷接入的优势已经成为企业短信领域重要的短信接入方式之一。中德福林依托其强大的研发实力、多年的无线通信经验,推出了一系列短信猫产品,除了原装正版的WAVECOM GSM MODEM,自身更是研发了多种型号的短信猫设备,基本上基于WAVECOM核心模块,接口包括串口(RS232)、USB接口、PCI接口、网口等,并提供一系列短信猫开发包及示例程序,支持VC/VC++/VB/DELPHI/PB/C#/.NET/ASP/JAVA/JSP二次开发。 短信猫设备二次开发接口 基于短信猫开发行业短信应用,软件开发商可以采取以下三种方式: 直接使用AT指令:基于串口通讯模式使用AT指令直接操作短信猫,这是最底层的短信猫开发模式,但是我们建议客户尽量不采用此方法,因为这种方式需要对短信猫的AT指令及特性非常熟悉。 短信猫二次开发包:短信猫厂商针对软件开发商短信应用提供的二次开发包,其底层是基于短信猫的AT指令,对于软件开发商只需要调用二次开发包或者控件中的API即可。基于多年的开发经验,为客户提供一套基于动态链接库(DLL)技术的短信猫开发包,可以支持所有的 WINDOWS 环境下开发工具,也提供支持 JAVA 开发的 JAR 包。 短信猫通信中间件:这是我们独家提供的基于数据库接口的短信猫通信服务器软件,软件开发商只需要提交短信队列到数据库里即可,开发简单快速,节约人力成本,是最佳的短信应用开发接口模式。 短信猫的优势 基于短信猫建立行业短信应用,具有如下优势: 投入低:无需购置接入服务器,只需购置经济的短信猫设备; 安装维护方便:短信猫设备容易安装,维护手段简便易用; 安全性好:服务采用自服方式,不需经第三方,信息保密,整个应用都在企业的控制之内; 用户覆盖面广:该服务能通过不同运营商的短信中心发送或接收短信息,兼容移动、联通的所有手机用户以及电信、网通的所有小灵通用户; 可靠性高:采用点对点的发送方式,优先级别高,稳定性好; 系统容量可扩展:通过简单添加通信模块就可以扩充系统容量; 业务开展自由:业务内容不受运营商限制,可以根据企业的具体需求进行业务和应用的定制; 接入门槛低:无需和运营商、服务提供商进行繁琐的商务谈判,只需一台短信猫就可以迅速构建企业自己的短信服务系统。 短 信 猫 直 销 网 产 品 简 介 欢迎由此查看本网短信猫产品规范及技术指标 短信猫,一般也叫做GSM MODEM,从英文名翻译过来,其实就是支持GSM制式通讯的调制解调器。所以,短信猫还有很多别称,如GSM猫,无线猫,短信模块,GSM短信模块等。因为大部分客户都是拿着GSM MODEM去收发短信,也就是在行业应用市场上,GSM MODEM最大的用途是用来收发短信,因此,大多数人还是称之为短信猫。 短信猫是什么?短信猫其实是一种支持GSM无线通讯的工业级调制解调器,一般基于法国WAVECOM或德国SIEMENS(西门子)GSM模块,插入国内移动通信运营商的SIM卡后即可接入运营商GSM网络,实现无线GSM通话、短信、数据等功能。 短信猫(GSM MODEM)的核心模块实际上就是手机的核心模块。当短信猫接通电源以后,GSM MODEM的内置软件就开始工作,如果您插入了某个移动运营商的SIM卡,GSM MODEM便完全就和手机一样接入到移动通信网络中去了。与此同时,计算机可以通过串口或USB连接GSM MODEM,通过一套AT指令,便可以操作GSM MODEM,例如收发短信。其实也可以拨打电话、收发传真等等,只是我们一般没有必要使用这些多余功能。因此短信猫(GSM MODEM)与手机的最大区别在于手机自带屏幕、键盘、应用软件,而短信猫相当于一个处于黑箱操作的手机,需要计算机去驱动和控制。 短信猫(GSM MODEM)的分类:按照与计算机的不同接口,短信猫可分为串口短信猫、USB接口短信猫、PCI接口短信猫、网口短信猫等。按照模块数的多少,短信猫可分为单口短信猫和短信猫池两种。短信猫池其实就是将多个模块集成到一起通过多串口或者网口与计算机形成多串口通讯,从而实现多个模块并发的设备。按照无线网络制式的不同,又可分为GSM短信猫、CDMA短信猫和小灵通短信猫。 短信猫开发接口(GSM MODEM SDK),基于短信猫开发行业短信应用,软件开发商可以采取以下四种方式:1、直接使用AT指令,基于串口通讯模式使用AT指令直接操作短信猫,这是最底层的短信猫开发模式,基本上无论是哪种接口的短信猫,其实质还是通过GSM MODEM的串口通讯AT指令来驱动的。2、短信猫开发包:短信猫厂商针对软件开发商短信应用提供的二次开发包,其底层是基于短信猫的AT指令,对于软件开发商只需要调用二次开发包或者控件中的API即可。3、短信猫通信中间件:这是一套的基于数据库接口的短信猫通信软件,用户只需提交短信队列到数据库即可进行短信收发。因此无论您用的是哪种开发语言,只要您能读写数据库即可。这种开发简单快速,节约人力成本,是最快捷的一种短信应用开发模式。4、直接使用由第三方提供的短信网关:这时其实已经没有必要再购买短信猫了(因为短信网关公司已经替您配备了类似设备),用户只需按照网关说明直接调用短信网关接口,系统就会自动实现短信收发。短信网关公司的网址为:SmsGate.CN。

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧