/*----------------------------------------- * Copyright (c) 2008 Eric Wong * ����������߲ο������������κ���ҵ��Ϊ * * �ļ����ƣ� CESeries.cpp * �ļ���ʶ�� * ժҪ�����ڷ�װWINCE ����ͨѶ * * ��ǰ�汾�� 1.0 * ���ߣ� ���� Eric Wong * ������ڣ� 2008��1��17�� * * ȡ���汾�� * ԭ���ߣ� * ������ڣ� ----------------------------------------*/ #include "StdAfx.h" #include "MySeries.h" //���캯�� CMyCESeries::CMyCESeries(UINT portNo, UINT baud, UINT parity, UINT databits, UINT stopbits) :m_portNo(portNo) ,m_baud(baud) ,m_parity(parity) ,m_databits(databits) ,m_stopbits(stopbits) ,m_hReadThread(NULL) ,m_hReadCloseEvent(NULL) { //m_portNo = portNo; //���ں�ʹ�ô���1 CANģ���GPS���� //m_baud = baud; //������ //m_parity = parity; //��żУ��,0-None,1-Odd,2-Even //m_databits = databits; //����λ //m_stopbits = stopbits; //ֹͣλ 0-ֹͣλ1��1-ֹͣλ1.5��2-ֹͣλ2 //��ʼ���ڲ����� m_hComm = INVALID_HANDLE_VALUE; m_OnSeriesRead = NULL; m_hReadCloseEvent = NULL; m_bOpened = false; bCanComRead = true; m_bSyncOrAsync = true;//ʹ��ͬ����ʽ�����첽��ʽ���ص���ʽ����Ĭ��ֵΪtrue���첽��ʽ memset(&m_olWrite,0,sizeof(OVERLAPPED)); } //�������� CMyCESeries::~CMyCESeries() { if (m_bOpened) ClosePort(); } //���ڶ��̺߳��� DWORD CMyCESeries::ReadThreadFunc(LPVOID lparam) { CMyCESeries *ceSeries = (CMyCESeries*)lparam; BYTE * readBuf = NULL;//��ȡ���ֽ� DWORD actualReadLen=0;//ʵ�ʶ�ȡ���ֽ��� DWORD willReadLen; DWORD dwReadErrors; COMSTAT cmState; //�첽��ʽ�½�ʹ����Щ���� //LPOVERLAPPED OVERLAPPED olWait; //memset(&olWaite,0,sizeof(olWaite)); memset(&olWait,0,sizeof(OVERLAPPED)); olWait.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); //ͬ����ʽ����ʹ�øñ��� DWORD evtMask; // ��ջ��壬����鴮���Ƿ�� ASSERT(ceSeries->m_hComm !=INVALID_HANDLE_VALUE); //��մ��� PurgeComm(ceSeries->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR ); SetCommMask (ceSeries->m_hComm, EV_RXCHAR | EV_CTS | EV_DSR );//����3�������¼� //���Բ鿴������������Щ�¼� //DWORD dwMask1; //GetCommMask(ceSeries->m_hComm,&dwMask1); OVERLAPPED olRead; memset(&olRead,0,sizeof(OVERLAPPED)); olRead.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL); while(TRUE) { if(ceSeries->m_bSyncOrAsync)//�첽��ʽ�� { DWORD dwCommStatus = 0; BOOL bWait1=0; bWait1= WaitCommEvent(ceSeries->m_hComm,&dwCommStatus,&olWait);//����������õ�3���¼����κ�һ�������ˣ�������Ҫ�Ǽ����ջ�������������ʱ //while(!bWait1);//�ȴ�WaitCommEvent����ΪTRUE��������ִ�У����ַ�ʽ�в�ͨ���ص���ʽ���첽��ʽ��ʱ���ú���һֱ����Ϊfalse�� DWORD dwByte; //norains:It is only suitable for the GetOverlappedResult(),not undefined here. if(GetOverlappedResult(ceSeries->m_hComm,&olWait,&dwByte,TRUE) == FALSE)//��������£���һֱ�ڸú���������ֱ��olWaite�е�hEvent�¼������� //��ú����������ˣ����ҷ���ֵΪTrue { if(GetLastError() != ERROR_IO_PENDING) { return 0x30; } //Clear the error flag DWORD dwErrors; COMSTAT comStat; memset(&comStat,0,sizeof(comStat)); ClearCommError(ceSeries->m_hComm,&dwErrors,&comStat); return 0x35; } //��ʾ�����յ��ַ� if (dwCommStatus & EV_RXCHAR) { ClearCommError(ceSeries->m_hComm,&dwReadErrors,&cmState); willReadLen = cmState.cbInQue ; if (willReadLen <= 0) { continue; } //�첽��ʽ //�����ڴ� readBuf = new BYTE[willReadLen+1]; ZeroMemory(readBuf,willReadLen+1); //��ȡ�������� //�첽��ʽ if(ReadFile(ceSeries->m_hComm, readBuf, willReadLen, &actualReadLen,&olRead)==FALSE)//�첽�������ڶ�ȡ����Ժ�TRUE { //�ͷ��ڴ� delete[] readBuf; readBuf = NULL; if(GetLastError() != ERROR_IO_PENDING) return 0x40; if(GetOverlappedResult(ceSeries->m_hComm,&olRead,&actualReadLen,TRUE) == FALSE) return 0x45; if(actualReadLen == 0) return 0x50; } else//�������е����ݶ�ȡ��ʱ { //�����ȡ�����ݴ���0�� if (actualReadLen>0) { //������ȡ�ص����� if (ceSeries->m_OnSeriesRead) { ceSeries->m_OnSeriesRead(ceSeries->m_pOwner,readBuf,actualReadLen); } } //�ͷ��ڴ� delete[] readBuf; readBuf = NULL; } } } else//ͬ����ʽ�� { if (WaitCommEvent(ceSeries->m_hComm,&evtMask,0)) { SetCommMask (ceSeries->m_hComm, EV_RXCHAR | EV_CTS | EV_DSR ); //��ʾ�����յ��ַ� if (evtMask & EV_RXCHAR) { ClearCommError(ceSeries->m_hComm,&dwReadErrors,&cmState); willReadLen = cmState.cbInQue ; if (willReadLen <= 0) { continue; } //�����ڴ� readBuf = new BYTE[willReadLen]; ZeroMemory(readBuf,willReadLen); //��ȡ�������� ReadFile(ceSeries->m_hComm, readBuf, willReadLen, &actualReadLen,0); //�����ȡ�����ݴ���0�� if (actualReadLen>0) { //������ȡ�ص����� if (ceSeries->m_OnSeriesRead) { ceSeries->m_OnSeriesRead(ceSeries->m_pOwner,readBuf,actualReadLen); } } //�ͷ��ڴ� delete[] readBuf; readBuf = NULL; } } } //ÿ�ζ��߳�ִ�е��ô�ʱ������ȴ������߽�������10milseconds�����Ƿ�رմ����¼��Ƿ��� //��ClosePort()�������е�����CloseHandle(m_hReadCloseEvent);��ʹ�ø��¼����źţ��Ҿ��ÿ�����SetEvent(m_hReadCloseEvent)���棬�ú���Ҳ��ʹ���¼����ź� //��ִ����ClosePotr����������˵�����¼��Ѿ������ˣ����ڶ��̺߳�����ִ�е��˴�ʱ�� //��������while(true),�Ӷ��˳����̣߳� if (WaitForSingleObject(ceSeries->m_hReadCloseEvent, 10) == WAIT_OBJECT_0)// { TRACE("�߳�ReadThreadFunc�˳�\n"); break; } } //�ر��¼� CloseHandle( olRead.hEvent ); CloseHandle( olWait.hEvent ); //�ͷ��ڴ� if(readBuf) { delete[] readBuf; readBuf = NULL; } ExitThread(0); return 0; } //�رն��߳� void CMyCESeries::CloseReadThread() { if( m_hComm != INVALID_HANDLE_VALUE ) { // SetEvent(m_hReadCloseEvent); // CloseHandle(m_hReadCloseEvent); //WaitForSingleObject(m_hReadThread, 1000); // DWORD exitCode; // BOOL ret = GetExitCodeThread(m_hReadThread, &exitCode); //if(ret && exitCode != 0) { TRACE("ǿ�йر�ReadThreadFunc�߳�\n"); TerminateThread(m_hReadThread,0); } // CloseHandle(m_hReadThread); m_hReadThread = NULL; } /* if( m_hComm != INVALID_HANDLE_VALUE ) { SetEvent(m_hReadCloseEvent); //���������¼���Ч SetCommMask(m_hComm, 0); //������н�Ҫ�������� PurgeComm( m_hComm, PURGE_RXCLEAR ); //�ȴ�4�룬������߳�û���˳�����ǿ���˳� if (WaitForSingleObject(m_hReadThread,4000) == WAIT_TIMEOUT) { TerminateThread(m_hReadThread,0); } m_hReadThread = NULL; } //*/ } //�������ܣ����� //��ڲ�����pPortOwner :ʹ�ô˴�����Ĵ����� // portNo :���ں� // baud :������ // parity :��żУ�� // databits :����λ // stopbits :ֹͣλ //���ڲ�����(��) //����ֵ��TRUE:�ɹ�����;FALSE:����ʧ�� BOOL CMyCESeries::OpenPort(void * pOwner, UINT portNo , //���ں� UINT baud , //������ UINT parity , //��żУ�� UINT databits , //����λ UINT stopbits , //ֹͣλ bool isASync ) { m_portNo = portNo; //���ں�ʹ�ô���1 CANģ���GPS���� m_baud = baud; //������ m_parity = parity; //��żУ��,0-None,1-Odd,2-Even m_databits = databits; //����λ m_stopbits = stopbits; //ֹͣλ 0-ֹͣλ1��1-ֹͣλ1.5��2-ֹͣλ2 m_bSyncOrAsync = isASync; DCB commParam; TCHAR szPort[15]; ASSERT(pOwner!=NULL); m_pOwner = pOwner; // �Ѿ��Ļ���ֱ�ӷ��� if (m_hComm != INVALID_HANDLE_VALUE) { return TRUE; } //���ô����� //wsprintf(szPort, _T("\.\COM%d:"), portNo); wsprintf(szPort, _T("\\\\.\\COM%d"), portNo); //sprintf(szPort, "\\\\.\\COM%d", portNo); //���� if(m_bSyncOrAsync)//m_bSyncOrAsyncֵΪ0������ͬ����ʽ�������������첽��ʽ������ { m_hComm = CreateFile( //���첽��ʽ���� szPort, GENERIC_READ | GENERIC_WRITE, //��������д 0, //��ռ��ʽ������ģʽ�� NULL, OPEN_EXISTING, //�����Ǵ�����������ʽ�� FILE_FLAG_OVERLAPPED, 0 ); } else { m_hComm = CreateFile( //��ͬ����ʽ���� szPort, GENERIC_READ | GENERIC_WRITE, //��������д 0, //��ռ��ʽ������ģʽ�� NULL, OPEN_EXISTING, //�����Ǵ�����������ʽ�� 0, NULL ); } if (m_hComm == INVALID_HANDLE_VALUE) { // ��Ч���,���ء� TRACE(_T("CreateFile ������Ч���\n")); DWORD ErrNo = GetLastError(); return FALSE; } // �õ����ڵĵ�ǰ���Բ������ĺ����������ô��ڡ� if (!GetCommState(m_hComm,&commParam)) { //�رմ��� CloseHandle (m_hComm); m_hComm = INVALID_HANDLE_VALUE; return FALSE; } if(m_bSyncOrAsync)//������첽��ʽ��ÿ����һ�����ڶ����ҳɹ���һ�����ڶ���ʱ�Ŵ���һ����Ӧ�ķ����¼� { //�첽д���� m_olWrite.hEvent = CreateEvent(NULL,TRUE,FALSE,_T("WriteData")); // DWORD dwError = GetLastError(); // if(dwError !=0) // { // TRACE("�첽��ʽ�������ڶ���ʱ��Ϊ�ô��ڶ�����������д�����¼�����ʧ��"); // return FALSE; // } } //���ô��ڲ��� commParam.BaudRate = baud; // ���ò����� commParam.fBinary = TRUE; // ���ö�����ģʽ���˴���������TRUE commParam.fParity = TRUE; // ֧����żУ�� commParam.ByteSize = databits; // ����λ,��Χ:4-8 commParam.Parity = parity; // У��ģʽ commParam.StopBits = stopbits; // ֹͣλ commParam.fOutxCtsFlow = FALSE; // No CTS output flow control commParam.fOutxDsrFlow = FALSE; // No DSR output flow control commParam.fDtrControl = DTR_CONTROL_ENABLE; // DTR flow control type commParam.fDsrSensitivity = FALSE; // DSR sensitivity commParam.fTXContinueOnXoff = TRUE; // XOFF continues Tx commParam.fOutX = FALSE; // No XON/XOFF out flow control commParam.fInX = FALSE; // No XON/XOFF in flow control commParam.fErrorChar = FALSE; // Disable error replacement commParam.fNull = FALSE; // Disable null stripping commParam.fRtsControl = RTS_CONTROL_ENABLE; // RTS flow control commParam.fAbortOnError = FALSE; // �����ڷ�����������ֹ���ڶ�д //���ô��ڲ��� if (!SetCommState(m_hComm, &commParam)) { TRACE(_T("SetCommState error\n")); DWORD dwError = GetLastError(); //�رմ��� CloseHandle (m_hComm); m_hComm = INVALID_HANDLE_VALUE; return FALSE; } //���ô��ڶ�дʱ�� COMMTIMEOUTS CommTimeOuts; GetCommTimeouts (m_hComm, &CommTimeOuts); CommTimeOuts.ReadIntervalTimeout = MAXDWORD; CommTimeOuts.ReadTotalTimeoutMultiplier = 0; CommTimeOuts.ReadTotalTimeoutConstant = 0; CommTimeOuts.WriteTotalTimeoutMultiplier = 10; CommTimeOuts.WriteTotalTimeoutConstant = 1000; if(!SetCommTimeouts( m_hComm, &CommTimeOuts )) { TRACE( _T("SetCommTimeouts ���ش���\n") ); //�رմ��� CloseHandle (m_hComm); m_hComm = INVALID_HANDLE_VALUE; return FALSE; } //ָ���˿ڼ����¼��� SetCommMask (m_hComm, EV_RXCHAR); //���䴮���豸������ SetupComm(m_hComm,1024,1024); //SetupComm(m_hComm,512,512); //��ʼ���������е���Ϣ PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR); CString strEvent; strEvent.Format(_T("Com_ReadCloseEvent%d"),portNo); m_hReadCloseEvent = CreateEvent(NULL,TRUE,FALSE,strEvent); //�������ڶ����ݼ����߳� if( bCanComRead == true ) { m_hReadThread = CreateThread(NULL,0,ReadThreadFunc,this,0,&m_dwReadThreadID);//ͨ��thisָ�뽫���ڶ��ݸ����̺߳���ReadThreadFunc���β� } TRACE(_T("����%d�ɹ�\n"), portNo); m_bOpened = true; return TRUE; } //�������ܣ��رմ��� //��ڲ�����(��) //���ڲ�����(��) //����ֵ�� (��) void CMyCESeries::ClosePort() { //��ʾ���ڻ�û�д� if (m_hComm == INVALID_HANDLE_VALUE) return ; //�ر��¼� //TRACE("�رմ��ڶ��¼�\n"); Sleep(100); //�رն��߳� CloseReadThread(); //�رմ��� TRACE("CMyCESeries�رմ���%d���\n", m_portNo); CloseHandle (m_hComm); //�ر��¼� CloseHandle(m_olWrite.hEvent); m_hComm = INVALID_HANDLE_VALUE; m_bOpened = false; } //�������ܣ�������д������ //��ڲ�����buf ����д�����ݻ����� // bufLen : ��д�뻺�������� //���ڲ�����(��) //����ֵ��TRUE:���óɹ�;FALSE:����ʧ�� BOOL CMyCESeries::WriteSyncPort(const BYTE*buf , DWORD bufLen) { if( false == m_bSyncOrAsync )//ͬ����ʽ { DWORD dwNumBytesWritten; DWORD dwHaveNumWritten =0 ; //�Ѿ�д����� int iInc = 0; //���3��д�벻�ɹ�������FALSE ASSERT(m_hComm != INVALID_HANDLE_VALUE); do { if (WriteFile (m_hComm, //���ھ�� buf+dwHaveNumWritten, //��д���ݻ����� bufLen - dwHaveNumWritten, //��д���ݻ�������С &dwNumBytesWritten, //����ִ�гɹ�����ʵ����д�ĸ��� NULL)) //�˴���������NULL { dwHaveNumWritten = dwHaveNumWritten + dwNumBytesWritten; //д����� if (dwHaveNumWritten == bufLen) { break; } iInc++; if (iInc >= 3) { TRACE("CMyCESeries::WriteSyncPort ͬ��д����ʧ��3��\n"); return FALSE; } Sleep(10); } else { TRACE("CMyCESeries::WriteSyncPort ͬ��д����ʧ��\n"); return FALSE; } }while (TRUE); return TRUE; } else//�첽��ʽ { DWORD dwNumBytesWritten; DWORD dwHaveNumWritten =0 ; //�Ѿ�д����� // OVERLAPPED olWrite; // memset(&olWrite,0,sizeof(OVERLAPPED)); // m_olWrite.hEvent = CreateEvent(NULL,TRUE,FALSE,_T("WriteData")); //�첽д���� if (WriteFile (m_hComm, //���ھ�� buf+dwHaveNumWritten, //��д���ݻ����� bufLen - dwHaveNumWritten, //��д���ݻ�������С &dwNumBytesWritten, //����ִ�гɹ�����ʵ����д�ĸ��� &m_olWrite) == FALSE)//�����DZ�ʾд��ʧ�ܣ�����û�н���������д�뵽�������У���ֻ��д���˲��ֶ��� { if(GetLastError() != ERROR_IO_PENDING) { TRACE("CMyCESeries::WriteSyncPort �첽д����0x20\n"); return 0x20; } if(GetOverlappedResult(m_hComm,&m_olWrite,&dwNumBytesWritten,TRUE) == FALSE)//���ォһֱ������ֱ������������д�뵽������Ϊֹ { TRACE("CMyCESeries::WriteSyncPort �첽д����0x25\n"); return 0x25; } } //else//д��ɹ� { dwHaveNumWritten = dwHaveNumWritten + dwNumBytesWritten; //д����� if (dwHaveNumWritten == bufLen) return TRUE; else { TRACE("CMyCESeries::WriteSyncPort �첽д����%dʧ��\n", m_portNo); return FALSE; } } } } //�������ܣ����ô��ڶ�ȡ��д�볬ʱ //��ڲ�����CommTimeOuts : ָ��COMMTIMEOUTS�ṹ //���ڲ�����(��) //����ֵ��TRUE:���óɹ�;FALSE:����ʧ�� BOOL CMyCESeries::SetSeriesTimeouts(COMMTIMEOUTS CommTimeOuts) { ASSERT(m_hComm != INVALID_HANDLE_VALUE); return SetCommTimeouts(m_hComm,&CommTimeOuts); } //�õ������Ƿ�� BOOL CMyCESeries::GetComOpened() { return m_bOpened; }