微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Windows Api、COM口:接收后发送数据

如何解决Windows Api、COM口:接收后发送数据

我有一个微控制器,我通过 FT232RL 与我的 Windows 电脑通信。 在计算机方面,我正在使用 Windows API 制作一个 C 库来发送和接收数据。

我已经做到了:

  1. 接收数据(或多次接收),
  2. 传输数据(或多次传输),
  3. 先发送(或多次发送),然后接收数据(或多次接收)

但我没有做到:

  1. 传输数据然后接收。

如果我收到任何东西,然后尝试传输,就会出错。所以,我猜当我收到数据时,HANDLE hComm 的配置发生了变化,我找不到。

那么问题是,当我接收数据时,我的 HANDLE hComm 配置有什么变化,之后不允许我进行传输?

这是我的代码/函数和给我错误的 main()。如果我运行这个,我会得到这个“错误 6”-下面的错误截图-:

#include <Windows.h>
#include <stdio.h>
#include <string.h>

int main(void)
{
    //Create Handler
    HANDLE hComm = comPortSetup("\\\\.\\COM5");//change this to the com port of your mcu
    //Setup the Receiver
    rx_setup(hComm);

    sleep(1);


    char  SerialBuffer[256];
    //Receive data
    rx_receive(hComm,&SerialBuffer);//<---- Works fine

    char firstData[125] = ".";
    tx_transmit(hComm,&firstData);//<----Wont work,since I received data first.

    CloseHandle(hComm);//Closing the Serial Port
    _getch();//press any key to close the window

}

处理comPortSetup:

HANDLE comPortSetup(char ComPrt[])
{
    int CharLoop=0;

    HANDLE HandleCom;                 // Handle to the Serial port

    /*----------------------------------- opening the Serial Port --------------------------------------------*/

    /*
    There might be a case where one would need to use CreateFileA instead. (Depending on the compiler)
    More can be found here: https://stackoverflow.com/questions/51462048/what-is-the-difference-between-createfile-and-createfilea
    */
    HandleCom = CreateFile( ComPrt,// Name of the Port to be Opened
                        GENERIC_READ | GENERIC_WRITE,// Read/Write Access
                        0,// No Sharing,ports cant be shared
                        NULL,// No Security
                        OPEN_EXISTING,// Open existing port only
                        0,// Non Overlapped I/O (0 does not match any of the flags of dwFlagsAndAttributes.
                                                           // This means we are setting no flags or attributes (We dont care about it) https://stackoverflow.com/questions/17997608/what-does-dwflagsandattributes-0-mean-in-the-createfile-method
                        NULL);                             // Null for Comm Devices

    if (HandleCom == INVALID_HANDLE_VALUE)
        printf("\n   Error! - Port %s can't be opened",ComPrt);
    else
        printf("\n   Port %s Opened\n ",ComPrt);

    /*------------------------------- Setting the Parameters for the SerialPort ------------------------------*/

    DCB dcbSerialParams = { 0 };

                        // Initializing DCB structure
    dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
    BOOL StatusFun;

    StatusFun = GetCommState(HandleCom,&dcbSerialParams);     //retreives  the current settings

    if (StatusFun == FALSE)
        printf("\n   Error! in GetCommState()");

    dcbSerialParams.Baudrate = CBR_9600;      // Setting Baudrate = 9600
    dcbSerialParams.ByteSize = 8;             // Setting ByteSize = 8
    dcbSerialParams.StopBits = OnesTOPBIT;    // Setting StopBits = 1
    dcbSerialParams.Parity   = nopARITY;      // Setting Parity = None

    StatusFun = SetCommState(HandleCom,&dcbSerialParams);  //Configuring the port according to settings in DCB

    if (StatusFun == FALSE)
        {
            printf("\n   Error! in Setting DCB Structure");
        }
    else
        {
            printf("\n   Setting DCB Structure Successfull\n");
            printf("\n       Baudrate = %d",dcbSerialParams.Baudrate);
            printf("\n       ByteSize = %d",dcbSerialParams.ByteSize);
            printf("\n       StopBits = %d",dcbSerialParams.StopBits);
            printf("\n       Parity   = %d",dcbSerialParams.Parity);
        }
    /*------------------------------------ Setting Timeouts --------------------------------------------------*/

    COMMTIMEOUTS timeouts = { 0 };

    //miliseconds (ms) intervals
    //interval between the arrival of any two bytes. Terminates the ReadFile
    timeouts.ReadIntervalTimeout         = 100; //Default =50
    //Total = (TimeoutMultiplier*BytesToRead + TimeoutConstant)
    timeouts.ReadTotalTimeoutConstant    = 10; //Default = 50
    timeouts.ReadTotalTimeoutMultiplier  = 20; //Default = 10
    //Total = (TimeoutMultiplier*BytesToRead + TimeoutConstant)
    timeouts.WritetotalTimeoutConstant   = 10; //Default = 50
    timeouts.WritetotalTimeoutMultiplier = 20; //Default = 10

    if (SetCommTimeouts(HandleCom,&timeouts) == FALSE)
        printf("\n   Error! in Setting Time Outs");
    else
        printf("\n\n   Setting Serial Port Timeouts Successfull");

    return HandleCom;
}

