Hi All,
I am very new to linux ( ~2 weeks old ) and I hope this is the right forum for my question.
I am trying to port some serial com port code over from Windows XP to Linux. Currently,
I am having trouble reading data from my serial port after writing some data to com port
I do a #cat /proc/tty/driver/serial to display COM port info after running my code.
serinfo:1.0 driver revision:
0: uart:16550A port:000003F8 irq:4 tx:114 rx:0 RTS|CTS|DTR
1: uart:unknown port:000002F8 irq:3
2: uart:unknown port:000003E8 irq:4
3: uart:unknown port:000002E8 irq:3
I assume tx:114 represents the number of bytes transmitted and rx:0 is the number of bytes received? Anyways, it looks like no data is coming back.
The setup is DTE-DCE where DCE is a data acquistion hardware connected to PCI slot on same computer and using serial com port for communication.
Questions:
1) Can someone show me the proper way to open serial com port for Linux Suse 10.1. I would like to elminate the possiblity that I have not opened and configured the serial port correctly. I've been playing around with the settings but no luck in fixing my problem.
2) I've enabled hardware flow-control. Should I be manually setting and un-setting the RTS/CTS signal using ioctl function in my code or should linux OS take care of that?
RTS/CTS signals:
[HTML]
DATA --[(DTE)QUERY DATA]--[(DCE)RESPONSE]--
________________
RTS __/ \___________________
___________________ ___
CTS \_______________/
[/HTML]
3) Does anyone know of any tools/tricks so I can check my COM port is working properly?
Any insight would be appreciated.
Thanks,
Geoff
My code (simplified):
Code:
main()
{
BYTE inputCMD[7] = { 0x22, 0x23,0x34,0x33,0x02,0x62,0x03 };
BYTE outputRES[10];
MyCOM comport;
if(comport.OpenPort())
{
comport.SendData(inputCMD,7)
usleep(10000000);
comport.ReceiveData(outputRES,10,&byteread);
}
else
{
printf("Unable to open port");
}
}
bool MyCOM::OpenPort()
{
//Open port
m_fdComPort = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY);
// save current port settings
tcgetattr(m_fdComPort,&m_origtio);
BAUD = B9600;
DATABITS = CS8;
STOPBITS = 1;
PARITYON = 0;
PARITY = 0;
memset(&m_newtio,0,sizeof(m_newtio));
cfsetispeed(&m_newtio,BAUD);
cfsetospeed(&m_newtio,BAUD);
fcntl(m_fdComPort,F_SETFL,FNDELAY);
//Trying to configure character and parity settings for 8N1
m_newtio.c_cflag &= ~PARENB;
m_newtio.c_cflag &= ~CSTOPB;
m_newtio.c_cflag &= ~CSIZE;
m_newtio.c_cflag |= DATABITS;
m_newtio.c_cflag |= CRTSCTS;
m_newtio.c_cflag |= CLOCAL;
m_newtio.c_cflag |= CREAD;
m_newtio.c_iflag = IGNPAR;
m_newtio.c_iflag &= ~(BRKINT|ICRNL|INPCK|ISTRIP|IXON);
m_newtio.c_oflag &= ~OPOST;
m_newtio.c_lflag &= ~(ISIG|ECHO|ICANON|IEXTEN);
m_newtio.c_cc[VMIN]=1;
m_newtio.c_cc[VTIME]=0;
tcsetattr(m_fdComPort,TCSAFLUSH,&m_newtio);
return true;
}
// Sends packet through communication port
bool MyCOM::SendData
(
BYTE* packet, //< The pointer to the packet to be transmitted
int nBytes //< Size of packet (in bytes).
)
{
int bytesWritten = 0; // number of bytes written to the firware
bool success = false; // CTS is not yet de-asserted yet
unsigned long timeout = 0;
bool bCTSStatus = false;
// Should Wait until CTS gets asserted (up to 10 seconds)
do
{
timeout++;
bCTSStatus = GetCTS();
if(bCTSStatus) break;
if(TIMEOUT_LISTEN < timeout)
printf("\nTIMEOUT waiting for CTS asserted\n");
}
while(timeout < TIMEOUT_LISTEN);
if(bCTSStatus)
{
bytesWritten = write(m_fdComPort,packet,nBytes);
if(0 < bytesWritten)
{
printf("\nBytes written = %d\n",bytesWritten);
success = true;
}
else
{
printf("\nError writting bytes\n");
}
}
else
{
printf("ERROR: CTS line is low - cannot send packet.");
printf(" Check Connection to Power Manager.");
}
return success;
}
#define PRE_TIMEOUT 5000
#define POST_TIMEOUT 100
// Reads data through communication port
// NOTE: I copied the big while loop from some sample on line. Its suppose loop until I get some info back from serial port or timeout
bool MyCOM::ReceiveData
(BYTE* packet,
UINT16 expectedSize,
DWORD *nBytesRead)
{
int iBytesRead=0;
int iByteCtr=0;
int cnt =0;
unsigned int offset=0;
struct timespec tv;
int timerflag =0;
tv.tv_sec = 0;
tv.tv_nsec = 100000; //100 ms
while(1)
{
if(expectedSize < 1)
{
break;
}
//pre data timer
if(!timerflag &&
cnt >= PRE_TIMEOUT/(tv.tv_nsec/1000))
{
printf("\n!!!timeout while reading\n");
break;
}
//post datatimer
if(timerflag && cnt >= POST_TIMEOUT/(tv.tv_nsec/1000))
{
printf("\n!!!timeout while reading\n");
break;
}
iBytesRead = read(m_fdComPort,packet+offset,1);
if(0 < (int)iBytesRead)
{
iByteCtr += iBytesRead;
timerflag = 1;
cnt=0;
--expectedSize;
++offset;
continue;
}
else
{
}
++cnt;
nanosleep(&tv,NULL);
}
*nBytesRead = (DWORD)iByteCtr;
return true;
}