找回密码
 注册
查看: 1265|回复: 26

关于串口的问题

[复制链接]
发表于 2004-10-28 14:28:20 | 显示全部楼层 |阅读模式
我单独读,写串口都是好用的,但我把读写放的一起就不好用了,
        nwrite=write(fd,buffw,strlen(buffw));
        printf("nwrite=%d\n",nwrite);
        printf("1\n");

        nread=read(fd,buffr,9);
        printf("2\n");
        buffr[9]='\0';
        printf("nread=%d\n",nread);
        printf("%s\n",buffr);
        printf("3\n");
请问这是为什么呢?
发表于 2004-10-28 14:42:15 | 显示全部楼层
怎样不好用法?
回复

使用道具 举报

 楼主| 发表于 2004-10-28 14:46:08 | 显示全部楼层
到打印完1的那个位置程序就死了。。。
回复

使用道具 举报

发表于 2004-10-28 16:23:43 | 显示全部楼层
在本版查找一下,有过不少串口编程的帖子,能解决你的问题
你现在的情况应该是等上一分钟(好像缺省是以1分钟为超时),超时后read读不到内容返回0
回复

使用道具 举报

 楼主| 发表于 2004-10-28 16:40:55 | 显示全部楼层
谢谢你的回复
options.c_cc[VTIME]=150;        //置读超时,单位:1/10秒
options.c_cc[VMIN]=0;   // Update the options and do it NOW
不知道我这么处理超时对不对。。我等了挺长时间还是死着的状态
我也查到了不少串口的文章,但都是一些关于初始化和接收的文章。
回复

使用道具 举报

发表于 2004-10-28 18:40:23 | 显示全部楼层
试试初始化时:
fcntl(fd, F_SETFL, FNDELAY);
Reading Data from the Port



Reading data from a port is a little trickier. When you operate the port in raw data mode, each read(2) system call will return however many characters are actually available in the serial input buffers. If no characters are available, the call will block (wait) until characters come in, an interval timer expires, or an error occurs. The read function can be made to return immediately by doing the following:

fcntl(fd, F_SETFL, FNDELAY);



The FNDELAY option causes the read function to return 0 if no characters are available on the port. To restore normal (blocking) behavior, call fcntl() without the FNDELAY option:

fcntl(fd, F_SETFL, 0);



This is also used after opening a serial port with the O_NDELAY option.
回复

使用道具 举报

 楼主| 发表于 2004-10-29 11:24:01 | 显示全部楼层
我的测试方法,我用了一个小东西,我发什么它给我发什么回来。
我开着minicom监视,当我运行我的程序的时候,minicom显示是收到了的,可我的read(fd,buffr,9); 的返回值却是-1,这是为什么呢?
我加了你说的那个fcntl(fd, F_SETFL, FNDELAY); 后程序不死了。。
回复

使用道具 举报

发表于 2004-10-30 09:20:50 | 显示全部楼层
不打开minicom监视,read(fd,buffr,9)有返回不?
回复

使用道具 举报

 楼主| 发表于 2004-10-30 13:04:21 | 显示全部楼层
我又验证了一下,minicom显示的是我发出去的数。
因为我开着minicom(其它的不跑),下面的东西发数字,minicom什么反映也没有,所以我认为我昨天看到的应该是我发出去的数。
现在证明我的接收又有问题了,我拿了以前接收好用的程序来接,同样是不好用。。。另外minicom我还不是很会用,所以我还是不确定是不是我的串口坏了根本接不上来数。
回复

使用道具 举报

发表于 2004-10-30 18:17:08 | 显示全部楼层
将自己串口的2、3脚连起来做试验(15针com口),自发自收
回复

使用道具 举报

 楼主| 发表于 2004-11-1 11:53:23 | 显示全部楼层
我的代码有什么问题吗,我怎么也收不上来了,不过偶尔还是能上来一两个数。
我感觉我的接收机制有问题,main中注释的那一大段昨天好用了,今天又不好了。。
#include     <stdio.h>      /*标准输入输出定义*/
#include     <stdlib.h>     /*标准函数库定义*/
#include     <unistd.h>     /*Unix标准函数定义*/
#include     <sys/types.h>  /**/
#include     <sys/stat.h>   /**/
#include     <fcntl.h>      /*文件控制定义*/
#include     <termios.h>    /*PPSIX终端控制定义*/
#include     <errno.h>      /*错误号定义*/
#define FALSE -1
#define TRUE 0

