asynchronous串口通信在Windows中的c

当我尝试运行一些基本写入串口的交stream文件时,出现错误。 我试图asynchronous运行,因为写入有时需要很长时间才能传输。 我的原始版本运行正常与WriteFile()命令同步运行。 我新使用OVERLAPPED,并会赞赏和input有关它。

我得到的错误是:

Debug Assertion Failed! <path to dbgheap.c> Line: 1317 Expression: _CrtIsValidHeapPointer(pUserData) 

当第二个写函数被调用时。

主要:

  { //initialized port (with overlapped), DBC, and timeouts result = write_port(outPortHandle, 128); result = write_port(outPortHandle, 131); } static void CALLBACK write_compl(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped) { //write completed. check for errors? if so throw an exception maybe? printf("write completed--and made it to callback function\n"); } int write_port(HANDLE hComm,BYTE* lpBuf) { OVERLAPPED osWrite = {0}; // Create this write operation's OVERLAPPED structure's hEvent. osWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (osWrite.hEvent == NULL) // error creating overlapped event handle return 0; // Issue write. if (!WriteFileEx(hComm, &lpBuf, 1, &osWrite, &write_compl )) { if (GetLastError() != ERROR_IO_PENDING) { // WriteFile failed, but isn't delayed. Report error and abort. printf("last error: %ld",GetLastError()); return 0; //failed, return false; } else { // Write is pending. WaitForSingleObjectEx(osWrite.hEvent, 50, TRUE); //50 ms timeout return -1; //pending } } else { return 1; //finished } } 

这不是完整的代码,对不起。 我也使用BYTE的数组,而不是常量。 但系统(“暂停”)导致我的debugging断言失败的错误,仔细查看我的代码后,当WriteFileEx()成功,它从来没有设置重叠结构中的事件的警报/超时,所以callback函数永远不会被调用。 我虽然解决了这些问题。

我只需要在调用ReadFileEx()函数(用于存储读取的字节以便可以处理)时分配的结构中处理/访问单个BYTE时需要帮助。 我需要知道如何使用偏移量访问该BYTE存储并使重叠结构为空。 将重叠的结构为空将是简单的将其中的句柄设置为INVALID_HANDLE_VALUE?

我想你有几个问题:


你传递一个整数作为指针(你的编译器应该警告这个或者最好拒绝编译代码):

result = write_port(outPortHandle,128);

将此与write_port的定义进行比较:

int write_port(HANDLE hComm,BYTE * lpBuf){

以上声明不符。 在稍后的时间里,通过获取BYTE * – >“&lpBuf”的地址,将指向lpBuf指针的指针传递给WriteFileEx函数。 这不会导致你认为它会做什么。


即使您解决了这个问题,只要写入成功排队,在50 ms的超时时间内仍然无法完成,您仍然可能会遇到寿命问题。

使用重叠I / O时,需要确保读/写缓冲区和重叠结构保持有效,直到I / O完成,取消或关闭的设备关闭。 在上面的代码中,您可以使用一个指向WriteFileEx中的OVERLAPPED结构的指针,该结构位于堆栈中。 如果WriteFileEx在50毫秒内没有完成,那么挂起的I / O将会引用一个不存在的OVERLAPPED结构,并且(希望)会有一个访问冲突(或者更糟糕的是,在你的应用程序的某个地方,你的应用程序中的数据会被静默地损坏)。

处理这些生命周期问题(如果性能不是一个大问题)的规范方法是使用包含OVERLAPPED结构和一些存储器的定制结构来读取/写入数据。 发布写入时分配结构,并从I / O完成例程释放结构。 将包含的OVERLAPPED结构的地址传递给WriteFileEx,并使用例如offsetof从完成例程中的OVERLAPPED地址获得自定义结构的地址。

另请注意,WriteFileEx实际上并不使用hEvent成员IIRC。


编辑:添加代码示例,请注意:

  1. 我实际上没有尝试编译代码,可能会有代码错别字或其他问题。
  2. 这不是发送数据的最有效方式(为发送的每个字节分配/取消分配内存块)。 不过,应该很容易改善。
     #include <stddef.h>
     #include <assert.h>
     #include <windows.h>

     // ...
     typedef struct _MYOVERLAPPED
     {
        重叠的ol;
         BYTE缓冲区;
     } MYOVERLAPPED,* LPMYOVERLAPPED;
     // ...

     static void CALLBACK write_compl(DWORD dwErrorCode,DWORD dwNumberOfBytesTransfered,LPOVERLAPPED lpOverlapped)
     {
         if(NULL == lpOverlapped)
         {
            断言(!“不应该发生”);
            返回;
         }

         LPBYTE pOlAsBytes =(LPBYTE)lpOverlapped;
         LPBYTE pMyOlAsBytes = pOlAsBytes  -  offsetof(MYOVERLAPPED,ol);
         LPMYOVERLAPPED pMyOl =(LPMYOVERLAPPED)pOlAsBytes;

        如果(((ERROR_SUCCESS == dwErrorCode)&& 
             (sizeof(BYTE)== dwNumberOfBytesTransfered))
         {
             printf(“写入%uc \ n”,pMyOl-> buffer);
         }
        其他
         {
             //处理错误
         }

        自由(pMyOl);
     }


     int write_port(HANDLE hComm,BYTE byte){

        LPMYOVERLAPPED pMyOl =(LPMYOVERLAPPED)malloc(sizeof(MYOVERLAPPED));

        ZeroMemory(pMyOl,sizeof(MYOVERLAPPED));
        pMyOl-> buffer = byte;

        //发出写入。
        if(!WriteFileEx(hComm,&pMyOl-> buffer,sizeof(BYTE),pMyOl,&write_compl)){
           if(GetLastError()!= ERROR_IO_PENDING){ 
              // WriteFile失败,但不会延迟。 报告错误并中止。
              自由(pMyOl);
               printf(“最后一个错误:%ld”,GetLastError());
              返回0;  //失败,返回false;
           }
           else {
            返回-1;  //待定
           }
        }
        else {
            自由(pMyOl);
            返回1;  //完成
        }
     }
  result = write_port(outPortHandle, 128); result = write_port(outPortHandle, 131); 

lpBuf参数必须是指向缓冲区的指针,而不是常量。

例如

 char buffer; buffer = 128; result = write_port(outPortHandle, &buffer); buffer = 131; result = write_port(outPortHandle, &buffer); 

你真正想要做的也是传递一个缓冲区的长度。

例如

  char buffer[] = { 128, 131 }; result = write_port(outPortHandle, &buffer, sizeof(buffer)); int write_port(HANDLE hComm,BYTE* lpBuf, size_t length) { ... // Issue write. if (!WriteFileEx(hComm, &lpBuf, length, &osWrite, &write_compl )) { ...