根據某本天書說明

首先要Configure a serial port

1.呼叫 CreateFile() 來開一個預設設定的新埠。

2.初始化 DCB 結構內的 DCBlength 的成員。

3.呼叫 GetCommState() 看剛剛開的埠的參數設定。

4.修改 DCB 以符合需求。

5.呼叫 SetCommState() 設定參數。

於是有了以下的範例

// Open the serial port.
// 參數1. Pointer to the name of the port
// 參數2. Access (read/write)  mode
// 參數3. Share mode
// 參數4. Pointer to the security attribute
// 參數5. How to open the serial port
// 參數6. Port attributes
// Handle to port with attribute to copy
HANDLE hPort;
hPort = CreateFile(lpszPortName,
                              GENERIC_READ|GENERIC_WRITE,
                              0,
                              NULL,
                              OPEN_EXISTING,
                              0,
                              NULL);
// If it fails to open the port, return error.
if ( hPort == INVALID_HANDLE_VALUE )
{
      CloseHandle(hPort);               // Could not open the port.
      LocalFree( lpMsgBuf );            // Free the buffer.
      return EC_FOPEN;
}
PortDCB.DCBlength = sizeof(DCB);
GetCommState(hPort, &PortDCB);      // Get the default port setting info

// Change the DCB structure settings.
PortDCB.BaudRate = 9600;                            // Current baud rate
PortDCB.fBinary = TRUE;                                // Binary mode; no EOF check
PortDCB.fParity = TRUE;                                 // Enable parity checking.
PortDCB.fOutxCtsFlow = FALSE;                    // No CTS output flow control
PortDCB.fOutxDsrFlow = FALSE;                    // No DSR output flow control
PortDCB.fDtrControl = DTR_CONTROL_ENABLE;      // DTR flow control type
PortDCB.fDsrSensitivity = FALSE;                   // DSR sensitivity
PortDCB.fTXContinueOnXoff = TRUE;             // XOFF continues Tx
PortDCB.fOutX = FALSE;                                // No XON/XOFF out flow control
PortDCB.fInX = FALSE;                                  // No XON/XOFF in flow control
PortDCB.fErrorChar = FALSE;                        // Disable error replacement.
PortDCB.fNull = FALSE;                                 // Disable null stripping.
PortDCB.fRtsControl = RTS_CONTROL_ENABLE;      // RTS flow control
PortDCB.fAbortOnError = FALSE;           // Do not abort reads/writes on error
PortDCB.ByteSize = 8;                                 // Number of bits/bytes, 4-8
PortDCB.Parity = NOPARITY;                        // 0-4=no,odd,even,mark,space
PortDCB.StopBits = ONESTOPBIT;               // 0,1,2 = 1, 1.5, 2

// Configure the port according to the specifications of the DCB structure.
if (!SetCommState (hPort, &PortDCB))
{
     printf("Unable to configure the port & Err Info. = %s\n",          
                (LPCTSTR)lpMsgBuf);
     // Free the buffer.
     LocalFree( lpMsgBuf );
     return EC_INVAL_CONFIG;
}
// Retrieve the time-out parameters for all read and write operations on the port.
GetCommTimeouts(hPort, &CommTimeouts);
// Change the COMMTIMEOUTS structure settings.
CommTimeouts.ReadIntervalTimeout = MAXDWORD;
CommTimeouts.ReadTotalTimeoutMultiplier = 0;
CommTimeouts.ReadTotalTimeoutConstant = 0;
CommTimeouts.WriteTotalTimeoutMultiplier = 10;
CommTimeouts.WriteTotalTimeoutConstant = 1000;
// Set the time-out parameters for all read and write operations on the port.
if (!SetCommTimeouts (hPort, &CommTimeouts))
{
// Could not create the read thread.
      dwError = GetLastError();
      printf("Unable to set the time-out parameters & Err code = %ld\n",       
                 dwError);
      return EC_TIMEOUT_SET;
}
EscapeCommFunction(hPort, SETDTR);
EscapeCommFunction(hPort, SETRTS);
pCreate->h_Port = hPort;                     // reserve the port handle

資料的寫入

再度引用天書的說法

WriteFile()是將資料送到UART寫入資料緩衝內。

1.Pass the port handler to the  WriteFile()  function in the  hPort  parameter. The
CreateFile() function returns this handler when our program opens a new port.
2.Specify a pointer to the data to be written in lpBuffer. Typically, this will be binary
data or a character array.
3.Specify the number of characters to write in nNumberOfBytesToWrite. For Win-
dows CE–based devices, only one character is usually written, because the application
must convert Unicode  characters to ASCII  characters to enable a text transfer to a
device at the opposite end of a serial connection.
4.Specify in lpNumberOfBytesWritten  a pointer to the number of bytes actually
written. WriteFile() fills this variable so that our program can determine if the data
has been transferred.
5.Be sure that the lpOverlapped parameter is set to NULL.