/***@brief  设置串口通信速率
*@param  fd     类型 int  打开串口的文件句柄
*@param  speed  类型 int  串口速度
*@return  void*/

int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300,
            B38400, B19200, B9600, B4800, B2400, B1200, B300, };
int name_arr[] = {38400,  19200,  9600,  4800,  2400,  1200,  300,
            38400,  19200,  9600, 4800, 2400, 1200,  300, };
void set_speed(int fd, int speed)
{
  int   i;
  int   status;
  struct termios   Opt;
  tcgetattr(fd, &Opt);
  for ( i= 0;  i < sizeof(speed_arr) / sizeof(int);  i++)
   {
           if  (speed == name_arr)
           {
               tcflush(fd, TCIOFLUSH);
            cfsetispeed(&Opt, speed_arr);
            cfsetospeed(&Opt, speed_arr);
        Opt.c_cflag|=(CLOCAL|CREAD);                //允许接收
            status = tcsetattr(fd, TCSANOW, &Opt);
            if  (status != 0)
            perror("tcsetattr fd1");
             return;
             }
   tcflush(fd,TCIOFLUSH);
   }
}
/**
*@brief   设置串口数据位,停止位和效验位
*@param  fd     类型  int  打开的串口文件句柄*
*@param  databits 类型  int 数据位   取值 为 7 或者8*
*@param  stopbits 类型  int 停止位   取值为 1 或者2*
*@param  parity  类型  int  效验类型 取值为N,E,O,,S
*/
int set_Parity(int fd,int databits,int stopbits,int parity)
{
        struct termios options;
if  ( tcgetattr( fd,&options)  !=  0)
  {
          perror("SetupSerial 1");
          return(FALSE);
  }
  options.c_cflag &= ~CSIZE;
  switch (databits)
  {
          case 7:
                  options.c_cflag |= CS7;
                  break;
          case 8:
                options.c_cflag |= CS8;
                break;
        default:
                fprintf(stderr,"Unsupported data size\n");
                return (FALSE);
        }
  switch (parity)
  {
          case 'n':
                case 'N':
                options.c_cflag &= ~PARENB;   /* Clear parity enable */
                options.c_iflag &= ~INPCK;     /* Enable parity checking */
                break;
        case 'o':
        case 'O':
                options.c_cflag |= (PARODD | PARENB);                 options.c_iflag |= INPCK;             /* Disnable parity checking */
                break;
        case 'e':
        case 'E':
                options.c_cflag |= PARENB;     /* Enable parity */
                options.c_cflag &= ~PARODD;   /* 转换为偶效验*/  
                options.c_iflag |= INPCK;      
                break;
        case 'S':
        case 's':  /*as no parity*/
                options.c_cflag &= ~PARENB;
                options.c_cflag &= ~CSTOPB;
                break;
        default:
                fprintf(stderr,"Unsupported parity\n");
                return (FALSE);
                }
  // 设置停止位
  
  switch (stopbits)
          {
          case 1:
                  options.c_cflag &= ~CSTOPB;
                break;
        case 2:
                options.c_cflag |= CSTOPB;
                break;
        default:
                fprintf(stderr,"Unsupported stop bits\n");
                return (FALSE);
        }

  /* Set input parity option */

  if (parity != 'n')
  //options.c_iflag |= INPCK;
    options.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    options.c_cc[VTIME] = 10; // 15 seconds
    options.c_cc[VMIN] = 0;

  tcflush(fd,TCIFLUSH); /* Update the options and do it NOW */
  if (tcsetattr(fd,TCSANOW,&options) != 0)
          {
                  perror("SetupSerial 3");
                return (FALSE);
        }
  return (TRUE);
}
/**
*@breif 打开串口
*/
int OpenDev(char *Dev)
{
int        fd = open( Dev, O_RDWR );         //| O_NOCTTY | O_NDELAY
        if (-1 == fd)
                {
                        perror("Can't Open Serial Port");
                        return -1;
                }
        else
        return fd;

}



