Linux论坛's Archiver

《开源》旗舰电子杂志2008年11期发布,火热下载中!

wangqiang6100 发表于 2008-3-18 20:44

READ()读串口的问题

READ()读串口的问题
在RECIEVE()函数里始终读不到READ里的数据啊,快疯了,顺便说一下,我采集的串口数据是GPS模块采集回来的信息.各位大哥,拜托了!!!
#include <termios.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/signal.h>
#include <pthread.h>
#include <stdlib.h>
#include <errno.h>
#include "gps.h"

#define BAUDRATE B4800
#define COM1 "/dev/ttyS0"
#define COM2 "/dev/ttyS1"
#define ENDMINITERM 27 /* ESC to quit miniterm */
#define FALSE 0
#define TRUE 1

volatile int STOP=FALSE;
volatile int fd;
GPS_INFO gps_info;
int GET_GPS_OK=FALSE;
char GPS_BUF[1024];

/*void child_handler(int s)
{
  printf("stop!!!\n");
   STOP=TRUE;
}*/


/*--------------------------------------------------------*/
void* show_gps_info(void * data)
{
        while(1){
                if(GET_GPS_OK){
                        GET_GPS_OK=FALSE;
                        printf("%s",GPS_BUF);
                        gps_parse(GPS_BUF,&gps_info);
                        show_gps(&gps_info);
                }
                usleep(100);
                if(STOP)break;
        }

}
/*--------------------------------------------------------*/

void* receive(void * data)
{
        int i=0;
        char c;
        int ss=0;
        char buf[1024];
        GPS_INFO GPS;
        
          printf("read modem\n");
      
          while (STOP==FALSE)
          {printf("read modem\n");
            ss=read(fd,&c,1024); /* com port */
        printf("%d/n",ss);
        printf("read modem\n");
            buf[i++] = c;
               
                if(c == '\n'){
                        strncpy(GPS_BUF,buf,i);
                        i=0;
                       
                        GET_GPS_OK=TRUE;
                }
                //if(STOP)break;
                //write(1,&c,1); /* stdout */
          }
          printf("exit from reading modem\n");
          return NULL;
}
/*--------------------------------------------------------*/
int main(int argc,char** argv)
{      int fd;   
      fd_set rd;
      int i;
      if((fd=open_port(fd,1))<0)
          {
            perror("open_port error");
            return;
          }
      if((i=set_opt(fd,4800,8,'N',1))<0)
          {
            perror("set_opt error");
            return;
          }
        
        /*struct termios oldtio,newtio,oldstdtio,newstdtio;
        struct sigaction sa;
        int ok;
        void * retval;
           fd = open(COM1, O_RDWR );
        if (fd <0) {
            perror(COM1);        
            exit(-1);
          }      
          tcgetattr(0,&oldstdtio);
          tcgetattr(fd,&oldtio); // save current modem settings
          tcgetattr(fd,&newstdtio); // get working stdtio
        newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;//ctrol flag
        newtio.c_iflag = IGNPAR; //input flag
        newtio.c_oflag = 0;                //output flag
        newtio.c_lflag = 0;
        newtio.c_cc[VMIN]=1;
        newtio.c_cc[VTIME]=0;
// now clean the modem line and activate the settings for modem
        tcflush(fd, TCIFLUSH);
        tcsetattr(fd,TCSANOW,&newtio);//set attrib
          */
        while(1)
     {
        receive(0);
        //show_gps_info(0);
        //while(!STOP){
                //usleep(100000);
        //}
     }
          /*tcsetattr(fd,TCSANOW,&oldtio); // restore old modem setings
          tcsetattr(0,TCSANOW,&oldstdtio); // restore old tty setings
          close(fd);
          exit(0);*/
}
/* 绔彛璁剧疆*/
int set_opt(int fd,int nspeed,int nbits,char nevent,int nstop)
{
         struct termios newtio,oldtio;
         if(tcgetattr(fd,&oldtio)!=0)
          {
           perror("setupserial 1");
          return (-1);
          }
          bzero(&newtio,sizeof(newtio));
    /*璁剧疆瀛楃澶у皬*/
          newtio.c_cflag|=CLOCAL|CREAD;
          newtio.c_cflag&=~CSIZE;
    /*璁剧疆鏁版嵁浣?/
          switch(nbits)
          {
          case7:
             newtio.c_cflag|=CS7;
             break;
          case8:
             newtio.c_cflag|=CS8;
             break;
           }
    /*璁剧疆濂囧伓鏍¢獙浣?/
           switch(nevent)
           {
           case 'O':   //濂囨暟
                 newtio.c_cflag|=PARENB;
                 newtio.c_cflag|=PARODD;
                 newtio.c_iflag|=(INPCK|ISTRIP);
                 break;
           case 'E':   //鍋舵暟
                 newtio.c_iflag|=(INPCK|ISTRIP);
                 newtio.c_cflag|=PARENB;
                 newtio.c_cflag&=~PARODD;
                 break;
           case 'N':  //鏃犲鍋舵牎楠?
                 newtio.c_cflag&=~PARENB;
                 break;
           }
    /*璁剧疆娉㈢壒鐜?/
          switch(nspeed)
          {
           case 2400:
                cfsetispeed(&newtio,B2400);
                cfsetospeed(&newtio,B2400);
                break;
           case 4800:
                cfsetispeed(&newtio,B4800);
                cfsetospeed(&newtio,B4800);
                break;
           case 9600:
                cfsetispeed(&newtio,B9600);
                cfsetospeed(&newtio,B9600);
                break;
           case 19200:
                cfsetispeed(&newtio,B19200);
                cfsetospeed(&newtio,B19200);
                break;
           case 115200:
                cfsetispeed(&newtio,B115200);
                cfsetospeed(&newtio,B115200);
                break;
           case 57600:
                cfsetispeed(&newtio,B57600);
                cfsetospeed(&newtio,B57600);
                break;
           default:
                cfsetispeed(&newtio,B19200);
                cfsetospeed(&newtio,B19200);
                break;
          }
    /*璁剧疆鍋滄浣?/
           if(nstop==1)
                 newtio.c_cflag&=~CSTOPB;
           else if (nstop==2)
                 newtio.c_cflag|=CSTOPB;
    /*璁剧疆绛夊緟鏃堕棿鍜屾渶灏忔帴鏀跺瓧绗?/
            newtio.c_cc[VTIME]=0;
            newtio.c_cc[VMIN]=0;
    /*澶勭悊鏈帴鏀跺瓧绗?/
           tcflush(fd,TCIFLUSH);
    /*婵

rose 发表于 2008-3-19 10:33

你拷贝上来的这段代码是你真实的代码吗?还是一部分?我没有太明白具体的代码用意,有些还被注释上了。
大致看了一下,那个fd变量到底是全局的?还是局部的变量?你的那个read函数调用的时候,那个fd是多少?可以打印出来看看。

wangqiang6100 发表于 2008-3-19 10:56

拜托了!

#include <termios.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/signal.h>
#include <pthread.h>
#include <stdlib.h>
#include <errno.h>
#include "gps.h"
volatile int fd;
void* receive(void * data)
{
        int i=0;
        char c;      
        char buf[1024];               
          printf("read modem\n");      
          while (1)
          {printf("%d\n",fd);     //这里fd返回的是3,我就想先从串口读GPS模块采集来的数据,什么也没有啊
            read(fd,&c,1); /* com port */      
        printf("read modem\n");
            buf[i++] = c;               
                if(c == '\n')    {
                        i=0;
                        printf("%s\n",buf);       
                        tcflush(fd, TCIFLUSH);                                                             
                               }               
          }         
}

