I have tried to read data from sensors. The sensors controller is using db9 header (com1), because I will use com1, I use db9 to usb converter and get com 11.
I have program to read and write to the serial port, it work when I use com1, but when I change to com 11, the program fail to open the com because it reach ERROR_FILE_NOT_FOUND
here is my program for the serial port programming:
Serial::Serial(char *portName)
{
this->connected = false;
wchar_t wcPort[64];
size_t convertedChars = 0;
mbstowcs_s(&convertedChars, wcPort, strlen(portName), portName, _TRUNCATE);
this->hSerial = CreateFile(wcPort,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
//Check if the connection was successfull
if(this->hSerial==INVALID_HANDLE_VALUE)
{
//If not success full display an Error
if(GetLastError()==ERROR_FILE_NOT_FOUND){
//Print Error if neccessary
printf("ERROR: Handle was not attached. Reason: %s not available.\n", portName);
}
else
{
printf("ERROR!!!");
}
}
else
{
DCB dcbSerialParams = {0};
if (!GetCommState(this->hSerial, &dcbSerialParams))
{
printf("failed to get current serial parameters!");
}
else
{
dcbSerialParams.BaudRate=CBR_38400;
dcbSerialParams.ByteSize=8;
dcbSerialParams.StopBits=ONESTOPBIT;
dcbSerialParams.Parity=NOPARITY;
dcbSerialParams.fOutX=TRUE;
dcbSerialParams.fInX=TRUE;
if(!SetCommState(hSerial, &dcbSerialParams))
{
printf("ALERT: Could not set Serial Port parameters");
}
else
{
this->connected = true;
}
}
}
}
Is it because the software/program or the hardware problem?
when I try with hyperterminal, it can read and write the com 11.
To open COM ports numbered 10 and higher, you need to prefix the name with \\.\.
Now, in C, you must escape all those backslashes. So the port you need to open is "\\\\.\\COM11".
Related
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:
Receive data (or multiple receives),
Transmit data (or multiple transmits),
First transmit (or multiple transmits) and then receive data (or multiple receives)
But I have not managed to:
Transmit Data and then receive.
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
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.
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
}
I have created a File system driver to allow or block the external storage devices in windows. For allowing a particular device I need to find out the Serial Number. I am using PSTORAGE_DEVICE_DESCRIPTOR to find out Serial Number but it will not work for all devices(eg: some devices shows the serial number as a special character). Is there any other possible way to find the Serial number in File system driver
Following code section is used for querying serial number
char szBuff [1024];
STORAGE_PROPERTY_QUERY Query;
//STORAGE_DEVICE_DESCRIPTOR Buffer[4];
NTSTATUS Status = STATUS_SUCCESS;
PSTORAGE_DEVICE_DESCRIPTOR Descriptor=NULL;
PIRP NewIrp2=NULL;
PIO_STACK_LOCATION NextIrpStack=NULL;
IO_STATUS_BLOCK IoStatus;
char szSptr[2]={'_','\0'};
SIZE_T szLength = 0;
Query.PropertyId = StorageDeviceProperty;// first set the query properties
Query.QueryType = PropertyStandardQuery;
KeInitializeEvent(&WaitEvent_newIrp, NotificationEvent, TRUE);// initialize the waitable event
__try
{
memset(szBuff,0,1024);
NewIrp2=IoBuildDeviceIoControlRequest(IOCTL_STORAGE_QUERY_PROPERTY, StorageStackDeviceObject,
(PVOID)&Query,sizeof(STORAGE_PROPERTY_QUERY),
szBuff,1024,
FALSE,&WaitEvent_newIrp,&IoStatus);
if(NewIrp2==NULL)
{
return STATUS_SUCCESS;
}
Status = IoCallDriver(StorageStackDeviceObject, NewIrp2);// send this irp to the storage device
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&WaitEvent_newIrp, Executive, KernelMode, FALSE, NULL);
Status =IoStatus.Status;
}
}
__finally
{
//if(NT_SUCCESS(Status))
if(szBuff!=NULL)
{
try
{
Descriptor = (PSTORAGE_DEVICE_DESCRIPTOR)szBuff;
Descriptor->Size = sizeof(szBuff);
uBusType = Descriptor->BusType; //Get the bus type.
}
except(EXCEPTION_EXECUTE_HANDLER)
{
/* Error handling code */
}
}
char pszStart[255];
if(Descriptor->SerialNumberOffset!=0)
{
memset(pszStart,0,255);
RtlStringCopyWorkerA(pszStart,255,((char*)(UINT_PTR)Descriptor+(DWORD32)Descriptor->SerialNumberOffset),255);
//pszStart condains the serial number
}
}
I was wondering if any of you know what I'm doing wrong here? So I have this program in C, that sends AT commands to a modem. These commands have been tested on hyperterminal and work fine, but when sendind them through the modem I get, first, and "OK" for the first "AT" command, which is good, but then, upon sending the next command, the modem answers with "AT+CC"...which I have no idea what it means. Any help is appreciated.
Source:
void sendSMS(const char* port, const char* number, const char* baud)
{
HANDLE hComm;
DCB dcb;
BOOL fSuccess;
hComm = CreateFile(port, //port name
GENERIC_READ | GENERIC_WRITE, //Read/Write
0, // No Sharing
NULL, // No Security
OPEN_EXISTING,// Open existing port only
0, // Non Overlapped I/O
NULL); // Null for Comm Devices
if (hComm == INVALID_HANDLE_VALUE)
{
printf("ERROR: Cannot open serial port\r\n");
return;
}
else
printf("STATUS: Serial port opened\r\n");
// Configure PORT
// Initialize the DCB structure.
SecureZeroMemory(&dcb, sizeof(DCB));
dcb.DCBlength = sizeof(DCB);
// Build on the current configuration by first retrieving all current
// settings.
fSuccess = GetCommState(hComm, &dcb);
if (!fSuccess)
{
// Handle the error.
printf("GetCommState failed with error %d.\n", GetLastError());
return;
}
// Fill in some DCB values and set the com state:
// 57,600 bps, 8 data bits, no parity, and 1 stop bit.
dcb.BaudRate = atoi(baud); // baud rate
dcb.ByteSize = 8; // data size, xmit and rcv
dcb.Parity = NOPARITY; // parity bit
dcb.StopBits = ONESTOPBIT; // stop bit
dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fOutX = FALSE;
fSuccess = SetCommState(hComm, &dcb);
if (!fSuccess)
{
// Handle the error.
printf("SetCommState failed with error %d.\n", GetLastError());
return;
}
// Get the comm config again.
fSuccess = GetCommState(hComm, &dcb);
if (!fSuccess)
{
// Handle the error.
printf("GetCommState failed with error %d.\n", GetLastError());
return;
}
// End Config
sendATCommands(hComm, number, "This is NOT a test.");
CloseHandle(hComm);//Closing the Serial Port
}
void sendATCommands(HANDLE hComm, const char* number, const char message[])
{
char str[256];
if (!writeToPort(hComm, "AT\r\n")) //Hello modem
return;
if (!readFromPort(hComm)) // Must be OK
return;
if (!writeToPort(hComm, "AT+CMGF=1\r\n")) //Modem, prepare to send text messages
return;
if (!readFromPort(hComm)) // Must be OK again
return;
memset(str, 0, 256);
strcpy_s(str, "AT+CMGS=\"");
strcat_s(str, 256, number);
strcat_s(str, 256, "\"\r\n");
if (!writeToPort(hComm, str)) //Modem, here's the number to send the message to
return;
if (!readFromPort(hComm)) // Must be ">"
return;
memset(str, 0, 256);
strcpy_s(str, message);
strcat_s(str, 256, "^Z");
if (!writeToPort(hComm, str)) //Modem, communicate this to the number I gave you.
return;
if (!readFromPort(hComm)) // Must be CMGS: ##
return;
}
int writeToPort(HANDLE hComm, const char lpBuffer[])
{
DWORD dNoOFBytestoWrite; // No of bytes to write into the port
DWORD dNoOfBytesWritten = 0; // No of bytes written to the port
dNoOFBytestoWrite = sizeof(lpBuffer);
int Status = WriteFile(hComm, // Handle to the Serial port
lpBuffer, // Data to be written to the port
dNoOFBytestoWrite, //No of bytes to write
&dNoOfBytesWritten, //Bytes written
NULL);
if (Status == FALSE)
{
printf("ERROR: Cannot write to serial port\r\n");
}
else
printf("STATUS: Command %s \n written to port.\r\n", lpBuffer);
return Status;
}
int readFromPort(HANDLE hComm)
{
char TempChar; //Temporary character used for reading
char SerialBuffer[256];//Buffer for storing Rxed Data
DWORD NoBytesRead = 0;
int i = 0;
int status;
memset(SerialBuffer, 0, 256);
printf("STATUS: Waiting response...\r\n");
do
{
status = ReadFile(hComm, //Handle of the Serial port
&TempChar, //Temporary character
sizeof(TempChar),//Size of TempChar
&NoBytesRead, //Number of bytes read
NULL);
if (!status)
{
printf("ERROR: Cannot read from serial port\r\n");
break;
}
SerialBuffer[i] = TempChar;// Store Tempchar into buffer
i++;
}
while (NoBytesRead > 0);
if (status)
printf("PORT RESPONSE: %s \r\n", SerialBuffer);
return status;
}
I have a C program that trying to read data from COM Port in windows.
I am able to write the data on com port but not able to read it.
This is my read function? if anyone could take a look and point me to correct direction.
I am starting a seperate thread in main method
------ Code of main method function ------
if(!SetCommMask(hSerial,eventFlags)){
printf("Error in setting the event maskwith error: %d \n",GetLastError());}
_beginthread(*readDataFromPort,0,NULL);
----- Code of read data function ------
void readDataFromPort(void*)
{
DWORD dwReadResult;
bool waitOnRead = FALSE;
bool abContinue = TRUE;
memset(&ovRead,0,sizeof(ovRead));
ovRead.hEvent = CreateEvent(0,TRUE,0,0);
if(ovRead.hEvent == NULL){
fprintf(stderr,"Error creating overlapped event for reading");
}
//Reading data from port
while (true){
//Changed the overlap to NULL
if(WaitCommEvent(hSerial,&eventFlags,NULL)){
if(GetCommMask(hSerial,&dwMask)){
ResetEvent(ovRead.hEvent);
if(dwMask == EV_RXCHAR){
printf("character arrived");
}
}
memset(tmp,0,sizeof(tmp));
if(!ReadFile(hSerial, tmp, sizeof(tmp), NULL, &ovRead)){
if(GetLastError()!=ERROR_IO_PENDING){
printf("error io pending: Error is %d\n",GetLastError());
break;
}else{
waitOnRead=TRUE;
}
}
if(waitOnRead){
dwReadResult = WaitForSingleObject(ovRead.hEvent,10000);
switch(dwReadResult){
case WAIT_OBJECT_0:
if(!GetOverlappedResult(hSerial,&ovRead,&dwBytesRead,TRUE)){
printf("Damn error again :-(");
}else{
if(dwBytesRead>0){
++Rx;
printf("Tx - %d: Rx - %d\n",Tx,Rx);
printf("%s",tmp);
}
}
}
}
waitOnRead=FALSE;
}
if(strlen(tmp)>0 && inLoop){
writeDataToPort(*tmp);
}
}
CloseHandle(ovRead.hEvent);
_endthread();
}
> Blockquote
_beginthread(*readDataFromPort,0,NULL);
This snippet starts the thread regardless of SetComMask outcome, but if you are reading OK must have worked.
Check out MSDN threaded port read/write which works (VC5 compile worked straight off out of the box) above code looks really similar though, is it same?.
i have a microcontroller connected to my usb port which i am reading using the code below
`
#include <windows.h>
#include <stdio.h>
#include <conio.h>
int main (void)
{
int n = 25;
char szBuff[25 + 1] = {0};
HANDLE hSerial;
DCB dcbSerialParams = {0};
COMMTIMEOUTS timeouts={0};
DWORD dwBytesRead =25;
dcbSerialParams.DCBlength=sizeof(DCB);
hSerial = CreateFile("COM4",
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if(hSerial==INVALID_HANDLE_VALUE)
{
if(GetLastError()==ERROR_FILE_NOT_FOUND)
{
puts ("cannot open port!");
return;
}
puts ("invalid handle value!");
return;
}
if (!GetCommState(hSerial, &dcbSerialParams))
{
puts ("error getting state");
return;
}
dcbSerialParams.BaudRate=CBR_57600;
dcbSerialParams.ByteSize=8;
dcbSerialParams.StopBits=ONESTOPBIT;
dcbSerialParams.Parity=NOPARITY;
if(!SetCommState(hSerial, &dcbSerialParams))
{
puts ("error setting port state");
return;
}
timeouts.ReadIntervalTimeout = 30;
timeouts.ReadTotalTimeoutMultiplier = 100;
timeouts.ReadTotalTimeoutConstant = 100;
if (!SetCommTimeouts(hSerial, &timeouts))
{
puts ("timeouts setting fail!");
}
while (1){
if(!ReadFile(hSerial, szBuff, n, &dwBytesRead, NULL)){
puts ("serial read error fail!");
return;
}
else
{
printf ("%s\n" , szBuff);
}
}
getch();
return 0;
}
`
i am sending data by this format: $A.B.C$ followed by a newline. so its 7 (or 8, including newline) bytes right? i set the 3rd argument for readfile to 20, greater than 7 bytes so that i can succesfully read all of the data string. however reading sometimes misses a few characters. instead of reading $A.B.C$ i read in one line $A.B.C and in the line after that $ (a hidden'\n'). how can i fix this?
This is normal. When the receive buffer contains at least one byte, you'll get back whatever is in the buffer. Which is usually but a fraction of what you expect, serial ports are quite slow. You'll have to keep reading until you get the full response.
Just to add to the answer, be sure to use some type of timeout, or you will block waiting a character that maybe never comes.
Maybe one option could be reading byte per byte then just wait the last '$' or '\n' to know that you received the complete string and then process it.