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

📄 serial.cpp

📁 Evc 4.0写的
💻 CPP
字号:
// Serial.cpp: implementation of the CSerial class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Serial.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

HANDLE hComm;

//定义向写线程发送的消息常量
const CM_THREADCOMMWRITE = WM_USER+110;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CSerial::CSerial()
{
	hComm = INVALID_HANDLE_VALUE;
	pRecvData=NULL;
	length=0;

    //2007-07-04 18:00
   // CEvent eventDATA(FALSE,TRUE,NULL,NULL);
}

CSerial::~CSerial()
{
	if(hComm != INVALID_HANDLE_VALUE)
		ClosePort();
}

BOOL CSerial::OpenPort(LPTSTR lpszPortName,/*串口号*/
					   UINT baud		,			/*波特率*/
					   UINT parity	,			/*奇偶校验*/
					   UINT databits	,			/*数据位*/
					   UINT stopbits			   /*停止位*/
					   )
{
	if(hComm != INVALID_HANDLE_VALUE)
	{
	return TRUE;
	}
//打开串口
  hComm = CreateFile (lpszPortName, GENERIC_READ | GENERIC_WRITE,0, NULL, OPEN_EXISTING,0, NULL);

  //如果打开端口出错, 返回FALSE

  if ( hComm == INVALID_HANDLE_VALUE ) 
  {
  
    return FALSE;

  }
   //指定端口监测的事件集

  SetCommMask (hComm, EV_RXCHAR);

  //分配设备缓冲区
  
  SetupComm(hComm,512,512);

  //初始化缓冲区中的信息

  PurgeComm(hComm,PURGE_TXCLEAR|PURGE_RXCLEAR);

  //配置串行端口

  if(!InitDCB(	baud,	parity,	databits,	stopbits))
    return FALSE;
    //设置端口超时值

  if(!InitCommTimeouts())
    return FALSE;

  //设置端口上指定信号的状态
  // SETDTR: 发送DTR (data-terminal-ready)信号
  // SETRTS: 发送RTS (request-to-send)信号

  EscapeCommFunction (hComm, SETDTR);
  EscapeCommFunction (hComm, SETRTS);

  //创建一个从串口读取数据的线程

 //创建一个从串口读取数据的线程
  hReadThread = CreateThread (NULL, 0, ReadThreadFunc, this, 0,&dwReadThreadID);
  if (!hReadThread)
  {
	  return FALSE;
  }
  
  return TRUE;
}

DWORD CSerial::WritePort(BYTE *buf,DWORD dwCharToWrite)
{
    BOOL fWriteState;
    DWORD dwHaveBytesWritten=0;
	DWORD dwNumBytesWritten=0;

    //写入数据
	/*
  do
  {
    fWriteState=WriteFile(hComm,buf+dwHaveBytesWritten,
		        (dwCharToWrite-dwHaveBytesWritten)*sizeof(BYTE),
		        &dwNumBytesWritten,
				NULL);
    
    if(!fWriteState)
    {
      dwHaveBytesWritten=dwHaveBytesWritten+dwNumBytesWritten; 
	  if(dwHaveBytesWritten==dwCharToWrite)
	  {
        break;
	  }
	  Sleep(50);
    }
	else
    {
	  LPVOID lpMsgBuf;
       FormatMessage( 
                     FORMAT_MESSAGE_ALLOCATE_BUFFER | 
                     FORMAT_MESSAGE_FROM_SYSTEM | 
                     FORMAT_MESSAGE_IGNORE_INSERTS,
                     NULL,
                     GetLastError(),
                     0, // Default language
                     (LPTSTR) &lpMsgBuf,
                     0,
                     NULL 
                     );
             // Process any inserts in lpMsgBuf.
             // ...
             // Display the string.
        MessageBox( NULL, (LPCTSTR)lpMsgBuf, TEXT("Error"), MB_OK | MB_ICONINFORMATION );
        // Free the buffer.
        LocalFree( lpMsgBuf );

      return FALSE;
	}
  }while(TRUE);
*/

   
    DWORD dwBytesWritten;
    //写入数据

    fWriteState=WriteFile(hComm,buf,dwCharToWrite*sizeof(BYTE),&dwBytesWritten,NULL);

    if(!fWriteState)
    {
           dwBytesWritten=0;
           //AfxMessageBox(TEXT("FGH"));
    }

    return dwBytesWritten;
   //return TRUE;
}

DWORD WINAPI ReadThreadFunc(LPVOID lpvoid)
  {
	CSerial *cSerial =(CSerial*)lpvoid;
    BOOL fReadState;
    DWORD dwCommModemStatus;
    DWORD dwLength;
    COMSTAT ComStat;
    DWORD dwErrorFlags;

//	BYTE* buf=NULL;
    BYTE buf1[256];
    while (hComm != INVALID_HANDLE_VALUE) 
    {
      //等待串口的事件发生
      WaitCommEvent (hComm, &dwCommModemStatus, 0);
      if (dwCommModemStatus & EV_RXCHAR) 
      {
        ClearCommError(hComm,&dwErrorFlags,&ComStat);
        //cbInQue返回在串行驱动程序输入队列中的字符数
        dwLength=ComStat.cbInQue;

        if(dwLength>0&&dwLength<256)
        {
	      //buf=new BYTE[dwLength];
          //从串口读取数据          
          fReadState=ReadFile(hComm,buf1,dwLength,&dwLength,NULL);
		  if(!fReadState)
          {
            //不能从串口读取数据
            MessageBox(NULL,TEXT("Error in read from serial port"),TEXT("Read Error"),MB_OK);
          }
          else
          {	
			  cSerial->pRecvData=buf1;
			  cSerial->length=dwLength;
			  cSerial->eventDATA.SetEvent();           
          }
         //delete[] buf;
        } 
      }
      GetCommModemStatus (hComm, &dwCommModemStatus);
	  //如果收到读线程退出信号,则退出线程
		if (WaitForSingleObject(cSerial->hReadCloseEvent,500) == WAIT_OBJECT_0)
		{
		//	delete[] buf;
			break;
		}
    }
    return 0;
}
 
