ComPrinter

Image link to download ComPrinter.exeComPrinter is a console application (i.e. a command line program) that opens a serial port and displays incoming text characters in the console. It features several very useful options, including the following:

  • ComPrinter supports a user-specified COM port number.
  • ComPrinter supports a user-specified baud rate.
  • By default, ComPrinter opens the highest available COM port (especially useful if you’re using a USB-to-serial converter).
  • ComPrinter provides a facility to simulate a keystroke for each incoming character. In combination with a USB-to-serial converter, this provides a very simple way of turning a microcontroller system with serial output into a communication device.
  • It provides an ideal free alternative to HyperTerminal in many applications.

Support ComPrinter Development

Without exaggeration, far more people have walked on the moon than have clicked this button.

How many links must there be on the Internet? Billions? At least. Occasionally, I think about those unfortunate links that hardly ever (or maybe never) get clicked. If you wish to travel a path which few before you have braved, you will find to the right of this paragraph one of the Internet’s most infrequently clicked buttons.

Seriously though, ComPrinter is free to download and use. No matter how much you use it, you shouldn’t feel any obligation to donate. You can support ComPrinter development by letting me know if you find it useful (just leave a comment below).

Why use ComPrinter?

I do a lot of microcontroller development and I regularly use a serial connection to send text from a microcontroller to a PC to be displayed on screen. I previously used HyperTerminal to open the serial port and display the incoming text. However, as of Windows 7, that application is no longer installed with the operating system, so I needed a convenient free Hyperterminal alternative. As it turns out, ComPrinter is actually more convenient than Hyperterminal for most of the things I do.

My personal favourite ComPrinter feature is that by default it opens the highest available COM port. I frequently use a low-cost USB-to-serial converter to communicate between a microcontroller circuit and my PC. However, each time I plug in my USB-to-serial converter, it is assigned a different (and usually quite high) COM port number. So far, ComPrinter has always automatically found and opened it without difficulty.

Running ComPrinter

There are several options when you run ComPrinter:

  • /devnum DEVICE_NUMBER : Use this to specify a COM port.
  • /baudrate BITS_PER_SECOND : Use this to specify the baud rate.
  • /keystrokes : Use this to simulate a keystroke for each incoming character, for example to type text into an application.
  • /debug : Use this to display additional information when opening the COM port.
  • /quiet : Use this to supress the welcome message text and other information. Only text received via the COM port will be displayed.

Example Commands

To open the highest available COM port at the default baud rate (2400 bits per second) and print all incoming text:

ComPrinter.exe

To open COM22 at 38400 baud and display all incoming text:

ComPrinter.exe /devnum 22 /baudrate 38400

To open the highest available COM port at 38400 baud and simulate a keystroke for each incoming character as well as printing it in the console window:

ComPrinter.exe /baudrate 38400 /keystrokes

Source Code

ComPrinter is a Win32 console application, written in C. I compiled it with the MinGW version of gcc. The complete source code is below.

//
// ComPrinter.c - This program reads text from a
//   serial port and prints it to the console.
//
// Written by Ted Burke - last updated 3-5-2012
//
// To compile with MinGW:
//
//		gcc -o ComPrinter.exe ComPrinter.c
//
// Example commands:
//
//		ComPrinter /devnum 22 /baudrate 38400
//		ComPrinter /id 12 /quiet
//		ComPrinter /baudrate 38400 /keystrokes
//
// To stop the program, press Ctrl-C
//

#define WINVER 0x0500

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

#define MESSAGE_LENGTH 100

// Declare variables and structures
HANDLE hSerial = INVALID_HANDLE_VALUE;
DCB dcbSerialParams = {0};
COMMTIMEOUTS timeouts = {0};
DWORD dwBytesWritten = 0;
char dev_name[MAX_PATH] = "";
int dev_number = -1;
int baudrate = 2400;
int scan_max = 30;
int scan_min = 1;
int simulate_keystrokes = 0;
int debug = 1; // print some info by default
int id = -1;

void CloseSerialPort()
{
	if (hSerial != INVALID_HANDLE_VALUE)
	{
		// Close serial port
		fprintf(stderr, "\nClosing serial port...");
		if (CloseHandle(hSerial) == 0)
			fprintf(stderr, "Error\n");
		else fprintf(stderr, "OK\n");
	}
}

void exit_message(const char* error_message, int error)
{
	// Print an error message
	fprintf(stderr, error_message);
	fprintf(stderr, "\n");

	// Exit the program
	exit(error);
}

