Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5567753
  • 博文数量: 1310
  • 博客积分: 12961
  • 博客等级: 上将
  • 技术积分: 15646
  • 用 户 组: 普通用户
  • 注册时间: 2009-01-09 11:25
个人简介

偷得浮生半桶水(半日闲), 好记性不如抄下来(烂笔头). 信息爆炸的时代, 学习是一项持续的工作.

文章分类

全部博文(1310)

文章存档

2020年(92)

2019年(193)

2018年(81)

2017年(80)

2016年(70)

2015年(52)

2014年(41)

2013年(51)

2012年(85)

2011年(45)

2010年(231)

2009年(287)

分类: Windows平台

2016-03-25 14:32:32

同步收发代码。(不能分开线程读与写)

点击(此处)折叠或打开

  1. /*
  2. * 线程控制串口的读与写操作。
  3. */
  4. #include "xconfig.h"

  5. #include <windows.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>

  8. static HANDLE FCommHandle = INVALID_HANDLE_VALUE;
  9. static BOOL FTerminated = FALSE;

  10. static DWORD do_comm_read(DWORD iTimeOut)
  11. {
  12.     BOOL bRet = FALSE;
  13.     DWORD iStart, iSpan;
  14.     DWORD dwLength, dwFixLen, dwErrorFlags, iRet=0;
  15.     COMSTAT comStatus;
  16.     char Buf[BUFSIZ];

  17.     iStart = GetTickCount();

  18.     dwLength = 0;
  19.     while (dwLength == 0) {
  20.         ClearCommError(FCommHandle, &dwErrorFlags, &comStatus);
  21.         if (dwErrorFlags > 0) {
  22.             //Abort Sending/Reading Operation and Data
  23.             PurgeComm(FCommHandle, (PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR));
  24.         }
  25.         dwLength = comStatus.cbInQue ;
  26.         iSpan = (GetTickCount()- iStart);
  27.         if (iSpan > iTimeOut) break ;
  28.         if (dwLength < dwFixLen) Sleep(0);
  29.     }
  30.     if (dwLength > 0) {
  31.         memset(Buf, 0, sizeof(Buf));
  32.         dwFixLen = sizeof(Buf);
  33.         bRet = ReadFile(FCommHandle, Buf, min(dwFixLen, dwLength), &iRet, 0);
  34.         if ((bRet)&& (iRet > 0)) {
  35.             printf("%s", Buf);
  36.         }
  37.     }
  38.     return iRet;
  39. }

  40. DWORD WINAPI ThreadFunc_UartSync(LPVOID args)
  41. {
  42.     BOOL bRet = FALSE;
  43.     DWORD iRet = 0, iLen=0;
  44.     char Buf[BUFSIZ];

  45.     while (!FTerminated)
  46.     {
  47.         memset(Buf, 0, sizeof(Buf));
  48.         gets(Buf);
  49.         iLen = strlen(Buf);
  50.         Buf[iLen] = '\r';
  51.         Buf[iLen+1] = '\n';
  52.         iLen += 2;
  53.         bRet = WriteFile(FCommHandle, Buf, iLen, &iRet, NULL);
  54.         if (bRet) {
  55.             //printf("WriteFile [%ld] bytes. [%s], real is [%ld] Bytes. \r\n", iLen, Buf, iRet);
  56.         }

  57.         while (0 != do_comm_read(1000));
  58.     }

  59.     return 0;
  60. }

  61. int main(int argc, char **argv)
  62. {
  63.     COMMTIMEOUTS CommTimeOut;
  64.     DCB dcb;
  65.     char com[64] = {0};

  66.     sprintf(com, "%s%s", "\\\\.\\", "com6");
  67.     FCommHandle = CreateFile(TEXT(com), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

  68.     if (FCommHandle == INVALID_HANDLE_VALUE) {
  69.         printf("Open Comm failed. [%ld] \r\n", GetLastError());
  70.         exit(0);
  71.     }
  72.     else {
  73.         printf("Open Comm success. \r\n");
  74.     }
  75.     //Set Commport File InQueue/OutQueue Buffer Size
  76.     SetupComm(FCommHandle, 8*1024, 8*1024);

  77.     //Set TimeOut Info
  78.     GetCommTimeouts( FCommHandle, &CommTimeOut);
  79.     CommTimeOut.ReadIntervalTimeout = 1000;
  80.     CommTimeOut.ReadTotalTimeoutMultiplier = 1000;
  81.     CommTimeOut.ReadTotalTimeoutConstant = 1000;
  82.     CommTimeOut.WriteTotalTimeoutMultiplier = 1000;
  83.     CommTimeOut.WriteTotalTimeoutConstant = 1000;
  84.     SetCommTimeouts( FCommHandle, &CommTimeOut);

  85.     //Set DCB Info
  86.     GetCommState(FCommHandle, &dcb);
  87. #if 1
  88.     dcb.DCBlength = sizeof(DCB);
  89.     dcb.BaudRate = CBR_115200;
  90.     dcb.ByteSize = DATABITS_8 ;
  91.     dcb.Parity = NOPARITY;
  92.     dcb.StopBits = ONESTOPBIT;
  93.     dcb.fBinary = TRUE;
  94.  #else
  95.     BuildCommDCB("baud=115200 parity=N data=8 stop=1" ,&dcb);
  96.  #endif
  97.     SetCommState(FCommHandle, &dcb);
  98.     PurgeComm(FCommHandle, (PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR));

  99.     //create thread to recv and send via Uart Device.
  100.     HANDLE hdr_sync = CreateThread(NULL, 0, ThreadFunc_UartSync, NULL, 0, NULL);

  101.     WaitForSingleObject(hdr_sync, INFINITE);

  102.     CloseHandle(FCommHandle);
  103.     FCommHandle = INVALID_HANDLE_VALUE;

  104.     return 0;
  105. }
异步代码

点击(此处)折叠或打开

  1. #include <windows.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>

  4. typedef struct {
  5.     HANDLE FCommHandle; //INVALID_HANDLE_VALUE; comx handler.
  6.     BOOL FTerminated; //FALSE; thread terminate flag.
  7.     OVERLAPPED ovlap;
  8.     // Event array.
  9.     // One element is used for each event. There are two event handles for each port.
  10.     // A Write event and a receive character event which is located in the overlapped structure (m_ov.hEvent).
  11.     // There is a general shutdown when the port is closed.
  12.     HANDLE hEventArray[3];

  13.     CRITICAL_SECTION    mutex;

  14.     char UserCmd[BUFSIZ];
  15.     DWORD iCmdLen;

  16.     char Recv[BUFSIZ];
  17.     DWORD iRecved;

  18. } ASYNC_COMM_CONTEXT;


  19. static ASYNC_COMM_CONTEXT g_context;



  20. static void RecvFromCom(void)
  21. {
  22.     BOOL bResult = TRUE;
  23.     DWORD dwError = 0;
  24.     DWORD BytesRead = 0;
  25.     COMSTAT comstat;

  26.     for (;;) {
  27.         EnterCriticalSection(&g_context.mutex);
  28.         bResult = ClearCommError(g_context.FCommHandle, &dwError, &comstat);
  29.         LeaveCriticalSection(&g_context.mutex);
  30.         if (comstat.cbInQue == 0) { // break out when all bytes have been read
  31.             break;
  32.         }

  33.         EnterCriticalSection(&g_context.mutex);

  34.         bResult = ReadFile(g_context.FCommHandle,        // Handle to COMM port
  35.                              g_context.Recv,                // RX Buffer Pointer
  36.                              1,                    // Read one byte
  37.                              &BytesRead,            // Stores number of bytes read
  38.                              &g_context.ovlap);        // pointer to the m_ov structure
  39.         // deal with the error code
  40.         if (!bResult){
  41.             switch (dwError = GetLastError()) {
  42.                     case ERROR_IO_PENDING: {
  43.                             GetOverlappedResult(g_context.FCommHandle,    // Handle to COMM port
  44.                                          &g_context.ovlap,        // Overlapped structure
  45.                                          &BytesRead,        // Stores number of bytes read
  46.                                          TRUE);             // Wait flag
  47.                         }
  48.                         break;
  49.                     default:
  50.                         break;
  51.             }
  52.         }

  53.         LeaveCriticalSection(&g_context.mutex);

  54.         if (BytesRead > 0) {
  55.             g_context.Recv[BytesRead] = 0;
  56.             printf("%s", g_context.Recv);
  57.             BytesRead = 0;
  58.         }
  59.     }
  60. }

  61. static void SendDataToCom(void)
  62. {
  63.     BOOL bResult = TRUE;
  64.     DWORD BytesSent = 0;

  65.     ResetEvent(g_context.hEventArray[2]);

  66.     EnterCriticalSection(&g_context.mutex);

  67.     //start write Data.
  68.     {
  69.         bResult = WriteFile(g_context.FCommHandle,                            // Handle to COMM Port
  70.                             g_context.UserCmd,                    // Pointer to message buffer in calling finction
  71.                             g_context.iCmdLen,     // Length of message to send
  72.                             &BytesSent,                                // Where to store the number of bytes sent
  73.                             &g_context.ovlap);                            // Overlapped structure
  74.         // deal with any error codes
  75.         if (!bResult) {
  76.             DWORD dwError = GetLastError();
  77.             switch (dwError) {
  78.                 case ERROR_IO_PENDING:    { // continue to GetOverlappedResults()
  79.                         GetOverlappedResult(g_context.FCommHandle,    // Handle to COMM port
  80.                                      &g_context.ovlap,        // Overlapped structure
  81.                                      &BytesSent,        // Stores number of bytes sent
  82.                                      TRUE);             // Wait flag
  83.                         break;
  84.                     }
  85.                 default:
  86.                  break;
  87.             }
  88.         }
  89.     }

  90.     //write complete.
  91.     LeaveCriticalSection(&g_context.mutex);

  92.     //Verify that the data size send equals what we tried to send
  93.     if (BytesSent != g_context.iCmdLen)    {// Length of message to send
  94.         //do what???
  95.     }
  96. }

  97. ///////////////////////////////////////////////////////////////////////////////////////////////////
  98. //// WIN32 异步串口
  99. ///////////////////////////////////////////////////////////////////////////////////////////////////
  100. static VOID FinalComPort(void)
  101. {
  102.     CloseHandle( g_context.ovlap.hEvent );

  103.     if (g_context.FCommHandle != INVALID_HANDLE_VALUE) {
  104.         CloseHandle(g_context.FCommHandle);
  105.         g_context.FCommHandle = INVALID_HANDLE_VALUE;
  106.     }
  107. }

  108. static BOOL InitEvent(void)
  109. {
  110.     //initial Overlapped struct.
  111.     g_context.ovlap.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  112.     ResetEvent(g_context.ovlap.hEvent);

  113.     g_context.hEventArray[0] = CreateEvent(NULL, TRUE, FALSE, NULL); //rs232 shutdown event.
  114.     g_context.hEventArray[1] = g_context.ovlap.hEvent; //rs232 read
  115.     g_context.hEventArray[2] = CreateEvent(NULL, TRUE, FALSE, NULL); //rs232 write event.

  116.     return TRUE;
  117. }

  118. static BOOL InitComPort(void)
  119. {
  120.     COMMTIMEOUTS CommTimeOut;
  121.     DCB dcb;
  122.     char com[64] = {0};

  123.     sprintf(com, "%s%s", "\\\\.\\", "com6");
  124.     g_context.FCommHandle = CreateFile(TEXT(com),
  125.                          GENERIC_READ | GENERIC_WRITE,    // read/write types
  126.                      0,                                // comm devices must be opened with exclusive access
  127.                      NULL,                            // no security attributes
  128.                      OPEN_EXISTING,                    // comm devices must use OPEN_EXISTING
  129.                      FILE_FLAG_OVERLAPPED,            // Async I/O
  130.                      0);                            // template must be 0 for comm devices

  131.     if (g_context.FCommHandle == INVALID_HANDLE_VALUE) {
  132.         printf("Open Comm failed. [%ld] \r\n", GetLastError());
  133.         return FALSE;
  134.     }
  135.     else {
  136.         printf("Open Comm success. \r\n");
  137.     }

  138.     //Set Commport File InQueue/OutQueue Buffer Size
  139.     SetupComm(g_context.FCommHandle, 8*1024, 8*1024);

  140.     //Set TimeOut Info
  141.     GetCommTimeouts( g_context.FCommHandle, &CommTimeOut);
  142.     CommTimeOut.ReadIntervalTimeout = 1000;
  143.     CommTimeOut.ReadTotalTimeoutMultiplier = 1000;
  144.     CommTimeOut.ReadTotalTimeoutConstant = 1000;
  145.     CommTimeOut.WriteTotalTimeoutMultiplier = 1000;
  146.     CommTimeOut.WriteTotalTimeoutConstant = 1000;
  147.     SetCommTimeouts( g_context.FCommHandle, &CommTimeOut);

  148.     SetCommMask(g_context.FCommHandle, EV_RXFLAG | EV_RXCHAR);

  149.     //Set DCB Info
  150.     GetCommState(g_context.FCommHandle, &dcb);
  151. #if 1
  152.     dcb.DCBlength = sizeof(DCB);
  153.     dcb.BaudRate = CBR_115200;
  154.     dcb.ByteSize = DATABITS_8 ;
  155.     dcb.Parity = NOPARITY;
  156.     dcb.StopBits = ONESTOPBIT;
  157.     dcb.fBinary = TRUE;
  158.  #else
  159.     BuildCommDCB("baud=115200 parity=N data=8 stop=1" ,&dcb);
  160.  #endif
  161.     dcb.EvtChar = 'q';
  162.     dcb.fRtsControl = RTS_CONTROL_ENABLE;        // set RTS bit
  163.     SetCommState(g_context.FCommHandle, &dcb);
  164.     PurgeComm(g_context.FCommHandle, (PURGE_RXABORT | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_TXCLEAR));

  165.     return TRUE;
  166. }


  167. void WriteUserCmd(char *Buf, DWORD iLen)
  168. {
  169.     memcpy(g_context.UserCmd, Buf, iLen);
  170.     g_context.iCmdLen = iLen;
  171.     // set event for write
  172.     SetEvent(g_context.hEventArray[2]);
  173. }


  174. DWORD WINAPI ThreadFunc_UartASync(LPVOID args)
  175. {
  176.     BOOL bRet = FALSE;
  177.     DWORD Event = 0;
  178.     DWORD CommEvent = 0;
  179.     DWORD dwError = 0;
  180.     COMSTAT comstat;

  181.     while (!g_context.FTerminated)
  182.     {
  183.         // Make a call to WaitCommEvent(). This call will return immediatly
  184.         // because our port was created as an async port (FILE_FLAG_OVERLAPPED)
  185.         bRet = WaitCommEvent(g_context.FCommHandle, &Event, &g_context.ovlap);
  186.         if (!bRet) { // If WaitCommEvent() returns FALSE, process the last error to determin the reason..
  187.             switch (dwError = GetLastError())
  188.             {
  189.                 case ERROR_IO_PENDING: // This is a normal return value if there are no bytes to read at the port.
  190.                     break;
  191.                 default: // All other error codes indicate a serious error has occured. Process this error.
  192.                     break;
  193.             }
  194.         }
  195.         else {
  196.             // If WaitCommEvent() returns TRUE, check to be sure there are actually bytes in the buffer to read.
  197.             bRet = ClearCommError(g_context.FCommHandle, &dwError, &comstat);
  198.             if (comstat.cbInQue == 0)
  199.                 continue;
  200.         }

  201.         // Main wait function. This function will normally block the thread
  202.         // until one of nine events occur that require action.
  203.         Event = WaitForMultipleObjects(3, g_context.hEventArray, FALSE, INFINITE);

  204.         switch (Event)
  205.         {
  206.         case 0: //shutdown event.
  207.             FinalComPort();
  208.             return 0;
  209.          break;
  210.         case 1: //read event. Event will be set by Overlapped via System.
  211.             GetCommMask(g_context.FCommHandle, &CommEvent);
  212.             if (CommEvent & EV_RXCHAR) {// Receive character event from port.
  213.                 RecvFromCom();
  214.             }
  215.             break;
  216.         case 2: //write event. this Event should be set by User Manual.
  217.             SendDataToCom();
  218.             break;
  219.         } //end switch
  220.     } //for ;;

  221.     return 0;
  222. }

  223. DWORD WINAPI ThreadFunc_Console(LPVOID args)
  224. {
  225.     DWORD iLen=0;
  226.     char Buf[BUFSIZ];
  227.     while (!g_context.FTerminated)
  228.     {
  229.         memset(Buf, 0, sizeof(Buf));
  230.         gets(Buf);
  231.         iLen = strlen(Buf);
  232.         Buf[iLen] = '\r';
  233.         Buf[iLen+1] = '\n';
  234.         iLen += 2;
  235.         WriteUserCmd(Buf, iLen);
  236.     }

  237.     return 0;
  238. }

  239. int main(int argc, char **argv)
  240. {
  241.     if (!InitComPort()) exit(-1);
  242.     if (!InitEvent()) exit(-2);

  243.     // initialize critical section
  244.     InitializeCriticalSection(&g_context.mutex);
  245.     g_context.FTerminated = FALSE;

  246.     //create thread to recv and send via Uart Device.
  247.     HANDLE hdr_async = CreateThread(NULL, 0, ThreadFunc_UartASync, NULL, 0, NULL);
  248.     HANDLE hdr_console = CreateThread(NULL, 0, ThreadFunc_Console, NULL, 0, NULL);

  249.     //waiting for some time
  250.     Sleep(60*1000);
  251.     g_context.FTerminated = TRUE;

  252.     WaitForSingleObject(hdr_async, INFINITE);
  253.     WaitForSingleObject(hdr_console, INFINITE);

  254.     DeleteCriticalSection(&g_context.mutex);
  255.     FinalComPort();
  256.     return 0;
  257. }

阅读(2506) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~