BOOL CSerial::ClosePort(void)
  {
    if (hComm != INVALID_HANDLE_VALUE)
    {

      //结束线程中WaitCommEvent的等待
      SetCommMask(hComm,0);
       //阻塞至线程停止
      if(hReadThread)
      {
        TerminateThread(hReadThread,0);
        CloseHandle(hReadThread);
      }

      //清除端口上指定信号的状态
      EscapeCommFunction(hComm,CLRDTR);
      EscapeCommFunction(hComm,CLRRTS);
      //清除驱动程序内部的发送和接收队列
      PurgeComm(hComm,PURGE_TXCLEAR|PURGE_RXCLEAR);

      //关闭串口
      CloseHandle (hComm);
      hComm = INVALID_HANDLE_VALUE;

      return TRUE;
    }
    else
    {
      return TRUE;
    }
}

BOOL CSerial::InitDCB(UINT baud,UINT parity,UINT databits,UINT stopbits)
  {
    DCB PortDCB;
    DWORD dwError;
     
    PortDCB.DCBlength = sizeof (DCB); 

    //得到端口的默认设置信息
    if(!GetCommState (hComm, &PortDCB))
	{
		MessageBox (NULL, TEXT("GetCommState error"),TEXT("Error"), MB_OK);;
		dwError = GetLastError ();
		return FALSE;
	}
    //改变DCB结构设置
    PortDCB.BaudRate = baud; //波特率 
    PortDCB.fBinary = TRUE; //Win32不支持非二进制串行传输模式,必须为TRUE 
    PortDCB.fParity = TRUE; //启用奇偶校验
	
    //PortDCB.fOutxCtsFlow = TRUE; //串行端口的输出由CTS线控制
    PortDCB.fOutxCtsFlow = FALSE; //串行端口的输出由CTS线控制
	
	PortDCB.fOutxDsrFlow = FALSE; //关闭串行端口的DSR流控制 
    
	//PortDCB.fDtrControl = DTR_CONTROL_ENABLE; //启用DTR线
    PortDCB.fDtrControl = FALSE; //启用DTR线
	
	PortDCB.fDsrSensitivity = FALSE; //如果设为TRUE将忽略任何输入的字节,除非DSR线被启用 
    
	//PortDCB.fTXContinueOnXoff = TRUE; //当为TRUE时,如果接收缓冲区已满且驱动程序已传送XOFF字符,将使驱动程序停止传输字符

    PortDCB.fTXContinueOnXoff = FALSE;

    PortDCB.fOutX = FALSE; //设为TRUE指定XON/XOFF控制被用于控制串行输出 
    PortDCB.fInX = FALSE; //设为TRUE指定XON/XOFF控制被用于控制串行输入 
    PortDCB.fErrorChar = FALSE; //WINCE串行驱动程序的默认执行将忽略这个字段 
    PortDCB.fNull = FALSE; //设为TRUE将使串行驱动程序忽略收到的空字节 
    
	//PortDCB.fRtsControl = RTS_CONTROL_ENABLE; //启用RTS线 
    PortDCB.fRtsControl = FALSE; //启用RTS线
	
	PortDCB.fAbortOnError = FALSE; //WINCE串行驱动程序的默认执行将忽略这个字段
    PortDCB.ByteSize = databits; //每字节的位数 
    PortDCB.Parity = parity; //无奇偶校验 
    PortDCB.StopBits = stopbits; //每字节一位停止位 

    //根据DCB结构配置端口 

    if (!SetCommState (hComm, &PortDCB))
    {
        return FALSE;
    }
    return TRUE;
}

BOOL CSerial::InitCommTimeouts()
  {
    COMMTIMEOUTS CommTimeouts;
  
    //得到超时参数
    if(!GetCommTimeouts (hComm, &CommTimeouts))
			{
				return FALSE;
			}

   //改变COMMTIMEOUTS结构设置

    CommTimeouts.ReadIntervalTimeout = MAXDWORD; 
    CommTimeouts.ReadTotalTimeoutMultiplier = 0; 
    CommTimeouts.ReadTotalTimeoutConstant = 0; 
    CommTimeouts.WriteTotalTimeoutMultiplier = 10; 
    CommTimeouts.WriteTotalTimeoutConstant = 10000; 

    //设置端口超时值 
    if (!SetCommTimeouts (hComm, &CommTimeouts))
    {
      //不能设置超时值
      //MessageBox (NULL, TEXT("SetCommTimeouts error"), TEXT("Error"), MB_OK);
      //dwError = GetLastError ();
      return FALSE;
    }

    return TRUE;
}  

//关闭读线程
void CSerial::CloseReadThread()
{
	SetEvent(hReadCloseEvent);
	//设置所有事件无效无效
	SetCommMask(hComm, 0);
	//清空所有将要读的数据
    PurgeComm( hComm,  PURGE_RXCLEAR );
    //等待10秒,如果读线程没有退出,则强制退出
    if (WaitForSingleObject(hReadThread,10000) == WAIT_TIMEOUT)
	{
		TerminateThread(hReadThread,0);
	}
	hReadThread = NULL;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -