Pelles C forum

C language => Expert questions => Topic started by: 0gmios on April 22, 2008, 05:43:24 AM

Title: Comm Port
Post by: 0gmios on April 22, 2008, 05:43:24 AM
Greetings,

I have been using Pelles C with Xp for the last 4 years to interface with electronics via the printer port and an interface card (http://www.ultrasmart.org/CTLplus3_mLogicDS-K2805.html (http://www.ultrasmart.org/CTLplus3_mLogicDS-K2805.html)). We just upgraded to a new USB interface (http://www.starting-point-systems.com/ (http://www.starting-point-systems.com/)) and it is controlled by sending text strings to the comm port (USB).

I have done some searching and found that using the comm port has to be done with asm (which I have not used but happy to learn). I was hoping someone could 'point' (;)) to some code to help me make a function. The function will need to be called with the text as the argument, which will then be sent to the comm port.

Another idea I had was to run a batch file from the C exe. The batch file would contain the relevant communications commands. However, I have no idea how to do this.

Regards,
Title: Re: Comm Port
Post by: Stefan Pendl on April 22, 2008, 07:39:12 AM
The COM port will be handled like an ordinary file on Windows, see the CreateFile API function.
Be sure to suppress the end-of-line characters (CRLF), if the manual for the interface does not say that they are needed.

There is no need for ASM, plain white C will do ;)
Title: Re: Comm Port
Post by: 0gmios on April 22, 2008, 07:51:17 AM
I see API and I am thinking windows API, as in a windows application. I am just going for a simple console application...  ???

Regards,
Title: Re: Comm Port
Post by: Stefan Pendl on April 22, 2008, 08:54:12 AM
There is no difference, if it is a GUI or console application.
You do not need a GUI to use the API functions.

You should be able to use the build-in file functions, since the COM ports are special files, like the file name COM1 will open a connection to COM1.
Title: Re: Comm Port
Post by: 0gmios on April 22, 2008, 10:08:00 AM
I guess I will have to relearn file handling. I haven't done file handling since the day I was shown how...  ;D

At least I have a direction, just need to make sure I call the file COM3, since that is the comm port it was assigned.

Now were is my K&R...

Regards,
Title: Re: Comm Port
Post by: DMac on April 22, 2008, 05:20:36 PM
Have you considered using VISA?

I have used both Agilent VISA and NI VISA and find that they make IO fairly easy.

I am using VISA now for direct USB communications and also for RS232.  The Agilent Developers Network has several C based examples implementing VISA and you might get going a bit faster than using the Windows API.

I started working on a Windows API wrapper for RS232 in my spare time but havn't been able to get to it in a while.

David M.
Title: Re: Comm Port
Post by: TimoVJL on April 22, 2008, 08:00:24 PM
Open COM port something like this:
Code: [Select]
hCom = OpenComPort("COM1");
Code: [Select]
HANDLE OpenComPort(char *szPort)
{
HWND hWnd;
HANDLE hCom;
DCB dcb;
COMMTIMEOUTS cto;
BOOL bOk;
char szTmp[80];

if (!szPort) return 0;
hWnd = hDlg;

hCom = CreateFile(szPort, GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
if ( hCom == (HANDLE)-1 ) {
wsprintf(szTmp, "Error opening port %s", szPort);
MessageBox( hWnd, szTmp, szAppName, MB_OK|MB_ICONERROR );
return 0;
}
bOk = GetCommState(hCom, &dcb);
if ( !bOk ) {
CloseHandle(hCom);
wsprintf(szTmp, "Error reading port %s state", szPort);
MessageBox( hWnd, szTmp, szAppName, MB_OK|MB_ICONERROR );
return 0;
}
dcb.BaudRate = 9600;
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcb.fRtsControl = RTS_CONTROL_ENABLE;
bOk = SetCommState(hCom, &dcb);
if ( !bOk ) {
CloseHandle(hCom);
wsprintf(szTmp, "Error writing port %s state", szPort);
MessageBox( hWnd, szTmp, szAppName, MB_OK|MB_ICONERROR );
return 0;
}
cto.ReadIntervalTimeout = 100;
cto.ReadTotalTimeoutMultiplier = 10;
cto.ReadTotalTimeoutConstant = 1000;
cto.WriteTotalTimeoutMultiplier = 500;
cto.WriteTotalTimeoutConstant = 1000;
bOk = SetCommTimeouts(hCom, &cto);
return hCom;
}

and use ReadFile and WriteFile functions.

finally close port like this:
Code: [Select]
if (hCom) CloseHandle(hCom);
Title: Re: Comm Port
Post by: 0gmios on April 23, 2008, 02:51:10 AM
Have you considered using VISA?

I have used both Agilent VISA and NI VISA and find that they make IO fairly easy.

I am using VISA now for direct USB communications and also for RS232.  The Agilent Developers Network has several C based examples implementing VISA and you might get going a bit faster than using the Windows API.

Hmm, sounds interesting. More information please...

Thanks,
Title: Re: Comm Port
Post by: 0gmios on April 23, 2008, 03:09:41 AM
Open COM port something like this:

At the risk of sounding foolish, I would like to say that dcb and cto appear to be objects... As in C++, not C...  ???

Then again, I didn't say that I want to write a C console program, so my bad.

Not that I am opposed to C++ just found a good book (like K&R) for it.

Regards,
Title: Re: Comm Port
Post by: DMac on April 23, 2008, 04:04:43 AM
Quote
Hmm, sounds interesting. More information please...

Here are some links:

C code samples:
http://adn.tm.agilent.com/index.cgi?CONTENT_ID=2908 (http://adn.tm.agilent.com/index.cgi?CONTENT_ID=2908)

A good article: (C#.NET but VISA is C based and so you can see the technique)
http://www.ddj.com/windows/184405902 (http://www.ddj.com/windows/184405902)

The download:
http://joule.ni.com/nidu/cds/fn/p/sn/n23:3.1637.1640/lang/en (http://joule.ni.com/nidu/cds/fn/p/sn/n23:3.1637.1640/lang/en)

This includes NI SPY which allows you to view input / output bus activity of devices making use of VISA.

The Manuals:
http://digital.ni.com/manuals.nsf/websearch/266526277DFF74F786256ADC0065C50C (http://digital.ni.com/manuals.nsf/websearch/266526277DFF74F786256ADC0065C50C)
http://digital.ni.com/manuals.nsf/websearch/87E52268CF9ACCEE86256D0F006E860D (http://digital.ni.com/manuals.nsf/websearch/87E52268CF9ACCEE86256D0F006E860D)

Regards,
DMac
Title: Re: Comm Port
Post by: Stefan Pendl on April 23, 2008, 04:18:04 AM
At the risk of sounding foolish, I would like to say that dcb and cto appear to be objects... As in C++, not C...  ???
They are structs and not objects.
You may want to spend some time on MSDN checking out the definitions of the Windows API functions used in the example.

Since Pelles C is an IDE for writing Windows applications there is no way around MSDN.
Title: Re: Comm Port
Post by: 0gmios on April 23, 2008, 05:31:46 AM
You may want to spend some time on MSDN checking out the definitions of the Windows API functions used in the example.

Since Pelles C is an IDE for writing Windows applications there is no way around MSDN.

 :'(
Title: Re: Comm Port
Post by: 0gmios on April 23, 2008, 08:21:44 AM
Okay, windows API and MSDN it is... I just ordered "The Windows Serial Port Programming Handbook" as a reference (which I am reading through google books). That way I can get my hands on some complete example code.

I don't do well with snippits. For example,

Code: [Select]
hCom = OpenComPort("COM1");
what is type is hCom...

Hopefully the book will help.

Regards,

PS The VISA download link doesn't work for me, I get a failure message...
Title: Re: Comm Port
Post by: TimoVJL on April 23, 2008, 10:40:48 AM
Quote
what is type is hCom...
HANDLE
OpenComPort() is example home made function for opening COM port, not Win32 API function.
Example code was below that usage example.
Code: [Select]
HANDLE OpenComPort(char *szPort);
Title: Re: Comm Port
Post by: DMac on April 23, 2008, 05:10:42 PM
Quote
PS The VISA download link doesn't work for me, I get a failure message...

Try this:
http://ftp.ni.com/support/softlib/visa/NI-VISA/4.3/win32/visa430full.exe (http://ftp.ni.com/support/softlib/visa/NI-VISA/4.3/win32/visa430full.exe)
Title: Re: Comm Port
Post by: 0gmios on April 23, 2008, 06:46:16 PM
HANDLE

HANDLE is not recognised when I use it as a type...

Regards,
Title: Re: Comm Port
Post by: 0gmios on April 23, 2008, 06:47:00 PM
Try this:
http://ftp.ni.com/support/softlib/visa/NI-VISA/4.3/win32/visa430full.exe (http://ftp.ni.com/support/softlib/visa/NI-VISA/4.3/win32/visa430full.exe)

Thanks,
Title: Re: Comm Port
Post by: Stefan Pendl on April 23, 2008, 10:00:33 PM
HANDLE is not recognised when I use it as a type...
Did you use
Code: [Select]
#include <windows.h>  ???
Title: Re: Comm Port
Post by: 0gmios on April 24, 2008, 04:07:01 AM

Did you use
Code: [Select]
#include <windows.h>  ???


No. I have never had to do anything that has included windows.h (didn't even know it existed).

Thanks, I will have a look at the code above again

Regards,
Title: Re: Comm Port
Post by: 0gmios on April 24, 2008, 04:13:10 AM
Okay, just by including windows.h I got over 100 errors, and if that wasn't bad enought it insulted me saying "please improve yourself"  :'(

It also says "If you are compiling a Windows program: make sure you use the /Ze option!"

How do I do this?

Regards,
Title: Re: Comm Port
Post by: 0gmios on April 24, 2008, 06:43:42 AM
Okay, just by including windows.h I got over 100 errors, and if that wasn't bad enought it insulted me saying "please improve yourself"  :'(

It also says "If you are compiling a Windows program: make sure you use the /Ze option!"

How do I do this?

I found it... I wasn't clicking the compiler tab in project options... Then there it was, a simple check box... Fool!
Title: Re: Comm Port
Post by: 0gmios on April 24, 2008, 11:42:17 AM
I think it is working, but I am having some security issues trying to access the port (I need to test on another machine at home). The new machines we are using won't even let me access the printer port with _outp and _inp. I use userport (http://www.writelog.com/support/lpt_port_support_on_windows_nt.htm (http://www.writelog.com/support/lpt_port_support_on_windows_nt.htm)) to grant direct access to the ports, its just not working on the current machines...  >:(

I also did this to send text to the serial port. But I cant receive text...
Code: [Select]
#include <stdio.h>
#include <stdlib.h>

void main(void)
{
    int menuoption = 0;

    for(;;) //forever
    {
        system("cls");
        printf (" 1  Turn LED on \n");
        printf (" 2  Turn LED off \n");
        printf (" 3  Exit \n");
        printf (" Select Option and RETURN \n");

        scanf("%d", &menuoption);

        if (menuoption == 1)
            system("echo led on > com3");
        if (menuoption == 2)
            system("echo led off > com3");
        if (menuoption == 3)
            break;
    }
}
The system command was quite helpful. I can control all of the outputs using this, but like I said I cannot receive text with it to read the inputs  :(

Regards,
Title: Re: Comm Port
Post by: TimoVJL on April 24, 2008, 07:32:08 PM
Example converted to use Win32 API.
It doesn't send CR+LF.

From here you found virtual com port.
http://com0com.sourceforge.net/ (http://com0com.sourceforge.net/)
Title: Re: Comm Port
Post by: 0gmios on April 25, 2008, 06:20:25 AM
Example converted to use Win32 API.
It doesn't send CR+LF.

Have no idea what that means.

But thanks for the zip file. Unfortunitly it is a public holiday here in Australia, so work is closed, and I don't have a serial port interface at home to test  :(

From here you found virtual com port.
http://com0com.sourceforge.net/ (http://com0com.sourceforge.net/)

Thanks, I will have a look at this.

Regards,

P.S. What is with the...
Code: [Select]
#define WIN32_LEAN_AND_MEAN
Title: Re: Comm Port
Post by: TimoVJL on April 25, 2008, 07:07:07 AM
Quote
Example converted to use Win32 API.
It doesn't send CR+LF.
It means that you have to send them ("\r\n") if linefeed is needed for device.

With com0com you can open virtually connected port (CNCB0) with HyperTerminal to see what you application send to CNCA0.
Open it as "\\\\.\\CNCA0".

Paired ports are CNCA0 <-> CNCB0 by default but those names can be changed to COMx with com0com setup program.

http://com0com.sourceforge.net/doc/UsingCom0com.pdf (http://com0com.sourceforge.net/doc/UsingCom0com.pdf)
Title: Re: Comm Port
Post by: 0gmios on April 28, 2008, 03:21:59 AM
Yeah gees thanks timovjl, that's great I just wasted a $100 on a book with source code which I don't need because your tiny piece of code works so well  ;D

Thanks. I am going through a winAPI tutorial from http://forum.pellesc.de/index.php?topic=2105.0 (http://forum.pellesc.de/index.php?topic=2105.0) and MSDN to try and understand all the components of the code.

The text book will still be a useful resource for leaning more about all of this, so I don't actually think that it is a waste of money.

Regards,
Title: Re: Comm Port
Post by: 0gmios on April 28, 2008, 08:35:22 AM
It means that you have to send them ("\r\n") if linefeed is needed for device.

BTW, yes I need to include either \n or \r for the command to work (hence I added an extra byte to each command - led on 6 bytes, led on \n, 7 bytes).

I recommend you add your code to http://forum.pellesc.de/index.php?topic=1272.0 (http://forum.pellesc.de/index.php?topic=1272.0). So other people get the same benifit I did. I would like to add it, but it is your code...

Regards,

Graham