⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ysatmodem.cpp

📁 VisualC++通信编程工程实例精解 Chapter 2 Example 1 MSCOMM控件编程实例 Example 2 基于Windows API的虚拟终端实现 Example 3
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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 + -