Reputation: 168
I have a microcontroller which I communicate with my windows pc, through FT232RL. On the computer side, I am making a C-library to send and receive data, using windows API.
I have managed to:
But I have not managed to:
If I receive anything, and then try to transmit, I get error. So, I guess when I receive data, there is a change in configuration of the HANDLE hComm
, which I cannot find.
So the question is, what changes to my HANDLE hComm
configuration when I receive data, which does not allow me to transmit after that?
Here is my code/functions and the main() that give me the error. If I run this, I get this "error 6" -screenshot of the error down below-:
#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
}
HANDLE 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://learn.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
}
transmit:
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());
}
The error I get after running the above code (Error 6. The 'Heater Driver' etc are from the MCU):
What I tried:
I noticed that the only thing that changes that could influence my transmission when receiving, is not inside rx_receive
but inside rx_setup
:
SetCommMask(HandleCom, EV_RXCHAR);
and:
WaitCommEvent(HandleCom, &dwEventMask, NULL);
So I tried to do SetCommMask(HandleCom, 0x00);
after the reception but It did not work, I got the same error. I do not know if I need to disable the WaitCommEvent(HandleCom, &dwEventMask, NULL);
though, but since it stops running when the reception is done, So it just runs inside the function and does not affect my HANDLE hComm
Upvotes: 0
Views: 2205
Reputation: 168
Found a solution! Solution:
I did not need to use the rx_setup
function in the main at all!.
I am unsure of why that is, but I can receive/send data now in any sequence I want.
So my main will be:
#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);//<----Works as expected now
CloseHandle(hComm);//Closing the Serial Port
_getch();//press any key to close the window
}
Upvotes: 0
Reputation: 2130
According to MSDN:Sample, Maybe you need to set a pin's signal state to indicate the data has been sent/received in your microcontroller program. More details reside in your serial communication transmission of data standard. And you should write code according to the result of WaitCommEvent(hCom, &dwEvtMask, &o);
like the linked sample.
Upvotes: 1