void simulate_keystroke(char c)
{
	// This structure will be used to create the keyboard
	// input event.
	INPUT ip;

	// Set up a generic keyboard event.
	ip.type = INPUT_KEYBOARD;
	ip.ki.wScan = 0; // hardware scan code for key
	ip.ki.time = 0;
	ip.ki.dwExtraInfo = 0;

	// Press the key
	// Currently only alphabet lettes, spaces, commas and full stops.
	if (c >= 0x61 && c <= 0x7A) c -= 0x20;
	if (c >= 0x30 && c <= 0x39) ip.ki.wVk = c;
	else if (c >= 0x41 && c <= 0x5A) ip.ki.wVk = c;
	else if (c == ' ') ip.ki.wVk = VK_SPACE;
	else if (c == ',') ip.ki.wVk = VK_OEM_COMMA;
	else if (c == '.') ip.ki.wVk = VK_OEM_PERIOD;
	else if (c == '\b') ip.ki.wVk = VK_BACK;
	else if (c == '\t') ip.ki.wVk = VK_TAB;
	else if (c == '\n') ip.ki.wVk = VK_RETURN;
	else return;

	ip.ki.dwFlags = 0; // 0 for key press
	SendInput(1, &ip, sizeof(INPUT));

	// Release the key
	ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
	SendInput(1, &ip, sizeof(INPUT));
}

int main(int argc, char *argv[])
{
	// Parse command line arguments. Available options:
	//
	// /devnum DEVICE_NUMBER
	// /baudrate BITS_PER_SECOND
	// /id ROBOT_ID_NUMBER
	// /keystrokes
	// /debug
	// /quiet
	//
	int n = 1;
	while (n < argc)
	{
		// Process next command line argument
		if (strcmp(argv[n], "/devnum") == 0)
		{
			if (++n >= argc) exit_message("Error: no device number specified", 1);

			// Set device number to specified value
			dev_number = atoi(argv[n]);
		}
		else if (strcmp(argv[n], "/baudrate") == 0)
		{
			if (++n >= argc) exit_message("Error: no baudrate value specified", 1);

			// Set baudrate to specified value
			baudrate = atoi(argv[n]);
		}
		else if (strcmp(argv[n], "/id") == 0)
		{
			if (++n >= argc) exit_message("Error: no id number specified", 1);

			// Set id to specified value
			id = atoi(argv[n]);
		}
		else if (strcmp(argv[n], "/keystrokes") == 0)
		{
			simulate_keystrokes = 1;
		}
		else if (strcmp(argv[n], "/debug") == 0)
		{
			debug = 2;
		}
		else if (strcmp(argv[n], "/quiet") == 0)
		{
			debug = 0;
		}
		else
		{
			// Unknown command line argument
			if (debug) fprintf(stderr, "Unrecognised option: %s\n", argv[n]);
		}

		n++; // Increment command line argument counter
	}

	// Welcome message
	if (debug)
	{
		fprintf(stderr, "\nComPrinter.exe - written by Ted Burke\n");
		fprintf(stderr, "https://batchloaf.wordpress.com\n");
		fprintf(stderr, "This version: 3-5-2012\n\n");
	}

	// Debug messages
	if (debug > 1) fprintf(stderr, "dev_number = %d\n", dev_number);
	if (debug > 1) fprintf(stderr, "baudrate = %d\n\n", baudrate);

	// Register function to close serial port at exit time
	atexit(CloseSerialPort);

	if (dev_number != -1)
	{
		// Limit scan range to specified COM port number
		scan_max = dev_number;
		scan_min = dev_number;
	}

	// Scan for an available COM port in _descending_ order
	for (n = scan_max ; n >= scan_min ; --n)
	{
		// Try next device
		sprintf(dev_name, "\\\\.\\COM%d", n);
		if (debug > 1) fprintf(stderr, "Trying %s...", dev_name);
		hSerial = CreateFile(dev_name, GENERIC_READ|GENERIC_WRITE, 0, 0,
								OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
		if (hSerial!=INVALID_HANDLE_VALUE)
		{
			if (debug > 1) fprintf(stderr, "OK\n");
			dev_number = n;
			break; // stop scanning COM ports
		}
		else if (debug > 1) fprintf(stderr, "FAILED\n");
	}

	// Check in case no serial port could be opened
	if (hSerial==INVALID_HANDLE_VALUE)
		exit_message("Error: could not open serial port", 1);

	// If we get this far, a serial port was successfully opened
	if (debug) fprintf(stderr, "Opening COM%d at %d baud\n\n", dev_number, baudrate);

	// Set device parameters:
	//	baudrate (default 2400), 1 start bit, 1 stop bit, no parity
	dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
	if (GetCommState(hSerial, &dcbSerialParams) == 0)
		exit_message("Error getting device state", 1);
	dcbSerialParams.BaudRate = baudrate;
	dcbSerialParams.ByteSize = 8;
	dcbSerialParams.StopBits = ONESTOPBIT;
	dcbSerialParams.Parity = NOPARITY;
	if(SetCommState(hSerial, &dcbSerialParams) == 0)
		exit_message("Error setting device parameters", 1);

	// Set COM port timeout settings
	timeouts.ReadIntervalTimeout = 50;
	timeouts.ReadTotalTimeoutConstant = 50;
	timeouts.ReadTotalTimeoutMultiplier = 10;
	timeouts.WriteTotalTimeoutConstant = 50;
	timeouts.WriteTotalTimeoutMultiplier = 10;
	if(SetCommTimeouts(hSerial, &timeouts) == 0)
		exit_message("Error setting timeouts", 1);

	// Read text and print to console (and maybe simulate keystrokes)
	int state = 1;
	//int i;
	char c;
	char message_buffer[MESSAGE_LENGTH];
	DWORD bytes_read;

	// Depending on whether a robot id has been specified, either
	// print all incoming characters to the console or filter by
	// the specified id number
	if (id == -1)
	{
		// No robot id specified - print everything to console
		while(1)
		{
			ReadFile(hSerial, &c, 1, &bytes_read, NULL);
			if (bytes_read == 1)
			{
				printf("%c", c);
				if (simulate_keystrokes == 1) simulate_keystroke(c);
			}
		}
	}
	else
	{
		// A robot id was specified - use a state machine to parse
		// incoming text and display only messages in the correct
		// format matching the specified id number
		while(1)
		{
			// Read next character
			ReadFile(hSerial, &c, 1, &bytes_read, NULL);
			if (bytes_read != 1) continue;

			if (state == 1)
			{
				// State 1: Waiting for '<' character to start message
				n = 0;
				strcpy(message_buffer, "");
				if (c == '<') state = 2;
			}
			else if (state == 2)
			{
				// State 2: Reading robot id one digit at a time
				if (c >= '0' && c <= '9') n = 10*n + (c-48);
				else if (c == '@') state = 3;
				else state = 1;
			}
			else if (state == 3)
			{
				// Got a '@' character, so now reading actual message
				if (n != id) state = 1;
				else if (c != '>') strncat(message_buffer, &c, 1);
				else if (c == '>') state = 4;
				if (strlen(message_buffer) >= MESSAGE_LENGTH-1) state = 4;
			}
			else if (state == 4)
			{
				// State 4: Display complete message
				fprintf(stdout, "%s\n", message_buffer);
				state = 1;
			}
			else state = 1;
		}
	}

	// We should never get to this point because when the user
	// presses Ctrl-C, the atexit function will be called instead.
	return 0;
}

65 Responses to ComPrinter

  1. Abdullah Tahir says:

    Sir I’m facing some problem. I have been writing code on VC++ 6.0. But I couldn’t get desired data (and even getting data more than 1 byte). I also downloaded your COM Printer software but it is showing: Opening COM2 at baud 2400 and then does nothing. Can you guide me to fix these two problems. Thanks.

  2. batchloaf says:

    Hi Abdullah,

    Do you know if COM 2 is the correct serial port device? Also, is 2400 the correct baudrate? If one of these is wrong, you’ll need to specify the desired device and/or baudrate on the command line. For example, the following command would open COM22 to receive data at 38400 baud (i.e. 38.4 kbps) and display the incoming bytes in the command window:

    ComPrinter.exe /devnum 22 /baudrate 38400
    
    Ted
  3. Anne M. says:

    Thanks for this application, it’s really handy… !! However, is it possible to run it while the COM port is already opened and used by another program ? I would like to use ComPrinter, let’s say on COM 5, but without turning off a software that needs to constantly read the output of this COM5…

    • batchloaf says:

      Hi Anne,

      Unfortunately, I don’t think that’s possible. A single program can certainly read from and write to a serial port device at the same time, but I don’t think it’s possible for two separate programs to open the same device simultaneously, even if one is reading and one is writing. There’s probably some sort of virtual serial port software out there somewhere that can open a single serial port, then provide two or more virtual serial ports for other programs to access, but I haven’t ever looked for one.

      As a matter of interest, what is the software that is reading continuously from COM5? If you can explain a little bit more about the application, perhaps I can suggest a workaround.

      Ted

  4. Ramesh says:

    can u send a source code for write bytes to a serial port

    • batchloaf says:

      Hi Ramesh,

      Sorry, I haven’t had a chance to do this yet, but I’ll do my best to post a simple serial port reading/writing example in C later on today if I can.

      Ted

      • Ramesh says:

        Hmmm thanks Ted….send me as soon as possible

      • Ramesh says:

        Hi Ted ,
        I know its not possible to read and write a serial port in c language simultaneously
        i think we can do it in C threads…. can u jst help me to do read/write serial port in C threads

  5. Ramesh says:

    …IS IT POSSIBLE TO WRITE A PROGRAM FOR SERIAL PORT WRITE/READ AS A SINGLE PROGRAM USING THREADS…..

  6. Ken says:

    Along the lines of Ramesh’s request… I am looking to start the program with an argument for the com port number, send a single character “+”, and get back the text from a barcode read. Posted to STDOUT so it can be piped to a file. The program needs to die after doing this.

  7. Ken says:

    ComBCread.exe /devnum 5 /baudrate 9600 /data 8N1 /char + /file bc_result.txt

  8. tim says:

    Just starting programming in C. I’ve been programming the 8051 in assembly for several years now, and since GW-BASIC stopped being supported, have been looking for a way to write my own programs for the P.C. to interface with my 8051 projects. I’m using Pelles C for Windows, which I can only assume works as well as any other free compiler.

    http://www.christian-heffner.de/index.php?page=download&lang=en&version=5.00.1

    Your serial programming example(s) are the only examples I’ve found I could get to work…thank you. So now I have a working example to breakdown and learn from.

    As for a terminal program, have you tried Brays Terminal. It’s truly awesome replacement for Hyper Terminal. Works with Windows 8 as long as your USB to 232 cable is compatible with Windows 8 (I had to buy a new cable when I got my new computer). Try it…you’ll like it.

    https://sites.google.com/site/terminalbpp/

    • batchloaf says:

      Hi Tim,

      Thanks for your comment. I’m glad to hear you found my examples useful, especially since it sounds like you’re working on applications which are in some ways similar to a lot of what I do. I’ve used several different microcontrollers over the years (PIC, MSP430, AVR) but I’ve actually never used 8051. When I started programming microcontrollers back in the 1990s, the development tools for 8051 were just way too expensive, so I cut my teeth on PICs.

      I’ve heard of the Pelles C compiler previously, but I haven’t tried it. Partly because I work on Windows and Linux alternately, I use GCC as my regular C compiler for PC programs. On Windows, I use MinGW which includes GCC and a number of other GNU development tools. Sometimes, I’m forced to use Visual C++ for a specific project, but I’m a lot happier using GCC, which makes it easier to strip things back to the bare essentials – no bloated project files and directories, just a plain text editor, my C files and a simple build script!

      I’m interested to hear that you’re a GW-BASIC refugee. I come across people all the time who loved using it and found it incredibly empowering. Several of my colleagues were bereft when it was retired. For what it’s worth, I urge you to take a look at Python. Firstly, it seems to tick a lot of the boxes for GW-BASIC aficionados – it just shares some of the same “spirit”. Secondly, with your specific applications in mind, the PySerial module is absolutely the best thing I’ve used for automating and experimenting with serial port interaction. In a very few short lines, you can open a serial port and send and receive arbitrary data. Incoming data can be really easily parsed and, for example, plotted on a graph, written to a file, or streamed over TCP/IP.

      Personally, I really enjoy programming in Python. After C (or alongside C), it’s my favourite language. Also, when I have students working on serial port interaction with microcontroller, I almost always suggest that they use Python on the PC end to get things working fast and they usually become firm fans of it and start using it for all sorts of other things.

      Anyway, thanks again for the interesting message, and especially for the Bray Terminal suggestion – it looks brilliant and is just the kind of thing I would find useful!

      Ted

      EDIT: Here’s a link to some really short examples that show how easy it is to open and use a serial port in Python:

      http://pyserial.sourceforge.net/shortintro.html

      • tim says:

        GW-Basic was the bomb for our type of programming. However, it was slow because it had to run within it’s own interpreter until IBM came out with a ‘compiler’ that converted basic to stand alone .exe programs. Then it went from the ‘bomb’ to the A-bomb! There were several other ‘basics’ that came out with code similar to what I’m finding in C.

        I chose C because of all the available information. However, I’m finding the information is a bit misleading because most of it is too advanced for my level right now and it’s hard to get a handle on the basics. Im reading the ‘C’ book right now and doing the newbie examples but I’ll try Python… I don’t know anything about any of them right now so I guess one is as good as the other. I just need to find something I can use….

  9. tim says:

    I am proud to be the first to click your ‘This button has literally never been clicked’ button…

  10. tim says:

    Glad to contribute…

    I took your suggestion and am trying Python. I’m having trouble getting the PYSerial examples you recommended to work. I’m thinking it’s because I’m using version 3.4 and the examples are written for an earlier version (2.x…??). Do you have any insight on this? Should I install 2.7 instead of 3.4 or try running both or??

    Thanks again

    • batchloaf says:

      Hi Tim,

      As it happens, I’m still running Python 2.7, so I haven’t actually tried using PySerial with Python 3.x. However, the PySerial installation page refers to Python 3.x as if they are compatible with each other. For example, see here in the installation section:

      http://pyserial.sourceforge.net/pyserial.html#from-source-tar-gz-or-checkout

      Once you have installed Python, there are a few different methods of installing the PySerial add-on. If you haven’t already done so, I suggest using the MS Windows installer for PySerial, which is available from here:

      https://pypi.python.org/pypi/pyserial

      Make sure you select the installer version for Python 3.x.

      If PySerial still doesn’t work after running that installer, I have two further suggestions you could consider:

      • You could try Python 2.7 instead. There are some minor differences between Python versions 2.x and 3.x, but for your purposes it won’t make much (any?) difference to step back to 2.7, so if that gets it working then great. You can install version 2.7 alongside version 3.x, but you’ll need to install PySerial separately for Python 2.7 as well. Also, you’ll need to be careful which version you’re running each time you start it up!
      • Another thing you could consider (either with 3.x or 2.7) is to install win32all, which is an add-on package for Python which provides Python programs with access to Microsoft’s full Win32 API. It seems plausible (to me) that this might be required to get PySerial running, but I’m just guessing. I already have win32all installed, so it’s impossible for me to compare, but if I didn’t maybe I would also see an error?

      If you do decide to install win32all (and it won’t do any harm to try), you can download the installer here:

      http://sourceforge.net/projects/pywin32/files/pywin32/Build 219/

      The file you want from that page is probably pywin32-219.win32-py3.4.exe although you might need to pick a different one if you’re running 64-bit Windows.

      Also, perhaps you might cut and paste the exact error you’re seeing? That might help me to identify the specific problem.

      Finally, let me just offer a few words of encouragement, lest you should lose heart! I find it very frustrating when I can’t get something working at all, and I know it’s tempting to move on to a different approach, but please rest assured: your effort here will be richly rewarded. Once you get this installation sorted, and you transfer your first bytes from microcontroller to Python, you’ll immediately see how unbelievable flexible and empowering this is. So, in short, keep the faith!

      Ted

  11. jiraheta says:

    Hi Ted, I grabbed your copy of comPrinter. But for some reason I get the following compilation errors. Was wondering if you can give me a hand to figure this out what the issue is.
    Thanks.

    the errors are as follow:
    66: In function ‘void simulate_keystroke(char)’
    66: ‘INPUT’ undeclared {first use in this function)
    66: (Each undeclared identifier is reported only once for each function it appears in.)
    66: parse error before ‘;’
    69: ‘ip’ undeclared (first use this function)
    69: ‘INPUT_KEYBOARD’ undeclared (first use this function)
    72: confused by earlier errors, bailing out

    I notice this are variables that are not declared. So I am assuming those should be declared somewhere and I might be missing something. I have copied your code exactly as it is above and using the same compiler you are using in case of compatibility issues with other compilers (which I don’t think its the issue). Thanks for you help on this matter.

    • batchloaf says:

      Hi Jiraheta,

      If you’re using the same compiler as me and have copied the code exactly from what is shown above, then I’m not quite sure why you’re getting that error, but it’s probably something to do with the following:

      “INPUT” is a type of generic data structure which is used to store information about a user input event. For example, it could store all the information about a key press – which key was pressed, whether it was pressed or released, whether any modifier keys such as Alt or Ctrl were pressed at the same time. Or it could store the information relating to a mouse click – where the mouse pointer was when the button was clicked, which button was clicked, etc. In this program, we’re using an INPUT structure to store the information about a simulated keyboard event that is then actually carried out using the SendInput function.

      What I think behind the problem you’re having is that INPUT and SendInput were only introduced into the Win32 API in (I think) Windows NT, so when you compile a program using these features it won’t be compatible with versions of Windows earlier than that. The compiler only makes INPUT, SendInput, etc available (by defining them) if it knows that you don’t intend to be compatible with these earlier (ancient actually) versions of Windows.

      The following line in the program tells the compiler that we’re only compiling for compatibility with Windows NT (I think) and later:

      #define WINVER 0x0500
      

      It’s critically important that that line appears before this one…

      #include <windows.h>
      

      …because INPUT, SendInput, etc will be defined by “windows.h” if WINVER is defined as 0x0500 or higher.

      If you leave out the line that defines WINVER, you get errors just like the ones you saw because INPUT won’t have been defined. Is it possible that that line has been commented out, removed, or moved to a point after #include windows.h?

      Ted

      • jiraheta says:

        Hi ted, and thank yo so much for your replay. I have check the code and it seems that the code is they way you described. #define WINVER 0x0500 before any of the imports. Is there anything else that you can think that might be cause thing issue? I will try to compile this on a different system with a winxp OS on it and see what the results are. Doing this, in consideration of the forward compatibility of the code with newer OS systems. This time around I was compiling on a win7 system. thank you so much for you help, and if you think of anything else that could be cause this issue… please do share.

        Take care,
        Jose

      • batchloaf says:

        Hi again Jose,

        I don’t know if this will make any difference or not, but I suppose it’s worth a try. Add the following line just before or after “#define WINVER 0x0500”:

        #define _WIN32_WINNT 0x0500
        

        I’m assuming both can be defined simultaneously, but in case it causes some errors, I suppose you could try removing the original “#define WINVER 0x0500”.

        I did a quick google search for other people getting similar errors compiling programs with MinGW and some of them seemed to solve their problems by including that line (see here for example). As before, the “#define _WIN32_WINNT 0x0500” must come before “#include “.

        Let me know if that makes any difference.

        Ted

      • batchloaf says:

        Ok, I did a bit more digging and I’m going to modify that suggestion a bit.

        Try putting this at the start of the program before #include

        #define WINVER 0x0501
        #define _WIN32_WINNT 0x0501
        #define _WIN32_WINDOWS 0x0501
        

        The reason I’m suggesting that is because of what I read on these pages (among others):

        Ted

  12. jiraheta says:

    Hi ted
    Thank you for following up with me on this issue. I am still looking around to solve this issue. I
    came across those solutions but they didn’t work for me. You can see the SC here.
    On both Subline and minGW give me the same output and same errors

    I will keep searching and see if I can find out a solution.

    • batchloaf says:

      Hi Jose,

      I’ve just tried compiling it myself on Windows 7 and I got no errors at all.

      I’m using a 32-bit laptop and I’m running GCC version 4.6.2. Are you running 64-bit Windows or maybe using a later version of GCC?

      Ted

    • batchloaf says:

      I’ve just tried compiling it with GCC version 4.8.1 and that worked perfectly for me too.

      Could this be a 32-bit / 64-bit compatibility thing?

      Ted

  13. jiraheta says:

    Thank you guys for your help on this. Yeah, I believe this error has to do with the 64bit version of windows. I compile on a 32 bit version and it works as expected. I got to look more into this as the machine where I need to run this is a 64 bit version:/

    thanks a million for all your help.

    • batchloaf says:

      Hi Jose,

      I’ll try to find a 64-bit PC in work that I can try compiling it on. If that really is the problem, I’d be optimistic that it can be solved. I don’t think there’s anything in the program that should particularly pose a problem in 64-bit Windows – it’s probably just a matter of getting it to compile with a 64-bit compiler. I’ll let you know if I find a solution. If you make any progress in the meantime, please let me know.

      Ted

  14. Burak says:

    Hi TED ,

    Thank you for sharing such a nice a functional program .
    What I’m trying to do is controlling a bunch of devices over network via telnet connection protocol .
    There is a server pc and there is a batch file in it which I use in order to send Serial commands through a TTL bridge . When I establish a ttl connection and run your program using my windows phone, it starts but it doesn’t display anything on the screen until I send a manual key stroke of CTRL+C … After I send CTRL+C , I can see the received characters … How can we solve the problem .?

    • batchloaf says:

      I’m not sure why that would be happening. ComPrinter reads and prints the incoming characters one at a time (i.e. it doesn’t wait for a complete line to arrive before doing an fprintf). I suppose you could add a fflush function call on line 242 to make sure the individual characters are actually being displayed and not just buffered by the console. I think the line you would want (as the new line 242) is:

      fflush(stdout);
      

      Give that a try and see if it fixes the problem.

      Ted

      • Burak says:

        Thanks for your answer … I found a solution with batch programming . I use “type com[portnumber]” command in order to read the com port … Now I’m searching for how to set the data I read into a variable .. ?? Do you have any idea about it ? MY MCU sends 5 bytes of data .. 5 characters actually like “B”,”U”,”R”,”A”,”K” …

  15. Burak says:

    Hi Ted It’s me again🙂

    Is there a chance of adding a termination procedure for the condition of “no more new data received”. So I want my batch script to go on proceeding the new lines ? Normally the program keeps reading when It arrives the batch script line “comprinter.exe” …

    • batchloaf says:

      Hi Burak,

      Do you mean some kind of timeout? As in, if no new data is received for x number of seconds the program exits. Is that what you have in mind?

      Ted

      • Burak says:

        Yes ted exactly .. !

      • Burak says:

        Here is what I do as I said before ,
        The fact is that I will connect to my PC via Telnet , then I want to send some commands to the com port connected to my TTL bridge – MCU … then mcu will interpret these strings and it will communicate with the terminals in my home via 2.4 GHZ nrf24l01 transceiver modules … I’ve taken care of everything except this feedback reading part of the code since it requires pc programming language knowledge .. I can only write some simple scripts using batch commands that’s all .. I wish I can be as good as you are @ c programming ..

  16. Burak says:

    Is it possible to add such a function into the existing comprinter.exe ?

    • batchloaf says:

      Hi Burak,

      I’ve had a quick go at adding functionality like what you suggested to ComPrinter. I’ve compiled the new version, but I don’t have an actual serial device here to test it properly, so I can’t be sure yet it’s working correctly. Perhaps you could try new version for me?

      ComPrinter.exe
      ComPrinter.c

      I’ve added four new options for causing ComPrinter to exit.

      1. Exit after a certain number of characters. For example, to exit after 5 characters,

      ComPrinter /charcount 5
      

      2. Exit after a timeout – i.e. no data received for the specified number of milliseconds. For example, to exit after 2 seconds of no data,

      ComPrinter /timeout 2000
      

      3. Exit when a certain character is received. For example, to exit when the letter ‘x’ is received,

      ComPrinter /endchar x
      

      4. Exit when a certain hex byte is received. For example, to exit when the hex value 0xFF is received,

      ComPrinter /endhex FF
      

      Maybe that’s enough to solve your current problem. Once I’ve had a chance to test this thoroughly myself, I’ll replace the main version on this page with this new version.

      Ted

      • Matti says:

        Would it be possible to add an option to print in hex codes the characters that cannot be written otherwise on the screen. An alternative would be to print all characters in hex codes.

  17. Burak says:

    If timeout makes things more complicated , you can consider applying “just read 5 bytes and terminate the program ” procedure … I hope you aren’t mad at me🙂

  18. Burak says:

    You’re amazing !! That works like a charm !! I’ve been searching for such a code snippet or sth written in batch for almost 5 days … Your code was the closest one to what I desire . But you’ve reworked on it , and it has become just as exactly what I want and what my system requires ..

    I’ll post you a video of the working system if you leave me your e-mail or sth ..

    I APPRECIATE YOU SO MUCH !! THANK YOU BROTHER !!
    I do owe you one ….

    • batchloaf says:

      Hi Burak,

      That’s great – I’m glad to hear you got it working. As it turned out, it only took a few minutes to add the new feature. Hopefully it might be useful to some other users in the future also.

      Ted

  19. Jeff says:

    Is there any chance you could combine serialsend and comprinter such that it starts by optionally sending a message as serialsend does, then optionally waiting for a response before closing, like comprinter does? Nothing I’ve found does that from a command line…

    Thanks

  20. Mariela says:

    Hi,
    Your program has been very useful for my work, thanks. But I have a problem, ComPrinter PRINTS the value and need that the program RETURN the value. I hope you can help me…

    • batchloaf says:

      Hi Mariela,

      I’m not sure I understand your question properly. When I talk about the return value from a console application like ComPrinter, I’m normally referring of the integer (whole number) value that the program returns (i.e. passes back) to the operating system when it ends. The normal convention is that a program returns 0 if it exits normally after successfully completing whatever task it was doing. Conversely, if a program exits due to some unexpected reason which meant it could not complete its task, then it normally returns a positive (non-zero) integer value. What positive integer is returned can provide information about what caused the program to fail.

      Anyway, it sounds like that’s not what you’re talking about at all when you say “return”. If you can explain a bit more about how you’re using ComPrinter, perhaps I can help you channel whatever information it is that you need to wherever you need to send it. Some specific questions:

      • Are you calling ComPrinter from within another program?
      • If so, what language is that program written in?
      • What is the information that ComPrinter is currently printing that you presumably need to do something else with? i.e. Is it a number or text or what?
      • Each time you run ComPrinter, do you need it get one piece of information, or do it over and over again?

      Ted

      • Mariela says:

        Hi,
        I am calling ComPrinter from an aplication in Visual Studio 2010, written in C++ code.
        The information that I need to get is value that display ComPrinter in the console (char c).
        I want to keep reading that value from ComPrinter, to convert it to int and to do an operation with it.
        I am thinking to use /charcount 1, to get a char each time the program is run inside the while loop.
        I hope that I explained better what I need , I will appreciate your support.
        Thank you.

  21. Gleb says:

    Hi I’ve just downloaded ComPrinter, when I open it, it has “Opening Com7 at 2400 baud” written.
    When I try to type in a command its doesn;t respond.
    Do you know what might be wrong?

    • batchloaf says:

      Hi Gleb,

      The purpose of ComPrinter is to print text which is being received from another device via a serial port. When you run ComPrinter, it prints a message to say which port was opened and the baudrate used but after that it just prints whatever is received from the device connected to that serial port. You don’t need to type in any additional commands (and doing so will have no effect). The only thing you might want to type is Ctrl-C to exit from ComPrinter.

      Hope that helps.

      Ted

  22. Feredzhanov says:

    Hi,
    I use your program and it works really good for me. I just have a small problem. Since I use it in a batch file on Windows 8.1 PC, I can’t stop the program with Ctrl+Z (I can do it, if I start it from command, but when running batch it doesn’t work), I couldn’t find any info on it so I decided to ask you if you know what could be causing this? And if it’s possible for a modification to be made for the program to be interrupted with a key from the keyboard instead of a Ctrl+Z combination? Thanks in advance.

    • batchloaf says:

      Hi Feredzhanof,

      The normal key combination to stop the program is Ctrl+C (rather than Ctrl-Z). Have you tried that?

      Ted

      • Feredzhanov says:

        Yes, and it stops your program, but it also wants to stop the whole batch file asking me “Do you want to stop the process (y/n)”. It’s not that big problem for me, but there are other ppl that work with those batch files.

      • batchloaf says:

        Ah, I see what you mean. It’s hard to know what the best solution would be here. There’s probably some way to spawn ComPrinter as a separate process to the batch file and then send a signal (from the batch file) to tell ComPrinter to exit. I’m not quite sure how to do that, but it’s probably possible.

        Ted

      • Feredzhanov says:

        If it’s possible to add a scan for key press during scanning the port, so if a specific key is pressed to stop scanning will be ok. I remember there was such command, but it’s been 10 years since I last wrote something in C.

  23. Nas says:

    Dear Ted,

    Firstly i would like to say thank you and it would be greatly appreciated if you can teach me.

    I have a device which has a serial printer port (DB-9 /RS232). This device can print locally and can connect to external printer (Serial printer which is almost impossible to find nowadays.)

    Here is what i actually wish for.
    Once i press “Print” on my device. I wish the data can appear as txt file on my Computer.

    Once again, Thank you very much and Good Day Sir.🙂

    Regards,
    Nas

  24. tim says:

    you can use terminal…its an awesome rs232 program

    https://sites.google.com/site/terminalbpp/

    • batchloaf says:

      Wow, that looks really cool. The CSV graph feature is something I was thinking of writing myself. They have something similar in the latest Arduino IDE, but I thought a generic serial port one would be handy, so I’m thrilled to see it in this. Thanks Tim!

      Ted

  25. tim says:

    ived been using terminal, with a usb cable and a couple of external parts, to program DS5000T processors for several years. its the best rs232 program ive ever seen

  26. Pingback: Automatic Webcam Tracking | RoboRoBlog

  27. quadko says:

    Thanks for the cool app. I used it to quickly dump some data from a USB hardware random number generator into a file. Just wanted to report it works excellently for grabbing some quick data!

    I’m using a TrueRNG device from ubld.it off this list: https://en.wikipedia.org/wiki/Comparison_of_hardware_random_number_generators

    If you ever felt like upgrading, add my vote also for a convenient “stop after n bytes or seconds” feature for scripting purposes, but it’s been very useful as-is, thank you!

  28. kaworu says:

    Thanks a bunch for this. This is very useful and has allowed me to make a batch file which I can output the response from the serial device immediately after a command is sent to it. I merged your codes for ComPrinter with your SerialSend and added some additional stuff like purging the input/output buffer before sending text etc. I believe it is kinda what Ramesh and Ken requested for.

    • batchloaf says:

      Thanks Kaworu, glad to hear you found this useful. That’s great that you were able to combine ComPrinter and SerialSend like that. Several people have asked me in the past about combining the features of both and I just never found time to do it.

      I don’t think I actually stated it above, but I’m very happy for the ComPrinter and SerialSend code to be available under a GPL license, so in case you’d like to publish your merged version under similar license that’s no problem at all. It sounds like it might be exactly what some of these other commenters have been looking for!

      Ted

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s