LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Serial Receive Problem (https://www.linuxquestions.org/questions/programming-9/serial-receive-problem-687633/)

nasr-noor 12-02-2008 12:20 AM

Serial Receive Problem
 
Hi,
I have 2 PC one has Windows and send data frame on serial port, and another is fedora 9 and receive data.

I send integer value(Not ASCII code),for example 00000000(Not 48) for number 0.

problem:
when I send 00000000,00001101,00010001,00010011 for 0,13,17,19 on linux I receive NULL or wrong characters on fedora, but when I receive them on windows its ok.

do you know whats the problem?

theNbomr 12-02-2008 08:09 AM

What are you using to read the serial data? If it is some program that you wrote, show us the relevant code fragments.

--- rod.

nasr-noor 12-07-2008 04:19 AM

Here is some of code :
//**************************************
//****** Receive Code in Linux *********
bool setSerial(char* portName,int parity)
{
struct termios options;
//open port
portNumber = open(portName,O_RDWR | O_NOCTTY | O_NDELAY);
if(portNumber == -1)
printf("port openning error\n");
//get the current setting of the serial port
tcgetattr(portNumber,&options);
//---------set the setting
fcntl(portNumber, F_SETFL, FNDELAY);
options.c_lflag &= ~(ICANON | ECHO | ISIG);
cfsetispeed(&options,B9600);
cfsetospeed(&options,B9600);
if(parity==0) //no parity
{
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
}
else if(parity==1) //odd parity
{
options.c_cflag |= PARENB;
options.c_cflag |= PARODD;
options.c_cflag |= ~CSTOPB;
options.c_cflag |= ~CSIZE;
options.c_cflag |= CS7;
}
else //even parity
{
options.c_cflag |= PARENB;
options.c_cflag |= ~PARODD;
options.c_cflag |= ~CSTOPB;
options.c_cflag |= ~CSIZE;
options.c_cflag |= CS7;
}
options.c_cflag |= (CLOCAL | CREAD);
//apply the setting to the serial port
if(tcsetattr(portNumber, TCSANOW, &options)!= 0)
printf("port setting error\n");
return true;
}

void readData(void)
{
for(j=0 ; j < readNo ; j++)
{
switch(FRAMEFLAG)
{
case 0 :if( buffer[j] == '$' )
FRAMEFLAG = 1;
break;

case 1 :Number = buffer[j];
FRAMEFLAG = 2;
break;

case 2 :if( buffer[j] == ~Number )
FRAMEFLAG = 3;
else
FRAMEFLAG = 0;
break;

case 3 :High = buffer[j];
FRAMEFLAG = 4;
break;

case 4 :Low = buffer[j];
FRAMEFLAG = 5;
break;

case 5 :if( buffer[j] == '*' )
frameEnd = true;
FRAMEFLAG = 0;
break;
}
if( frameEnd )
{
frameEnd = false;
OrderNumber = charToInt(Number);
Value = charToInt(High) * 256 + charToInt(Low);
printf("Number %d Data is : %d \n", OrderNumber, Value);
}
}
}

void* readThreadFunc(void* arg)
{
while(READON)
{
readNo = read(portNumber, buffer, bufSize);
if( readNo > 0 )
{
readData();
}
}
return NULL;
}

int main(int argc, char **argv)
{
char portNo[12] = "/dev/ttyS0";
if( !setSerial(portNo,0) ) return -1;
pthread_create(&readThread, NULL, &readThreadFunc, NULL);

//...........

//close serial port
if(close(portNumber) == -1) return -1;
return 1;
}

//**************************************
//****** Send Code in Windows **********

void CSendDlg::DoExecute()
{
while(Run)
{
for( i=0 ; num < 250 ; i++ )
{
transmit=MainArray.GetAt(i);
if(transmit!=0)
{
SendArray.Format("%c",transmit);
MySerial.Write(SendArray);
}
//windows don't send 0x00 (it's NULL)
else
{
SendArray="";
MySerial.Write(SendArray,1);
}
}
i=0;
}
}

ta0kira 12-07-2008 04:35 AM

Try converting them with htonl before sending, then ntohl when receiving. That will force transmission in a universal integer format, then it will convert to the receiving host's format on the other end. I don't know what the Windows equivalents are.
ta0kira

PS Your code is very difficult to read.

theNbomr 12-07-2008 12:21 PM

Reading between the lines, it looks as if your Windows code is intended to be used as part of some higher level protocol. I would expect there to be a simpler API that allows you to merely send arbitrary streams of data, or even a byte-at-a-time send function. This is what you want, in order to explore where the conversion/translation is taking place.
As ta0kira said, you code is difficult to read ([code] tags would really help), but I see no obvious errors.
Can you try to create a diagnostic component on your Linux host, or some other host, which simply sends some basic data fragments under your control? Especially the bytes in question. If your Linux box has more than one serial port, you can use it to send known buffers, and see how the receiver responds. I would also consider writing a barebones receiver that dumps the received data in some human-readable format (how 'od -cb' displays binary as an example). If your high-level application is failing, you need to be able to closely inspect the lower levels to see what is truly being received.
Just to confirm that the Linux serial subsystem itself is not faulty, try setting up a Kermit file transfer between it and your Windows host.
--- rod.

kalleanka 12-12-2008 10:51 AM

well I would flush both in an out before reading.

I will come back after revising my code. Its on another computer.

Probebly some setting is wrong in setserial. Normaly its like that and I usally use a ocilloscope to detect it. Its fastest like that.


All times are GMT -5. The time now is 01:12 PM.