Low Level Terminal I/O
- Hi,
I am trying to read and write from a serial port.
I found functions such as _open() and _close() and was successful in opening and closing the port.
I couldn't find any functions for setting terminal parameters such as baudrate, parity,databits at the low level.
Can I set the parameters using DCB structure? or are there different functions for low level?
Also, SetCommState() takes HANDLE as a parameter.
So I am in search of functions which would take and return INT as a parameter instead of a HANDLE.
Any documentation,links etc etc??
回答
- You'll need to get off the _open() bandwagon, the HANDLE thingy is what you need to make it work. Brian gave you a link to the kind of code you need. If this kind of API programming doesn't spin your propeller, consider writing your program in managed code. The System::IO::Ports::SerialPort class has very friendly properties that you can set in the designer to get the correct baudrate (etc) settings. Using C# makes that easier yet.
Hans Passant.- 回答としてマークNancy ShaoMSFT, モデレータ2009年7月9日 6:35
すべての返信
- There are several good coding examples at www.codeproject.com. Here is one of them.
_open and _close are no longer low-level. If you use CreateFile, your problems are solved. (Your need to use integers is based on the return from _open, anyway.) There never were any low-level functions for COM Ports. You set those things up in the UART registers directly using C I/O, which you can no longer do. The only low-level support ever afforded the serial port was a couple of useless BIOS services (Int14, iirc), the AUX/COM devices, and some DOS utilities added in DOS 5, or so. Not much use to you, plus...you can't get there from here, unless you want to write a console app, but they are supremely disappointing to use when compared to the Win32 API, or even .NET, in fact.
The DCB is the way to go for setting those parameters, and that article Brian Muth has linked you to is a good resource, in my opinion.
The SerialPort class in .NET is a very complete API for RS-232 comms, but it is hardly low-level, and comes with a lot of other stuff you probably don't want in the first place.- Your need to use integers is based on the return from _open, anyway.
Nope,My need to use integers is because the code at the top-level takes integers as parameters.
I am already able to do the terminal i/o using the CreateFile function, but don't want the handle thing.
I tried to set the DCB structure and it doesn't work in my case.#include <io.h> #include <windows.h> #include <stdio.h> #include <fcntl.h> int i; int fd; DCB parameters; char *data = "Hello"; void main(void){ fd = _open("COM4",_O_RDWR); fprintf(stderr,"Opened COM port\n%d\n",fd); parameters.BaudRate = 9600; parameters.ByteSize = 7; parameters.Parity = EVENPARITY; parameters.StopBits = ONESTOPBIT; for(i=0;i<100;i++) _write(fd,data,10);
Actually I am porting an application from uclinux where the top layer specifies integer because the bottom layer serial i/o is using file descriptor which returns an integer.
All I want to do is change the serial i/o file. - One more thing,
This code opens the port,returns a value for fd, but doesn't transmit.Even if it transmits, I'm not able to see it on hyperterminal.
Maybe because the baudrate,databits and parity settings are not taking place???? SetDefalutCommConfig might help you. It uses the port name (like "COM1") instead of a handle.
- You'll need to get off the _open() bandwagon, the HANDLE thingy is what you need to make it work. Brian gave you a link to the kind of code you need. If this kind of API programming doesn't spin your propeller, consider writing your program in managed code. The System::IO::Ports::SerialPort class has very friendly properties that you can set in the designer to get the correct baudrate (etc) settings. Using C# makes that easier yet.
Hans Passant.- 回答としてマークNancy ShaoMSFT, モデレータ2009年7月9日 6:35
Okay, your need to use integers is based on your insistence on using low-level I/O on a device that has no such low-level I/O support. Semantics aside, the COM port is a HANDLE based asset now...you are trying to put a 16-bit concept into a 32/64-bit OS, and I am trying to tell you that it won't work as well as the code you've been linked to.
You will not be able to use SetCommState without a HANDLE from CreateFile, so really this discussion is pointless, as the only other ways are to set the registers in the UART directly, and the BIOS Int14 services.
Windows is not Linux, and it no longer wants to support low-level I/O because that is a platform dependent concept, and also a security risk. The fact that there is an underscore prepended to the name of the function tells me that the implementation is OS specific, and an extension to C...not a standard component. To expect it to work the same in Linux and Windows is not realistic. The reason, I've already belabored above...the BIOS itself provides little in the way of serial I/O support, so C has scant little to work with.
I still do not understand why that means you have to use some other 32-bit integer value. When you open a file using _open, you get an integer that is 32-bits wide. When you open a file using CreateFile, you get a handle that is 32-bits wide. While they are not the same types, they are the same size, and it is not as onerous to change some variables in the main app as it would be to fight Windows on this issue. Windows has all the same functions, appropriately named...Write, Read, CloseHandle (Okay, that one is a little different.)
That's my two cents worth.
Cheers.- You will not be able to use SetCommState without a HANDLE from CreateFile
Precisely. That's why I wanted to know if there are any other functions which take integer as an argument.
While they are not the same types, they are the same size, and it is not as onerous to change some variables in the main app as it would be to fight Windows on this issue.
I am not fighting windows. I just wanted to know my options.
Maybe this could help.....http://www.codeproject.com/KB/files/handles.aspx
ughhh......now I'll have to change the variables.

