galneweinhaw
asked on
Serial Port Communication
Hello,
I am building a program that is going to communicate with an actuator controller via "command strings" over the 9 pin serial port. I am using the CreateFile, ReadFile, and WriteFile functions. Here are the specifications of the controller
Electrical Specifications EIA RS485
Synchronization Method Asynchronous
Connection Method Differential Line
Connector 6 pole modular
Strings Fromat ASCII
Baud Rate 38.4kbps (Standard). 9.6kbps, 19.2kbps (Can be set as a factory default)
Data length Eight bits
Stop bit One bit
Parity check None
Communication Method Half-Duplex
Here is my implementation so far:
CString m_sComPort;
m_sComPort = "Com1";
m_hCom = CreateFile (m_sComPort, // Port Name (Unicode compatible)
GENERIC_READ | GENERIC_WRITE, // Open for Read-Write
0, // COM port cannot be shared
NULL, // Always NULL for Windows CE
OPEN_EXISTING, // For communication resource
0, // Non-overlapped operation only
NULL); // Always NULL for Windows CE
COMMTIMEOUTS ct;
ct.ReadIntervalTimeout = 100;
ct.ReadTotalTimeoutMultipl ier = 10;
ct.ReadTotalTimeoutConstan t = 10;
ct.WriteTotalTimeoutMultip lier = 10;
ct.WriteTotalTimeoutConsta nt = 1000;
if(!SetCommTimeouts(m_hCom , &ct))
{
MessageBox(NULL,(_T("Setti ng comm. timeouts.")), (_T("Error")), MB_OK);
DWORD tmp = GetLastError();
return false;
}
DCB dcb;
dcb.DCBlength = sizeof(DCB);
if(!GetCommState(m_hCom, &dcb))
{
MessageBox(NULL,(_T("Getti ng Comms. State.")), (_T("Error")), MB_OK);
return false;
}
dcb.BaudRate = 9600; // set baud rate to what we want
dcb.fOutxCtsFlow = TRUE;
dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcb.fOutxDsrFlow = FALSE;
dcb.fOutX = FALSE; // no XON/XOFF control
dcb.fInX = FALSE;
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
if(!SetCommState(m_hCom, &dcb))
{
MessageBox(NULL,(_T("Setti ng Comms. State.")), (_T("Error")), MB_OK);
return false;
}
return true;
My other functions are just the ReadFile and WriteFile using the 16 character commands.
example -> WriteFile(m_hCom, "02BaFFFF167A000603",16,&i BytesWritt en,NULL);
Breakdown of Example According to Controller Manual:
STX 02 Start Transmission Character
Axis No. B (HEX) Axis 11(decimal)
Command a Character for command
Position Data FFFF167A Position in HEX as converted by algorithm
Zero's 00 String Filler (string must contain 16 characters)
BCC 06 Block Check Calculation - Value of String (HEX)
ETX 03 End Transmission Character
Nothing happens when I run this code, and in the debug window I notice that the BytesWritten data remains at '0', indicating to me that nothing is being written to the controller.
I have also tried using the ActiveX Controller "Microsoft Communications" and have had equal bad luck. I would prefer using the ReadFile and WriteFile functions though. But a solution is a solution.
-Cheers
I am building a program that is going to communicate with an actuator controller via "command strings" over the 9 pin serial port. I am using the CreateFile, ReadFile, and WriteFile functions. Here are the specifications of the controller
Electrical Specifications EIA RS485
Synchronization Method Asynchronous
Connection Method Differential Line
Connector 6 pole modular
Strings Fromat ASCII
Baud Rate 38.4kbps (Standard). 9.6kbps, 19.2kbps (Can be set as a factory default)
Data length Eight bits
Stop bit One bit
Parity check None
Communication Method Half-Duplex
Here is my implementation so far:
CString m_sComPort;
m_sComPort = "Com1";
m_hCom = CreateFile (m_sComPort, // Port Name (Unicode compatible)
GENERIC_READ | GENERIC_WRITE, // Open for Read-Write
0, // COM port cannot be shared
NULL, // Always NULL for Windows CE
OPEN_EXISTING, // For communication resource
0, // Non-overlapped operation only
NULL); // Always NULL for Windows CE
COMMTIMEOUTS ct;
ct.ReadIntervalTimeout = 100;
ct.ReadTotalTimeoutMultipl
ct.ReadTotalTimeoutConstan
ct.WriteTotalTimeoutMultip
ct.WriteTotalTimeoutConsta
if(!SetCommTimeouts(m_hCom
{
MessageBox(NULL,(_T("Setti
DWORD tmp = GetLastError();
return false;
}
DCB dcb;
dcb.DCBlength = sizeof(DCB);
if(!GetCommState(m_hCom, &dcb))
{
MessageBox(NULL,(_T("Getti
return false;
}
dcb.BaudRate = 9600; // set baud rate to what we want
dcb.fOutxCtsFlow = TRUE;
dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcb.fOutxDsrFlow = FALSE;
dcb.fOutX = FALSE; // no XON/XOFF control
dcb.fInX = FALSE;
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
if(!SetCommState(m_hCom, &dcb))
{
MessageBox(NULL,(_T("Setti
return false;
}
return true;
My other functions are just the ReadFile and WriteFile using the 16 character commands.
example -> WriteFile(m_hCom, "02BaFFFF167A000603",16,&i
Breakdown of Example According to Controller Manual:
STX 02 Start Transmission Character
Axis No. B (HEX) Axis 11(decimal)
Command a Character for command
Position Data FFFF167A Position in HEX as converted by algorithm
Zero's 00 String Filler (string must contain 16 characters)
BCC 06 Block Check Calculation - Value of String (HEX)
ETX 03 End Transmission Character
Nothing happens when I run this code, and in the debug window I notice that the BytesWritten data remains at '0', indicating to me that nothing is being written to the controller.
I have also tried using the ActiveX Controller "Microsoft Communications" and have had equal bad luck. I would prefer using the ReadFile and WriteFile functions though. But a solution is a solution.
-Cheers
>>Nothing happens when I run this code, and in the debug window I notice that the BytesWritten data remains at '0'
Check if 'WriteFile()' returns 'FALSE' and evaluate 'GetLastError()' in this case.
Check if 'WriteFile()' returns 'FALSE' and evaluate 'GetLastError()' in this case.
ASKER
When I call GetLastError(),
it returns a 6
which means there is an INVALID HANDLE,
More to this, when I try to shut down the program, there is a first chance exception talking about an Invalid handle
it returns a 6
which means there is an INVALID HANDLE,
More to this, when I try to shut down the program, there is a first chance exception talking about an Invalid handle
So, have you verified that your handle is valid? E.g.
m_hCom = CreateFile (...);
if (!m_hCom) {
dwError = GetLastError();
}
What port name are you using with 'CreateFile()'?
m_hCom = CreateFile (...);
if (!m_hCom) {
dwError = GetLastError();
}
What port name are you using with 'CreateFile()'?
BTW, according to the docs, there's a suble little difference for CE, such as the name has to be 'COM1:' instead of 'COM1' - NOTE the trailing colon:
http://msdn.microsoft.com/library/en-us/fileio/fs/createfile.asp states "The CreateFile function can create a handle to a communications resource, such as the serial port COM1"
http://msdn.microsoft.com/library/en-us/wceobjst/html/cerefCreateFile.asp says "When lpFileName points to a COM port to open, you must include a colon after the name. For example, specify COM1: to open that port. When using IrCOMM, specify COM3:. "
http://msdn.microsoft.com/library/en-us/fileio/fs/createfile.asp states "The CreateFile function can create a handle to a communications resource, such as the serial port COM1"
http://msdn.microsoft.com/library/en-us/wceobjst/html/cerefCreateFile.asp says "When lpFileName points to a COM port to open, you must include a colon after the name. For example, specify COM1: to open that port. When using IrCOMM, specify COM3:. "
ASKER
Okay just to clarify, I am working on with Visual Studios 6.0, on an Windows XP computer. I pulled that code from a website (they are not my comments) sorry for the miscommunication.
I have fixed (at least for testing purposes) the invalid handle. It know does not create any errors, but still the string format does not seem to be valid, for the controller still does nothing
I have fixed (at least for testing purposes) the invalid handle. It know does not create any errors, but still the string format does not seem to be valid, for the controller still does nothing
Are you sure about the DCB settings? I'd suggest to
DCB dcb;
dcb.DCBlength = sizeof(DCB);
if(!GetCommState(m_hCom, &dcb))
{
MessageBox(NULL,(_T("Getti ng Comms. State.")), (_T("Error")), MB_OK);
return false;
}
// set that according to your specs
BuildCommDCB("baud=9600 parity=N data=8 stop=1", &dcb);
if(!SetCommState(m_hCom, &dcb))
{
MessageBox(NULL,(_T("Setti ng Comms. State.")), (_T("Error")), MB_OK);
return false;
}
Apart from that, according to your specs, you'll need to set ETX at the end of the string, e.g.
"02BaFFFF167A000006X\003"
The '\003' is the escape sequnce for ETX, the 'X' represents the BCC value that *you* have to calculate.
return true;
DCB dcb;
dcb.DCBlength = sizeof(DCB);
if(!GetCommState(m_hCom, &dcb))
{
MessageBox(NULL,(_T("Getti
return false;
}
// set that according to your specs
BuildCommDCB("baud=9600 parity=N data=8 stop=1", &dcb);
if(!SetCommState(m_hCom, &dcb))
{
MessageBox(NULL,(_T("Setti
return false;
}
Apart from that, according to your specs, you'll need to set ETX at the end of the string, e.g.
"02BaFFFF167A000006X\003"
The '\003' is the escape sequnce for ETX, the 'X' represents the BCC value that *you* have to calculate.
return true;
ASKER
Could it possibly be that I'm setting the incorrect amount of memory (currently 16 bytes) in the WriteFile function? I tried the above and there is no progress.
Could it be an improper format? Should I send you the "serial protocol manual."
Could it be an improper format? Should I send you the "serial protocol manual."
>>Could it be an improper format?
That's what I tried to point out - according to the table you posted above, the last char has to be 0x03 (and not the character '3') which I corrected above. But, I don't know how to calculate the BCC byte...
That's what I tried to point out - according to the table you posted above, the last char has to be 0x03 (and not the character '3') which I corrected above. But, I don't know how to calculate the BCC byte...
ASKER
Here is information provided in the manual regarding the BCC byte, let me know if any more info will be of use
BCC:
Two characters ’00-FF’ showing hexadecimal number digits for block check characters. It is calculated by using the 12 data characters (excluding STX, ETX and BCC). It’s calculated by taking last 2 characters of the one's complement of the sum of the ASCII codes of those 12 characters.
Example of calculating BCC
[STX]1a1234567800[BCC][ETX ]
First, add all ASCII codes for the 12 data characters:
sum = 31H+61H+31H+32H+33H+34H+35 H+36H+37H+ 38H+30H+30 H = 296H
Second, take the last 2 characters of the 1’s complement:
[BCC] = "6A"
BCC:
Two characters ’00-FF’ showing hexadecimal number digits for block check characters. It is calculated by using the 12 data characters (excluding STX, ETX and BCC). It’s calculated by taking last 2 characters of the one's complement of the sum of the ASCII codes of those 12 characters.
Example of calculating BCC
[STX]1a1234567800[BCC][ETX
First, add all ASCII codes for the 12 data characters:
sum = 31H+61H+31H+32H+33H+34H+35
Second, take the last 2 characters of the 1’s complement:
[BCC] = "6A"
Hello,
Insted of Read/Write to file.... directly send data to com port....
http://sourceforge.net/projects/comport/ (this is in pascal.....)
Rgds
Insted of Read/Write to file.... directly send data to com port....
http://sourceforge.net/projects/comport/ (this is in pascal.....)
Rgds
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thank you for the help on the BCC bit, I haven't gotten there yet because I still can't communicate with the controller. But thank you for the assistance.
I don't know if it means anything, but the manual seems to want the command strings in hexadecimal ASCII values. And when I look at the
char acCmd[] = "\002BaFFFF167A0006X\003" value in Debug mode. It does not seem to match up, for instance
the manual says '0' should have a value of '30', whereas the actual value for '0' in the program is '48'
could this be a problem
I don't know if it means anything, but the manual seems to want the command strings in hexadecimal ASCII values. And when I look at the
char acCmd[] = "\002BaFFFF167A0006X\003" value in Debug mode. It does not seem to match up, for instance
the manual says '0' should have a value of '30', whereas the actual value for '0' in the program is '48'
could this be a problem
>>the manual says '0' should have a value of '30'
Um which '0' are you referring to?
Um which '0' are you referring to?
ASKER
0 (Zero the number)
Ah, now I got you - that's OK, '48' is the ASCII code for '0'. BTW, have to correct myself, the command string should be
"\002BaFFFF167A0006\003"
"\002BaFFFF167A0006\003"
ASKER
Its over, the actuator is going back to the company, after grinding the tech support for 3 days, I got talking to their communications "expert" and they told me I would be crazy to program it in VC++ 6.0, saying that it would take over a 1000 lines of code (don't ask why, cause he didn't know). Apparently it is easier to program it in VB, but I would still have to know the "handshake procedure," which they were unsure of. After downloading a trail version of a com spy and turning on their software, there was a ton going on that was way out of the scope of the documentation they gave me.
Thus, this horse is dead, and there is no sense flogging it. If they are not going to tell me the command procedure then its all for nothing.
jkr, thanks for sticking with this train wreck, all points and props go to you........
Thus, this horse is dead, and there is no sense flogging it. If they are not going to tell me the command procedure then its all for nothing.
jkr, thanks for sticking with this train wreck, all points and props go to you........
I notice in your comments here that you state Windows CE...
m_hCom = CreateFile (m_sComPort, // Port Name (Unicode compatible)
GENERIC_READ | GENERIC_WRITE, // Open for Read-Write
0, // COM port cannot be shared
NULL, // Always NULL for Windows CE
OPEN_EXISTING, // For communication resource
0, // Non-overlapped operation only
NULL); // Always NULL for Windows CE
Is this a CE project or a Win32 project?
IF it is a CE project are you running your code on the emulator or on a device?
Jeremy