请教有关串口编程方面的知识点1。creatafile() 创建文件句柄 2。writefile() 发送数据(命令)3。readfile() 读取数据 4。closehandle() 关闭句柄请问:请站长,斑主,高手解释上面的各个函数的具体做了什么事情。他的参数的具体含义是什么??
最好能结合操作系统和串口硬件结构讲讲这几个函数怎么联系在一起工作的谢谢!

解决方案 »

  1.   

    看看msdn吧,4个函数实在是一言难尽呀^_^
    要不你也可以用MSComm控件
      

  2.   

    你所说的是API方式,其实没有你说的那么简单,要说有很多道理要讲,
    给你个网站自己去看看吧
    http://www.gjwtech.com/
    里面对串口编程讲的比较全面
      

  3.   

    CreateFile 打开串口
    WriteFile 发送
    ReadFile 读取
    CloseFile 关闭串口
    因为COM1、COM2、...是特殊的文件名
    我可以贴一点点代码过来,不是很完全的
    CLSSerialPort::CLSSerialPort()
    {
    m_hComm = NULL; 
    m_hMsgWnd = NULL;

    // 初始化 OVERLAPPED 结构
    m_ov.Offset = 0; 
    m_ov.OffsetHigh = 0; 

    // 事件句柄 
    m_ov.hEvent = NULL; 
    m_hWriteEvent = NULL; 
    m_hShutdownEvent = NULL; 

    m_bThreadAlive = FALSE; 
    m_dwCommEvents = EV_RXCHAR | EV_CTS;
    m_dwTimeOut = 0;
    m_pSpecBuf = NULL;
    }CLSSerialPort::~CLSSerialPort()
    {
    ClosePort(); if (m_ov.hEvent != NULL) // 读事件
    ResetEvent(m_ov.hEvent); 
    if (m_hWriteEvent != NULL) // 写事件
    ResetEvent(m_hWriteEvent); 
    if (m_hShutdownEvent != NULL) // 关闭事件
    ResetEvent(m_hShutdownEvent); 

    m_hEventArray[0] = NULL; // 高优先级
    m_hEventArray[1] = NULL; 
    m_hEventArray[2] = NULL; 
    }#define LeaveCriticalSectionAndReturnFalse \
    { \
    LeaveCriticalSection(&m_csCommunicationSync); \
    return FALSE; \
    }

    BOOL CLSSerialPort::InitPort(UINT uPort, UINT uBaudRate, char chParity, UINT uDataBits, UINT uStopBits)
    {
    BOOL bResult = FALSE; 
    char szPort[50]; 
    char szBaud[50]; 

    m_pSpecBuf = NULL;
    m_uPort = uPort;  ClosePort();

    InitializeCriticalSection(&m_csCommunicationSync);  // 初始化临界区
    EnterCriticalSection(&m_csCommunicationSync);  // 进入临界区

    // 如果串口已经打开则关闭
    if (m_hComm != NULL) 

    CloseHandle(m_hComm); 
    m_hComm = NULL; 


    sprintf(szPort, "COM%d", uPort);  // 准备口串口字符串
    sprintf(szBaud, "Baud=%d Parity=%c Data=%d Stop=%d", uBaudRate, chParity, uDataBits, uStopBits); 

    m_hComm = CreateFile(szPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); // template must be 0 for comm devices 

    if (m_hComm == INVALID_HANDLE_VALUE)
    return FALSE; 

    // 设置超时 
    m_CommTimeouts.ReadIntervalTimeout = 1000; 
    m_CommTimeouts.ReadTotalTimeoutMultiplier = 1000; 
    m_CommTimeouts.ReadTotalTimeoutConstant = 1000; 
    m_CommTimeouts.WriteTotalTimeoutMultiplier = 1000; 
    m_CommTimeouts.WriteTotalTimeoutConstant = 1000; 

    // 配置串口
    if(!SetCommTimeouts(m_hComm, &m_CommTimeouts))
    LeaveCriticalSectionAndReturnFalse;
    if(!SetCommMask(m_hComm, m_dwCommEvents)) 
    LeaveCriticalSectionAndReturnFalse;
    if(!GetCommState(m_hComm, &m_dcb)) 
    LeaveCriticalSectionAndReturnFalse;
    m_dcb.fRtsControl = RTS_CONTROL_ENABLE; // 设置 RTS 位高 
    if(!BuildCommDCB(szBaud, &m_dcb)) 
    LeaveCriticalSectionAndReturnFalse;
    if (!SetCommState(m_hComm, &m_dcb)) //异常操作
    LeaveCriticalSectionAndReturnFalse;

    PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); //刷新端口
    LeaveCriticalSection(&m_csCommunicationSync); //离开临界区

    return StartSerialPortThread();
    }DWORD __stdcall CLSSerialPort::_SerialPortThread(LPVOID pParam)
    {
    DWORD BytesTransfered = 0; 
    DWORD Event = 0; 
    DWORD CommEvent = 0; 
    DWORD dwError = 0; 
    COMSTAT comStat; 

    CLSSerialPort *port = (CLSSerialPort*)pParam; 

    port->m_bThreadAlive = TRUE; // 设置线程运行标志

    if(port->m_hComm) // 判断端口是否已经打开
    PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); //清除串口缓冲区

    while(1)

    if (!WaitCommEvent(port->m_hComm, &Event, &port->m_ov))  // 如果 WaitCommEvent() 返回 FALSE,处理错误

    switch (dwError = GetLastError()) 

    case ERROR_IO_PENDING:  // 端口上没有数据可读取,这是一个常见的返回值。
    break; 
    case 87:  // Windows NT下,某些情况下可能返回这个值,我没有研究过是为什么,这里没有做任何处理
    break; 
    default:  // 其它错误代码表明出现严重错误,应该处理该错误
    break; 


    else // 缓冲区中有数据

    ClearCommError(port->m_hComm, &dwError, &comStat); 

    if (comStat.cbInQue == 0) 
    continue; 


    Event = WaitForMultipleObjects(3, port->m_hEventArray, false, INFINITE);  // 阻塞线程,等待事件发生

    switch (Event) 

    case 0:  // 关闭事件,这个事件应该有最高优先级
    port->m_bThreadAlive = FALSE; 
    ExitThread(100); //退出线程,break实际上是不需要的,只是为了使结构更清析
    break; 
    case 1: // 读事件
    GetCommMask(port->m_hComm, &CommEvent); 
    if(port->m_hMsgWnd)
    {
    if (CommEvent & EV_CTS)
    ::SendMessage(port->m_hMsgWnd, WM_COMM_CTS_DETECTED, (WPARAM)0, (LPARAM)port->m_uPort);
    if (CommEvent & EV_RXFLAG)
    ::SendMessage(port->m_hMsgWnd, WM_COMM_RXFLAG_DETECTED, (WPARAM)0, (LPARAM)port->m_uPort);
    if (CommEvent & EV_BREAK)
    ::SendMessage(port->m_hMsgWnd, WM_COMM_BREAK_DETECTED, (WPARAM)0, (LPARAM)port->m_uPort);
    if (CommEvent & EV_ERR)
    ::SendMessage(port->m_hMsgWnd, WM_COMM_ERR_DETECTED, (WPARAM)0, (LPARAM)port->m_uPort);
    if (CommEvent & EV_RING)
    ::SendMessage(port->m_hMsgWnd, WM_COMM_RING_DETECTED, (WPARAM)0, (LPARAM)port->m_uPort);
    if (CommEvent & EV_DSR)
    ::SendMessage(port->m_hMsgWnd, WM_COMM_DSR_DETECTED, (WPARAM)0, (LPARAM)port->m_uPort);
    if (CommEvent & EV_RLSD)
    ::SendMessage(port->m_hMsgWnd, WM_COMM_RLSD_DETECTED, (WPARAM)0, (LPARAM)port->m_uPort);
    if (CommEvent & EV_TXEMPTY)
    ::SendMessage(port->m_hMsgWnd, WM_COMM_TXEMPTY_DETECTED, (WPARAM)0, (LPARAM)port->m_uPort);
    }
    if (CommEvent & EV_RXCHAR)
    ReceiveIn(port, comStat); //从端口接收字符事件
    break; 
    case 2: // 写事件
    SendOut(port); //向端口写字符事件
    break; 
    }
    }
    return 0; 
    }
      

  4.   

    BOOL CLSSerialPort::StartSerialPortThread()
    {
    DWORD lpThreadId;  if(m_bThreadAlive)
    return TRUE; // 创建事件
    if (m_ov.hEvent != NULL) // 读事件
    ResetEvent(m_ov.hEvent); 
    m_ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 
    if (m_hWriteEvent != NULL) // 写事件
    ResetEvent(m_hWriteEvent); 
    m_hWriteEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 
    if (m_hShutdownEvent != NULL) // 关闭事件
    ResetEvent(m_hShutdownEvent); 
    m_hShutdownEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 

    // 初始化事件对象
    m_hEventArray[0] = m_hShutdownEvent; // 高优先级
    m_hEventArray[1] = m_ov.hEvent; 
    m_hEventArray[2] = m_hWriteEvent; 

    m_hThread = CreateThread(NULL, 0, _SerialPortThread, this, 0, &lpThreadId);  if(m_hThread==NULL) 
    return FALSE; return TRUE; 
    }void CLSSerialPort::StopSerialPortThread()
    {
    while(m_bThreadAlive)
    SetEvent(m_hShutdownEvent); // 通过设置终止事件来结束线程
    m_bThreadAlive = FALSE;
    }void CLSSerialPort::ReceiveIn(CLSSerialPort *port, COMSTAT comstat)
    {
    BOOL bRead = true; 
    BOOL bResult = true; 
    DWORD dwError = 0; 
    DWORD BytesRead = 0; 
    unsigned char RXBuff; 

    ResetEvent(port->m_ov.hEvent);
    for (;;) 

    EnterCriticalSection(&port->m_csCommunicationSync); 
    bResult = ClearCommError(port->m_hComm, &dwError, &comstat);  // 更新 COMSTAT 结构体并清除所有其它错误
    LeaveCriticalSection(&port->m_csCommunicationSync); 

    if (comstat.cbInQue == 0) //读取完所有字节后跳出循环
    break; 

    EnterCriticalSection(&port->m_csCommunicationSync); //进入临界区

    if (bRead) 

    bResult = ReadFile(port->m_hComm, &RXBuff, 1, &BytesRead, &port->m_ov); 
    // 处理错误代码
    if (!bResult) 

    switch (dwError = GetLastError()) 

    case ERROR_IO_PENDING: 
    // 异步I/O仍在处理,继续执行 GetOverlappedResults(); 
    bRead = false; 
    break; 


    else 
    bRead = true;  // ReadFile成功,没有必要调用 GetOverlappedResults() 
    }

    if (!bRead) 

    bRead = true; 
    bResult = GetOverlappedResult(port->m_hComm, &port->m_ov, &BytesRead, true);
    }

    LeaveCriticalSection(&port->m_csCommunicationSync);  if(port->m_hMsgWnd)
    ::SendMessage(port->m_hMsgWnd, WM_COMM_RXCHAR, (WPARAM)RXBuff, (LPARAM) port->m_uPort);
    if(port->m_pSpecBuf)
    {
    port->m_uExactSize++;
    *(port->m_pSpecBuf) = (unsigned char)RXBuff;
    port->m_pSpecBuf++;
    }
    }
    }void CLSSerialPort::SendOut(CLSSerialPort *port)
    {
    BOOL bWrite = TRUE; 
    BOOL bResult = TRUE; 

    DWORD BytesSent = 0; 

    ResetEvent(port->m_hWriteEvent); 
    EnterCriticalSection(&port->m_csCommunicationSync); //进入临界区

    if (bWrite) 

    // 初始化变量 
    port->m_ov.Offset = 0; 
    port->m_ov.OffsetHigh = 0; 

    PurgeComm(port->m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT); //清除缓冲区

    if (!WriteFile(port->m_hComm, port->m_pSpecBuf, port->m_uBufSize, &BytesSent, &port->m_ov)) 

    DWORD dwError = GetLastError(); 
    switch (dwError) 

    case ERROR_IO_PENDING:  // 继续调用 GetOverlappedResults() 
    BytesSent = 0; 
    bWrite = false; 
    break; 
    default: 
    break; // 这里应处理其它错误


    else 
    LeaveCriticalSection(&port->m_csCommunicationSync); 
    }

    if (!bWrite) 

    bWrite = TRUE; 
    GetOverlappedResult(port->m_hComm, &port->m_ov, &BytesSent, TRUE);
    LeaveCriticalSection(&port->m_csCommunicationSync); 
    }
    port->m_uExactSize = BytesSent;
    port->m_pSpecBuf = NULL;
    }void CLSSerialPort::SetMessageTargetWindow(HWND hMsgWnd)
    {
    m_hMsgWnd = hMsgWnd;
    }DCB CLSSerialPort::GetDCB()
    {
    return m_dcb;
    }DWORD CLSSerialPort::GetCommEvents()
    {
    return m_dwCommEvents;
    }UINT CLSSerialPort::Receive(unsigned char *pBuf, UINT uBufSize)
    {
    DWORD dwTicks;
    ASSERT(m_hComm != NULL);  m_pSpecBuf = pBuf;
    m_uExactSize = 0;

    SetEvent(m_ov.hEvent);
    dwTicks = GetTickCount();
    while((m_dwTimeOut == 0) || ((GetTickCount()-dwTicks)<m_dwTimeOut))
    {
    if(m_uExactSize>=uBufSize)
    break;
    }
    ResetEvent(m_ov.hEvent);
    m_pSpecBuf = NULL; return m_uExactSize;
    }UINT CLSSerialPort::Send(unsigned char *pBuf, UINT uSize)
    {
    DWORD dwTicks;
    ASSERT(m_hComm != NULL);  m_uExactSize = 0;
    m_pSpecBuf = pBuf;
    m_uBufSize = uSize; SetEvent(m_hWriteEvent); //设置写事件
    dwTicks = GetTickCount();
    while((m_dwTimeOut == 0) || ((GetTickCount()-dwTicks)<m_dwTimeOut))
    {
    if(m_uExactSize>=uSize)
    break;
    }
    m_uBufSize = 0;
    m_pSpecBuf = NULL; return m_uExactSize;
    }void CLSSerialPort::SetTimeOut(DWORD dwMilliSec)
    {
    m_dwTimeOut = dwMilliSec;
    }void CLSSerialPort::ClosePort()
    {
    StopSerialPortThread();
    CloseHandle(m_hComm);
    m_hComm = NULL;
    }UINT CLSSerialPort::Receive(UINT *puVal)
    {
    return Receive((unsigned char*)puVal, sizeof(UINT));
    }UINT CLSSerialPort::Send(char *pString)
    {
    return Send((unsigned char*)pString, strlen(pString));
    }
      

  5.   

    请问这些都是你自己写的吗?
    if (是) then 
    高手!!!!
    向你学习
    else 
     谢谢!
    但仍给你一定的分 
    end if 你的给的代码和我买的一本书上的差不多。
    我感觉C++  MFC  很复杂,很深的东西。得有一定的基础才行的我现在比较熟悉用PowerBuilder写的代码
    关于com 口的pb 例子 我看了不是很理解 
     writefile() 中的数据写到缓冲区里去了。但是,具体到硬件上在什么地方?
    然后,readfile()又是怎么把缓冲区的数据读出的?读出后,数据防在什么地方?  
       
      

  6.   

    MSDN里面很详细的,另外在CSDN里面搜索一下,合理利用资源
      

  7.   

    去www.vckbase.net搜一下“串口”,有很多例子