以下是天書的步驟說明

1.Pass the port handler to the  WriteFile()  function in the  hPort  parameter.

   TheCreateFile() function returns this handler when our program opens a new port.

2.Specify a pointer to the data to be written in lpBuffer. Typically, this will be binarydata or a character array.

3.Specify the number of characters to write in nNumberOfBytesToWrite.

   For Win-dows CE–based devices, only one character is usually written, because the applicationmust convert Unicode  characters to

   ASCII  characters to enable a text transfer to adevice at the opposite end of a serial connection.

4.Specify in lpNumberOfBytesWritten  a pointer to the number of bytes actuallywritten.

   WriteFile() fills this variable so that our program can determine if the datahas been transferred.

5.Be sure that the lpOverlapped parameter is set to NULL.

超簡短寫入的範例

if (!WriteFile (hPort,                          // Port handle  
                  NumByte,                      // Number of bytes to write
                  &dwNumBytesWritten,     // Pointer to the number of bytes written
                  NULL))                          // Must be NULL for Windows CE
{
               // WriteFile failed. Report error.
               printf("Unable to write the port ...& Err Info. = %s", (LPCTSTR)lpMsgBuf);
              // Free the buffer.
              LocalFree( lpMsgBuf );
              …….
}

資料的讀取

天書又再度開示了步驟

1.Pass the port handler to ReadFile() in the hPort parameter. The CreateFile()

   function returns this handler when a new port is created.

2.Specify a pointer to the data to be read in lpBuffer.

3.Specify the number of characters to read in nNumberOfBytesToRead.

4.Specify a pointer to the number of bytes actually read in the argument

   lpNumberOfBytesRead.

5.Be sure that  lpOverlapped  is set to NULL. Windows CE does not support the

   overlapped I/O.

另外還有一個要點:

      如果要使用 WaitCommEvent() ,最好另開一個thread去讀取序列埠。

後面漏漏等,我貼範例比較快。

if (!(hThread = CreateThread(NULL,                        // no security attributes
             0,                                                        // use default stack size
             (LPTHREAD_START_ROUTINE) ThreadFunc,
             (LPVOID)hCommPort,                              // parameter to thread function
             CREATE_SUSPENDED,                             // creation flag - suspended
             &IDThread) ) )                                      // returns thread ID
{
      printf("Create Read Thread failed\n");
      return EC_CREATE_THREAD;
}
ResumeThread(hThread);                  // start thread function now
Ret = WaitForSingleObject(hThread, dTimeout);
if (Ret == WAIT_OBJECT_0)
{
      // data received & process it...
      // Need do nothing, the data has been stored in the hCommPort in Thread Func.
      // close thread handle
      CloseHandle(hThread);
}
else if (Ret == WAIT_TIMEOUT)
{
       // time out happened, warning & kill thread
      Ret = GetExitCodeThread(hThread, &ExitCode);
      if (ExitCode == STILL_ACTIVE)
      {
            printf("Time out happened!\n"); // debug purpose
            TerminateThread(hThread, ExitCode);
            CloseHandle(hThread);
            return EC_PORT_TIMEOUT;
      }
      else
      {
            printf("ERROR in GetExitCodeThread: != STILL_ACTIVE\n");
            ecStatus = EC_EXIT_CODE;
       }
}
else
{
      printf("ERROR in WaitFor SingleObject...\n");
      ecStatus = EC_WAIT_SINGLEOBJ;
}
……

關於thread的內容如下

void WINAPI ThreadFunc(void* hCommPorts)
{
          ……
          // Specify a set of events to be monitored for the port.
         SetCommMask(CommPorts->handlePort, EV_RXCHAR | EV_CTS |
                                                                     EV_DSR | EV_RLSD | EV_RING);
         // Wait for an event to occur for the port.
         WaitCommEvent(CommPorts->handlePort, &dwCommModemStatus, 0);
         // Re-specify the set of events to be monitored for the port.
        SetCommMask(CommPorts->handlePort, EV_RXCHAR | EV_CTS |
                                                                      EV_DSR |EV_RLSD| EV_RING);
         if (dwCommModemStatus & EV_RXCHAR||dwCommModemStatus & EV_RLSD)
         {     // received the char_event
               // Read the data from the serial port.
               bResult = ReadFile(CommPorts->handlePort, &Byte, 1, &dwBytesTransferred, 0);
               if (!bResult)
               {
                     printf("Unable to read the port ...& Err Info. = %s\n", (LPCTSTR)lpMsgBuf);
                     LocalFree( lpMsgBuf ); // Free the buffer.
                     printf("ERROR in PortRead - Timeout\n");
               }
               else
               {
                     // store the data read.
                     CommPorts->bByte = Byte;
                     nTotRead++;
               }
      }
      return;
}

如果沒有WaitCommEvent()怎麼辦?

我也不知道怎麼辦

這只是個節錄,不是傳道授業用。