rx_setup:

BOOL rx_setup(HANDLE HandleCom)
{
/*------------------------------------ Setting Receive Mask ----------------------------------------------*/
    //https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-setcommmask
    BOOL Status;
    Status = SetCommMask(HandleCom,EV_RXCHAR); //Configure Windows to Monitor the serial device for Character Reception

    if (Status == FALSE)
    {
         printf("\n\n    Error! in Setting CommMask");
    }

    /*------------------------------------ Setting WaitComm() Event   ----------------------------------------*/

    printf("\n\n    Waiting for Data Reception...");

    DWORD dwEventMask; // Event mask to trigger. 32-bit unsigned integer (range: 0 through 4294967295 decimal)
    //Wait for the first character to be received
    Status = WaitCommEvent(HandleCom,&dwEventMask,NULL); //dwEventMask Should be 1 for "A character was received and placed in the input buffer." AKA EV_RXCHAR
    /*-------------------------- Program will Wait here till one Character is received ------------------------*/

    if (Status == FALSE)
    {
        printf("\n  Error! in Setting WaitCommEvent()");
        exit(-1);
    }

    return Status;

}

rx_receive:

void rx_receive(HANDLE HandleCom,char SerialBufferFun[])
{
    char  TempChar;                        // Temperory Character
    BOOL Status;

    /*Receiver start*/
    DWORD NoBytesRead;                     // Bytes read by ReadFile()
    int loopArrayFun = 0;
    do
    {
        Status = ReadFile(HandleCom,&TempChar,sizeof(TempChar),//No of bytes to be read
                          &NoBytesRead,//How many bytes were actually read
                          NULL);
        SerialBufferFun[loopArrayFun] = TempChar;
        printf("%c",SerialBufferFun[loopArrayFun]);
        loopArrayFun = loopArrayFun+1;
    }while (NoBytesRead > 0);//NoBytesRead = 0 when bytes are finished reading.

SerialBufferFun[loopArrayFun-3] = '\0'; //WHY -3
}

传输:

void tx_transmit(HANDLE HandleCom,char DataToTransmit[])
{
    BOOL Status;

        /*----------------------------- Writing a Character to Serial Port----------------------------------------*/
    //DataToTransmit should be  char or byte array,otherwise write will fail
    DWORD  dNoOFBytestoWrite;              // No of bytes to write into the port

    DWORD  dNoOfBytesWritten = 0;          // No of bytes written to the port

    dNoOFBytestoWrite = sizeof(DataToTransmit); // Calculating the no of bytes to write into the port


    if (HandleCom == INVALID_HANDLE_VALUE)
    {
        printf("\n   Invalid handle");
    }

        Status = WriteFile(HandleCom,// Handle to the Serialport
                       DataToTransmit,// Data to be written to the port
                       (dNoOFBytestoWrite),// No of bytes to write into the port
                       &dNoOfBytesWritten,// No of bytes written to the port
                       NULL);

    if (Status != TRUE)
        printf("\n\n   Error %d in Writing to Serial Port",GetLastError());
}

运行上述代码后出现的错误错误 6。“加热器驱动程序”等来自 MCU):

Error 6 in writing to serial port

我尝试了什么:

我注意到,在接收时唯一可能影响我的传输的变化不是在 rx_receive 内部,而是在 rx_setup 内部:

SetCommMask(HandleCom,EV_RXCHAR);

和:

WaitCommEvent(HandleCom,NULL);

所以我在接收后尝试执行 SetCommMask(HandleCom,0x00); 但它没有用,我遇到了同样的错误。我不知道我是否需要禁用 WaitCommEvent(HandleCom,NULL);,但由于它在接收完成后停止运行,所以它只是在函数内部运行,不会影响我的 HANDLE hComm

解决方法

根据MSDN:Sample,也许您需要设置引脚的信号状态以指示数据已在您的微控制器程序中发送/接收。更多细节在您的数据标准串行通信传输中。并且您应该像链接示例一样根据 WaitCommEvent(hCom,&dwEvtMask,&o); 的结果编写代码。

,

找到解决办法了!解决方案:

我根本不需要在 main 中使用 private const int _port = 555; private static WebSocketServer _ws = new WebSocketServer(IPAddress.Loopback,_port); 函数!

我不确定为什么会这样,但我现在可以按我想要的任何顺序接收/发送数据。

所以我的主要内容是:

rx_setup

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。