int main(int argc, char **argv)
{
        int fd;
        int nread;
        int nwrite;
        char buffr[512];
        char buffw[512]={49,50,51,52,53,54,55,56,57};
        char *dev ="/dev/ttyS0";
        int i;
        fd = OpenDev(dev);
        if (fd>0)
    set_speed(fd,9600);
        else
                {
                printf("Can't Open Serial Port!\n");
                exit(0);
                }
  if (set_Parity(fd,8,1,'N')== FALSE)
  {
    printf("Set Parity Error\n");
    exit(1);
  }
        printf("1\n");
/*        nwrite=write(fd,buffw,9);
        printf("nwrite=%d\n",nwrite);
        printf("2\n");
          nread = read(fd,buffr,1);
           printf("\nLen %d\n",nread);
        printf("3\n");
              //buffr[nread+1]='\0';
              //printf("%s\n",buffr)
        for(i=0;i<nread;i++)
        printf("%c",buffr);
        printf("\nright!\n");*/
       
                 for(i=0;i<11:i++)
        {
                nread = read(fd,buffr+i,1);
                if(nread>0)
                printf("%c\n",buffr);
                else
                printf("read faild\n");
        }
               

    close(fd);
   // exit(0);
}
回复

使用道具 举报

发表于 2004-11-1 22:54:04 | 显示全部楼层
case 'o':
case 'O':
options.c_cflag |= (PARODD | PARENB); options.c_iflag |= INPCK; /* Disnable parity checking */

设置成不用校验试试
如果发送方设置校验,譬如设置了偶校验的话,如果接收方没有设置偶检验而又不忽略校验的话,将会出现校验出错而丢弃校验出错的数据
回复

使用道具 举报

 楼主| 发表于 2004-11-2 10:38:20 | 显示全部楼层
首先很感谢你这么长时间一直的回帖,真的谢谢你。。
我已经设成不要校验的方式了set_Parity(fd,8,1,'N')。

下面是我最新的代码,其实没改什么就好用了,不过有的时候还是不好用。我现在有点怀疑它的驱动做的是不是有问题了,因为下面的代码什么也不改动,有时候一天都好用,而第二天就不好用了,让我很是困惑。


#include     <stdio.h>      /*标准输入输出定义*/
#include     <stdlib.h>     /*标准函数库定义*/
#include     <unistd.h>     /*Unix标准函数定义*/
#include     <sys/types.h>  /**/
#include     <sys/stat.h>   /**/
#include     <fcntl.h>      /*文件控制定义*/
#include     <termios.h>    /*PPSIX终端控制定义*/
#include     <errno.h>      /*错误号定义*/
#define FALSE -1
#define TRUE 0

/***@brief  设置串口通信速率
*@param  fd     类型 int  打开串口的文件句柄
*@param  speed  类型 int  串口速度
*@return  void*/

int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300,
            B38400, B19200, B9600, B4800, B2400, B1200, B300, };
int name_arr[] = {38400,  19200,  9600,  4800,  2400,  1200,  300,
            38400,  19200,  9600, 4800, 2400, 1200,  300, };
void set_speed(int fd, int speed)
{
  int   i;
  int   status;
  struct termios   Opt;
  tcgetattr(fd, &Opt);
  for ( i= 0;  i < sizeof(speed_arr) / sizeof(int);  i++)
   {
           if  (speed == name_arr)
           {
               tcflush(fd, TCIOFLUSH);
            cfsetispeed(&Opt, speed_arr);
            cfsetospeed(&Opt, speed_arr);
        Opt.c_cflag|=(CLOCAL|CREAD);                //允许接收
            status = tcsetattr(fd, TCSANOW, &Opt);
            if  (status != 0)
            perror("tcsetattr fd1");
             return;
             }
   tcflush(fd,TCIOFLUSH);
   }
}
/**
*@brief   设置串口数据位,停止位和效验位
*@param  fd     类型  int  打开的串口文件句柄*
*@param  databits 类型  int 数据位   取值 为 7 或者8*
*@param  stopbits 类型  int 停止位   取值为 1 或者2*
*@param  parity  类型  int  效验类型 取值为N,E,O,,S
*/
int set_Parity(int fd,int databits,int stopbits,int parity)
{
        struct termios options;
if  ( tcgetattr( fd,&options)  !=  0)
  {
          perror("SetupSerial 1");
          return(FALSE);
  }
  options.c_cflag &= ~CSIZE;
  switch (databits)
  {
          case 7:
                  options.c_cflag |= CS7;
                  break;
          case 8:
                options.c_cflag |= CS8;
                break;
        default:
                fprintf(stderr,"Unsupported data size\n");
                return (FALSE);
        }
  switch (parity)
  {
          case 'n':
                case 'N':
                options.c_cflag &= ~PARENB;   /* Clear parity enable */
                options.c_iflag &= ~INPCK;     /* Enable parity checking */
                break;
        case 'o':
        case 'O':
                options.c_cflag |= (PARODD | PARENB);  /* 设置为奇效验*/
                options.c_iflag |= INPCK;             /* Disnable parity checking */
                break;
        case 'e':
        case 'E':
                options.c_cflag |= PARENB;     /* Enable parity */
                options.c_cflag &= ~PARODD;   /* 转换为偶效验*/  
                options.c_iflag |= INPCK;       /* Disnable parity checking */
                break;
        case 'S':
        case 's':  /*as no parity*/
                options.c_cflag &= ~PARENB;
                options.c_cflag &= ~CSTOPB;
                break;
        default:
                fprintf(stderr,"Unsupported parity\n");
                return (FALSE);
                }
  // 设置停止位
  
  switch (stopbits)
          {
          case 1:
                  options.c_cflag &= ~CSTOPB;
                break;
        case 2:
                options.c_cflag |= CSTOPB;
                break;
        default:
                fprintf(stderr,"Unsupported stop bits\n");
                return (FALSE);
        }

  /* Set input parity option */

  if (parity != 'n')
  //options.c_iflag |= INPCK;
    options.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    options.c_cc[VTIME] = 5; // 1/10 seconds
    options.c_cc[VMIN] = 0;

  tcflush(fd,TCIFLUSH); /* Update the options and do it NOW */
  if (tcsetattr(fd,TCSANOW,&options) != 0)
          {
                  perror("SetupSerial 3");
                return (FALSE);
        }
  return (TRUE);
}
/**
*@breif 打开串口
*/
int OpenDev(char *Dev)
{
int        fd = open( Dev, O_RDWR );         //| O_NOCTTY | O_NDELAY
        if (-1 == fd)
                {
                        perror("Can't Open Serial Port");
                        return -1;
                }
        else
        return fd;

}



