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? |
What are you using to read the serial data? If it is some program that you wrote, show us the relevant code fragments.
--- rod. |
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; } } |
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. |
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. |
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. |