int main(int argc,char** argv)
{   
        struct termios oldtio,newtio,oldstdtio,newstdtio;
        struct sigaction sa;
        int ok;
        void * retval;
           fd = open("/dev/ttyS0", O_RDWR );
        if (fd <0) {
            perror("/dev/ttyS0");        
            exit(-1);
          }
        printf("open uart1 is ok!\n");      
          tcgetattr(0,&oldstdtio);
          tcgetattr(fd,&oldtio); // save current modem settings
          tcgetattr(fd,&newstdtio); // get working stdtio
        newtio.c_cflag = B4800 | CRTSCTS | CS8 | CLOCAL | CREAD;//ctrol flag
        newtio.c_iflag = IGNPAR; //input flag
        newtio.c_oflag = 0;                //output flag
        newtio.c_lflag = 0;
        newtio.c_cc[VMIN]=1;
        newtio.c_cc[VTIME]=0;
        tcflush(fd, TCIFLUSH);
        tcsetattr(fd,TCSANOW,&newtio);//set attrib
          
        while(1)
     {
        receive(0);
       
     }
          /*tcsetattr(fd,TCSANOW,&oldtio); // restore old modem setings
          tcsetattr(0,TCSANOW,&oldstdtio); // restore old tty setings
          close(fd);
          exit(0);*/
}

rose 发表于 2008-3-19 11:34

read读不到数据就会堵塞,可以先用select查询一下状态,我看见网上有这样一段代码供你参考:

Linux下用select查询串口数据

Linux下直接用read读串口可能会造成堵塞,或数据读出错误。然而用select先查询com口,再用read去读就可以避免,并且当com口延时时,程序可以退出,这样就不至于由于com口堵塞,程序就死了。我的代码如下:

bool ReadDevice( int hComm, unsigned long uLen, char* pData )

{  

int nread = 0;

char inbuf[uLen];

char buff[uLen];

memset( inbuff, '\0', uLen );

memset( buff, '\0', uLen );

fd_set readset;
struct timeval tv;
int MaxFd = 0;

int c = 0;
int z;
do
{
FD_ZERO( &readset );
if( hComm >= 0 )
FD_SET( hComm, &readset );
MaxFd = hComm + 1;
tv.tv_sec = 0;
tv.tv_usec = 500000;
do
{
z = select( MaxFd, &readset, 0, 0, &tv);
}while( z==-1 && errno==EINTR );
if( z == -1 )
printf("select(2)\n");
if( z == 0 )
{
hComm = -1;
}

if( hComm>=0 && FD_ISSET(hComm, &readset) )
{
z = read( hComm, buff, uLen - c );
c += z;
if( z == -1 )
{
hComm = -1;
}
if( z > 0 )
{

buff[ z + 1 ] = '\0';
strcat( inbuff, buff );
memset( buff, 0x00, uLen );
}
else
{
hComm = -1;
}
}
}while( hComm >= 0 );

memcpy( pData, inbuff, c );

return true;

}

页: [1]

Powered by Discuz! Archiver 6.1.0  © 2001-2007 Comsenz Inc.