int main(int argc, char **argv)
{
        int fd;
        int nread=0;
        int nwrite=0;
        char buffr[512];
        char buffw[512]={49,50,51,52,53,54,55,56,57};
char buffw1[512]={48,49,50,51,52,53,54,55,56,57};
        char *dev ="/dev/ttyS0";
        int i;
        fd = OpenDev(dev);
        if (fd>0)
    set_speed(fd,9600);
        else
                {
                printf("Can't Open Serial Port!\n");
                exit(0);
                }
  if (set_Parity(fd,8,1,'N')== FALSE)
  {
    printf("Set Parity Error\n");
    exit(1);
  }
        printf("1\n");
        nwrite=write(fd,buffw,9);
        printf("nwrite=%d\n",nwrite);
        for(i=0;i<nwrite;i++)
        printf("%c",buffw);

        nread = read(fd,buffr,20);//缓冲区内有大于20个数只读20个,小于则读出实际的数目
        printf("\nnread=%d\n",nread);

        for(i=0;i<nread;i++)
        printf("%c",buffr);

printf("\n....2....\n");
nwrite=write(fd,buffw1,9);
printf("nwrite=%d\n",nwrite);
for(i=0;i<nwrite;i++)
printf("%c",buffw1);
nread = read(fd,(buffr+5),5);//nread返回真正收到的字节数
printf("\nnread=%d\n",nread);
for(i=5;i<(5+nread);i++)
printf("%c",buffr);
        printf("\nright!\n");
/*        for(i=0;i<9;i++)
        {
                nread = read(fd,buffr+i,1);
                if(nread>0)
                printf("%c\n",buffr);
                else
                printf("read faild\n");
        }
               
*/

    close(fd);
   // exit(0);
}
回复

使用道具 举报

 楼主| 发表于 2004-11-2 10:49:41 | 显示全部楼层
也许是我理解的有问题,因为这么长时间了,有几个函数我还是不知道是什么意思。
tcgetattr(fd, &Opt);
tcflush(fd, TCIOFLUSH);
tcsetattr(fd,TCSANOW,&options);
还有几个参数options.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG);之类的,我根本不知道它们是什么意思,只是一阵吓改。
可能上这样的原因才导致一会好用一会不好用的。。
回复

使用道具 举报

 楼主| 发表于 2004-11-2 11:18:48 | 显示全部楼层
关于流控制的两个参数
options.c_cc[VTIME] = 50; //  
options.c_cc[VMIN] = 0; // VMIN=0时在VTIME没收到数据则返回0
                                     //  VMIN不等于0时则收不到数据一直等待
                        //                 (收不到VMIN个数据也等待的现象没有)
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2025-2-11 21:52 , Processed in 0.039322 second(s), 15 queries .

© 2001-2025 Discuz! Team. Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表