Serial Comm using WriteFile / ReadFile
//#include "StdAfx.h" #include <stdio.h> #include <windows.h> #include <winbase.h> #include <iostream> #include <tchar.h> using namespace std; int main() { int com = 'COM2'; string data = "\n 010400 \n"; char output[32]; //unsigned int length = 0; DCB config = {0}; bool abContinue = true; DWORD dwBytesWritten; DWORD dwBytesRead; int isRead = false; HANDLE m_hCommPort = ::CreateFile(L"COM2", GENERIC_READ|GENERIC_WRITE,//access ( read and write) 0, //(share) 0:cannot share the COM port 0, //security (None) OPEN_EXISTING,// creation : open_existing 0, // we dont want overlapped operation 0// no templates file for COM port... ); config.DCBlength = sizeof(config); if((GetCommState(m_hCommPort, &config) == 0)) { printf("Get configuration port has a problem."); return FALSE; } config.BaudRate = 9600; config.StopBits = ONESTOPBIT; config.Parity = PARITY_NONE; config.ByteSize = DATABITS_8; config.fDtrControl = 0; config.fRtsControl = 0; if (!SetCommState(m_hCommPort, &config)) { printf( "Failed to Set Comm State Reason: %d\n",GetLastError()); //return E_FAIL; } printf("Current Settings\n Baud Rate %d\n Parity %d\n Byte Size %d\n Stop Bits %d", config.BaudRate, config.Parity, config.ByteSize, config.StopBits); int isWritten = WriteFile(m_hCommPort, &data,(DWORD) sizeof(data), &dwBytesWritten, NULL); //memset(output, 0, sizeof(output)); while (abContinue) { isRead = ReadFile(m_hCommPort, output, sizeof(output), &dwBytesRead, NULL); if(!isRead) { abContinue = false; break; } } cin.get(); } I have a problem reading from the COM port. If I go through the code, it goes to "isRead = ReadFile (m_hCommPort, output, sizeof (output)" and "dwBytesRead, NULL)"; and does not return ... This is my first attempt on this without success.
After opening the file, you can try something like this, but before trying to use it:
COMMTIMEOUTS timeouts; timeouts.ReadIntervalTimeout = 1; timeouts.ReadTotalTimeoutMultiplier = 1; timeouts.ReadTotalTimeoutConstant = 1; timeouts.WriteTotalTimeoutMultiplier = 1; timeouts.WriteTotalTimeoutConstant = 1; if (!SetCommTimeouts(m_hCommPort, &timeouts)) // setting timeouts failed. Edit: it might be easier to start with some code that works and get it to do what you need, rather than trying to get your code to work. Here is a simple terminal program. It is minimalist as a last resort, but it works (at least well enough so that I can see the output from my GPS, for example). This is a long way from what someone (least of all me) would call difficult, but should give at least some idea of how to start.
#include <stdio.h> #include <conio.h> #include <string.h> #define STRICT #define WIN32_LEAN_AND_MEAN #include <windows.h> void system_error(char *name) { // Retrieve, format, and print out a message from the last error. The // `name' that passed should be in the form of a present tense noun // (phrase) such as "opening file". // char *ptr = NULL; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), 0, (char *)&ptr, 1024, NULL); fprintf(stderr, "\nError %s: %s\n", name, ptr); LocalFree(ptr); } int main(int argc, char **argv) { int ch; char buffer[1]; HANDLE file; COMMTIMEOUTS timeouts; DWORD read, written; DCB port; HANDLE keyboard = GetStdHandle(STD_INPUT_HANDLE); HANDLE screen = GetStdHandle(STD_OUTPUT_HANDLE); DWORD mode; char port_name[128] = "\\\\.\\COM3"; char init[] = ""; // eg, "ATZ" to completely reset a modem. if ( argc > 2 ) sprintf(port_name, "\\\\.\\COM%c", argv[1][0]); // open the comm port. file = CreateFile(port_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if ( INVALID_HANDLE_VALUE == file) { system_error("opening file"); return 1; } // get the current DCB, and adjust a few bits to our liking. memset(&port, 0, sizeof(port)); port.DCBlength = sizeof(port); if ( !GetCommState(file, &port)) system_error("getting comm state"); if (!BuildCommDCB("baud=19200 parity=n data=8 stop=1", &port)) system_error("building comm DCB"); if (!SetCommState(file, &port)) system_error("adjusting port settings"); // set short timeouts on the comm port. timeouts.ReadIntervalTimeout = 1; timeouts.ReadTotalTimeoutMultiplier = 1; timeouts.ReadTotalTimeoutConstant = 1; timeouts.WriteTotalTimeoutMultiplier = 1; timeouts.WriteTotalTimeoutConstant = 1; if (!SetCommTimeouts(file, &timeouts)) system_error("setting port time-outs."); // set keyboard to raw reading. if (!GetConsoleMode(keyboard, &mode)) system_error("getting keyboard mode"); mode &= ~ ENABLE_PROCESSED_INPUT; if (!SetConsoleMode(keyboard, mode)) system_error("setting keyboard mode"); if (!EscapeCommFunction(file, CLRDTR)) system_error("clearing DTR"); Sleep(200); if (!EscapeCommFunction(file, SETDTR)) system_error("setting DTR"); if ( !WriteFile(file, init, sizeof(init), &written, NULL)) system_error("writing data to port"); if (written != sizeof(init)) system_error("not all data written to port"); // basic terminal loop: do { // check for data on port and display it on screen. ReadFile(file, buffer, sizeof(buffer), &read, NULL); if ( read ) WriteFile(screen, buffer, read, &written, NULL); // check for keypress, and write any out the port. if ( kbhit() ) { ch = getch(); WriteFile(file, &ch, 1, &written, NULL); } // until user hits ctrl-backspace. } while ( ch != 127); // close up and go home. CloseHandle(keyboard); CloseHandle(file); return 0; } If you did not explicitly set timeouts , then ReadFile will be blocked until the data becomes available.
I had this problem in a readfile with timeouts set. This made me hack, so I got code from the network that worked, and then changed line by line to see where the error was.
Turns out he was reading the file in order. My problem was WaitCommEvent, which hung when the port was disconnected, since no com event was ever received ...