如何解决Windows Api、COM口:接收后发送数据
我有一个微控制器,我通过 FT232RL 与我的 Windows 电脑通信。 在计算机方面,我正在使用 Windows API 制作一个 C 库来发送和接收数据。
我已经做到了:
- 接收数据(或多次接收),
- 传输数据(或多次传输),
- 先发送(或多次发送),然后接收数据(或多次接收)
但我没有做到:
- 传输数据然后接收。
如果我收到任何东西,然后尝试传输,就会出错。所以,我猜当我收到数据时,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):
我尝试了什么:
我注意到,在接收时唯一可能影响我的传输的变化不是在 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 举报,一经查实,本站将立刻删除。