📄 ysatmodem.cpp
字号:
// ATModem.cpp: implementation of the CYsATModem class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "YsATModem.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
UINT CYsATModem::WaitThread(LPVOID lpvoid)
{
CYsATModem* pThis=(CYsATModem*)lpvoid;
pThis->DetectConnect();
return 1;
}
//检测modem是否就续
UINT CYsATModem::DetectModemThread(LPVOID pParam)
{
TRACE(_T("in Detect Thread"));
CYsATModem* pThis=(CYsATModem*)pParam;
DWORD dwEvent;
DWORD dwTime;
int iRing=0;
pThis->m_bCD=0;
while(1==pThis->WaitEvent(&dwEvent,INFINITE))
{
if(dwEvent&EV_DSR)
{
pThis->SetEvent(0);
//糟啦,modem坏啦!!!
TRACE(_T("My God!!! the modem broken!!!\n"));
pThis->Purge(PURGE_ALL);
pThis->ChangeMode(MODE_UNMODEM);
TRACE(_T("Quit Detect Thread"));
return 1;
}
else if(dwEvent&EV_RING)//win95不支持这种通知
{
//这里有个问题,如果对方拨号一声后,挂断,计数器没清零,第二次就会出问题
if(iRing>0)
{
if(GetTickCount()-dwTime>10000)
iRing=0;//如果两次响铃大于10秒钟,重设为0
}
dwTime=GetTickCount();
iRing++;
CString s;
s.Format("ring count=%d %d Mode=%d\n",iRing,pThis->m_nRingCount,pThis->m_nMode);
TRACE(s);
if(pThis->m_nMode==MODE_COMMAND)
{
if(iRing>=pThis->m_nRingCount)
{
iRing=0;
#ifdef USER_ANSWER
Sleep(500);
pThis->SendAT(CMD_ATA);
#endif
AfxBeginThread(WaitThread,pThis);
}
}
}
else if(dwEvent&EV_RLSD)
{
CString s;
s.Format("\nCD灯改变 @@@ %d -%d\n",pThis->m_nMode,pThis->m_bCD);
TRACE(s);
if(pThis->m_nMode==MODE_DATA)
{
pThis->m_bCD=FALSE;
TRACE("Modem Disconnect!!!!\n");
ResetEvent(pThis->m_hConnected);
pThis->ChangeMode(MODE_COMMAND);
pThis->HangUp();
if(pThis->m_Thread)
{
if(WAIT_OBJECT_0!=WaitForSingleObject(pThis->m_Thread->m_hThread,10000))
{
TerminateThread(pThis->m_Thread->m_hThread,-11);
}
delete pThis->m_Thread;
pThis->m_Thread=NULL;
}
}
else if(pThis->m_nMode==MODE_CONNECTING)
{
pThis->m_bCD=TRUE;
pThis->StopRead();
pThis->Purge(PURGE_ALL);
pThis->m_Thread = AfxBeginThread(CYsATModem::ReadCommThread,(LPVOID)pThis);
if(!pThis->m_Thread)
{
pThis->ChangeMode(MODE_COMMAND);
pThis->SetLastError(_TEXT("Start read comm thread error"));
return FALSE;
}
pThis->m_Thread->m_bAutoDelete=FALSE;
::SetEvent(pThis->m_hConnected);
pThis->ChangeMode(MODE_DATA);
TRACE("Modem connect!!!!\n");
//无处理
}
else pThis->m_bCD=FALSE;//如果正在拨号的时候断线,可能会出现CD变化?
}
}
TRACE(_T("Quit Detect Thread"));
return 1;
}
/*************************2001.10.30 ycat *********************************************
FUNCTION: UINT CYsATModem::ReadCommThread(LPVOID pParam)
PURPOSE: 线程函数,把串口读入缓冲区的字符,写到自己维护的缓冲区中,并判断断线
PARAMETERS:
pParam:指向CYsATModem类
RETURN VALUE:
COMMENTS: 断线的处理,也许还要改进
**********************************************************************/
UINT CYsATModem::ReadCommThread(LPVOID pParam)
{
//judge if no carrier
char strJudge[]=ECHO_NOCARRIER;
//current judge string position
int iJudge=0;
int iJudgeSize=strlen(strJudge);
TRACE("Start Thread\n");
CYsATModem* pThis=(CYsATModem*)pParam;
DWORD dwInterTimeOut=INFINITE;//读每个字符之间的等待时间
int i;
BYTE chRead;
DWORD dwHaveRead;
while(1)
{
do
{
//read one char
i=pThis->ReadComm(&chRead,1,&dwHaveRead,dwInterTimeOut);
if (1==i)
{
TRACE(_TEXT("##:%02x\n"),chRead,chRead);
pThis->m_pQueue->Put(&chRead);
}
else if(i==-3)
{
TRACE(_TEXT("stop event set!~\n"));
//user hangup
i=TRUE;
goto Exit;
}
else if(i==-1) //非超时
{
TRACE(_TEXT("in Function Read Error code%d\n"),i);
i=FALSE;
goto Exit;
}
}
while(dwHaveRead);
}//while
Exit:
TRACE(_TEXT("End Read comm Thread\n"));
if(!i) TRACE(_TEXT("there are some error occur in thread\n"));
return i;
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CYsATModem::CYsATModem()
{
m_nRingCount=2;
m_bInit=FALSE;
m_bTestMode=FALSE;
ChangeMode(MODE_UNINITIALIZE);
m_pQueue=new CYsQueue<BYTE>(QUEUE_SIZE);
m_Thread=NULL;
//顺序不能变
pstrCmdString[0]=ECHO_OK;
pstrCmdString[1]=ECHO_CONNECT;
pstrCmdString[2]=ECHO_RING;
pstrCmdString[3]=ECHO_NOCARRIER;
pstrCmdString[4]=ECHO_ERROR;
pstrCmdString[5]=ECHO_CONNECT1200;
pstrCmdString[6]=ECHO_NODIALTONE;
pstrCmdString[7]=ECHO_BUSY;
pstrCmdString[8]=ECHO_NOANSWER;
m_hConnected=CreateEvent(NULL,TRUE,FALSE,NULL);
ResetError();
}
CYsATModem::~CYsATModem()
{
#ifndef USER_ANSWER
if(m_nMode==MODE_COMMAND)
SendAT(CMD_ATS0);
#endif
//because m_Thread->m_bAutoDelete set FALSE
if(m_pQueue)delete m_pQueue;
}
/*************************2001.10.30 ycat *********************************************
/*************************2002.04.15 ycat *********************************************
FUNCTION: BOOL CYsATModem::DialUp(LPTSTR strDial,int iTime)
PURPOSE: 用AT命令建立连接
PARAMETERS:
strDial:要拨号的号码
iTime:如果不为0,如果当前状态为连接状态,或线路忙(转成等待方式),等待的时间
RETURN VALUE:
如果操作成功,返回TRUE,如果失败返回FALSE
COMMENTS:
1)发送ATDXXX后,会段时间等待,连接字符串的返回,
如果另一边一拨号成功就发送数据,很可能会导致数据丢失
2)对电话号码的支持有待测试,特别字符
**********************************************************************/
BOOL CYsATModem::DialUp(LPCTSTR strDial)
{
if(m_bTestMode)return TRUE;
if(m_nMode==MODE_UNINITIALIZE||m_nMode==MODE_UNMODEM)
if(m_bInit)
{
if(!InitModem(m_nPort,m_iBaud,2,m_hWnd))
return FALSE;
}
if(m_nMode==MODE_DATA)
{
return TRUE;//have connected
}
if(m_nMode==MODE_CONNECTING)//connecting
{
//wait connect success
if(WAIT_OBJECT_0==WaitForSingleObject(m_hConnected,DIALTIME_START))
return TRUE;//have connected
return FALSE;
}
if(m_nMode!=MODE_COMMAND)//MODE_DIALING MODE_WAITRING
return FALSE;
CHAR strTemp[200];
lstrcpy(strTemp,CMD_ATD);
lstrcat(strTemp,(LPCTSTR)strDial);
SendAT(strTemp);
return DetectConnect();
}
/*************************2001.10.30 ycat *********************************************
FUNCTION: int CYsATModem::DetectConnect()
PURPOSE: 检测连接
PARAMETERS:
RETURN VALUE:
如果操作成功,返回TRUE,如果失败返回FALSE
COMMENTS:
**********************************************************************/
int CYsATModem::DetectConnect()
{
if(m_nMode!=MODE_COMMAND) return FALSE;
ChangeMode(MODE_CONNECTING);
CHAR strTemp[200];
Sleep(3000);
//读字符
DWORD dwRead;
int nErr;
int nRet=FALSE;
Purge(PURGE_ALL);
TRACE("\n Clear \n");
memset(strTemp,0,200);
nErr=this->ReadComm((PBYTE)strTemp,200,&dwRead,DIALTIME_START,DIALTIME_INTER);
TRACE(strTemp);
/* if(nErr!=-2)
{
goto Exit;
}
strTemp[dwRead]='\0';
i=CheckString(strTemp);
//find AT command string
if(i==CODE_CONNECT) nRet=TRUE;
else if(i==CODE_CANNTFIND)//can't fine AT command string
{
TRACE(_TEXT("Unknow string %s\n"),strTemp);
goto Exit;
}
else// if(i==CODE_BUSY||i==CODE_NODIALTONE)
{
goto Exit;
}
if(m_nMode!=MODE_CONNECTING) return m_bCD;//可能中间运行了hangup()*/
//Exit:
if(!m_bCD)
{
SendAT(CMD_AT);//打断连接
Sleep(500);
Purge(PURGE_ALL);
ChangeMode(MODE_COMMAND);
}
else ChangeMode(MODE_DATA);
return m_bCD;
}
/*************************2001.10.30 ycat *********************************************
FUNCTION: BOOL InitModem(UINT nPort,HWND hWnd)
PURPOSE: 生成串口文件句柄,
发送AT命令查看Modem是否正常,
生成一个挂起的收数线程
PARAMETERS:
nPort:串口号,com1为1,com2为2
hWnd:用来接收消息的窗口
RETURN VALUE:
如果操作成功,返回TRUE,如果失败返回FALSE
COMMENTS:
**********************************************************************/
BOOL CYsATModem::InitModem(UINT nPort,UINT uBaud,int iRingCount,HWND hWnd)
{
m_bCD=FALSE;
m_nRingCount=iRingCount;
if(!m_bTestMode)
{
if(m_nMode!=MODE_UNINITIALIZE&&m_nMode!=MODE_UNMODEM) return TRUE;
}
//create comm
if(!Create(nPort))
{
SetLastError(_TEXT("创建通信端口失败"));
//SetLastError(_TEXT("Create Comm error"));
return FALSE;
}
if(!SetComm(uBaud))
{
SetLastError(_TEXT("Set comm error"));
return FALSE;
}
m_hWnd=hWnd;
//clear comm buffer
if(!Purge(PURGE_ALL))
{
return FALSE;
}
m_pQueue->Clear();
if(m_bTestMode) return TRUE;
ChangeMode(MODE_UNMODEM);
int i;
TCHAR buffer[50];
DWORD length=0;
//send ATZ0,复位命令
if(!SendAT(CMD_ATZ0))
{
return FALSE;
}
//if echo don't open then must timeout
i=ReadComm((PBYTE)buffer,11,&length,WAITTIME);
if(i!=1&&i!=-2)
{
SetLastError(_TEXT("读串口失败"));
//SetLastError(_TEXT("Read comm error"));
return FALSE;
}
buffer[length]='\0';
i=CheckString(buffer);
if(i!=CODE_OK)
{
SetLastError(_TEXT("Cann't find OK string"));
return FALSE;
}
//取消回显
if(!SendAT(CMD_ATE))
{
return FALSE;
}
i=ReadComm((PBYTE)buffer,10,&length,WAITTIME);
if(1!=i)
{
SetLastError(_TEXT("读串口失败"));
//SetLastError(_TEXT("Read comm error"));
return FALSE;
}
buffer[length]='\0';
i=CheckString(buffer);
if(i!=CODE_OK)
{
SetLastError(_TEXT("Cann't find OK string"));
return FALSE;
}
#ifndef USER_ANSWER
TCHAR temp[10];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -