免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 8194 | 回复: 10

串口编程的 tcsetattr() 问题!莫名其妙 [复制链接]

论坛徽章:
0
发表于 2007-04-12 14:19 |显示全部楼层

  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <fcntl.h>
  5. #include <unistd.h>
  6. #include <termios.h>

  7. #define DEVICE "/dev/ttyS0"
  8. #define BAUDRATE B2400
  9. #define _POSIX_SOURCE 1
  10. #define FALSE 0
  11. #define TRUE 1

  12. int main()
  13. {
  14.     int fd;
  15.     struct termios oldtio, newtio;

  16.     fd = open(DEVICE, O_RDWR | O_NOCTTY);
  17.     if(fd < 0)
  18.         printf("Open com failed.\n");
  19.     else
  20.     {
  21.         printf("FD is %d.\n", fd);
  22. //      fcntl( fd, F_SETFL, 0 );
  23.     }

  24.     tcgetattr(fd, &oldtio);

  25.     bzero(&newtio,sizeof(struct termios));

  26.     newtio.c_cflag|= (CLOCAL | CREAD);
  27.     newtio.c_cflag|=BAUDRATE;
  28.     newtio.c_cflag&=~CSTOPB;
  29.     newtio.c_cflag&=~PARENB;
  30.     newtio.c_cflag&=~CSIZE;
  31.     newtio.c_cflag|=CS8;
  32.     newtio.c_cflag&=~CRTSCTS;

  33.     newtio.c_lflag=0;

  34.     newtio.c_oflag=0;

  35.     newtio.c_cc[VMIN]=4;
  36.     newtio.c_cc[VTIME]=0;

  37.     newtio.c_iflag&=~(IXON|IXOFF|IXANY);
  38.     newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG );

  39.     cfsetispeed(&newtio, BAUDRATE);
  40.     cfsetospeed(&newtio, BAUDRATE);

  41.     tcflush(fd, TCIOFLUSH);//up or down?
  42.     tcsetattr(fd, TCSANOW, &newtio);
  43.     return 0;
  44. }
复制代码


这就是我测试的源程序了,运行环境是linux Enterprise AS 3, 用串口线将此机器的串口与我的windows机器相连,windows端使用超级终端来监控输入情况。

程序看着好像没有什么错误,但是只要一运行到    tcsetattr(fd, TCSANOW, &newtio);  这里,在我的windows的超级终端上就会出现许多莫名奇妙的数据,数据还是在不停的变化,变化的很快,但是仔细看这些乱七八糟的数据好像是内容一样的数据在循环不停的输入。并且不能停止,只有将那台linux机器重启之后windows这边才能停下来。

不知什么原因,请高手指点则个。。。

论坛徽章:
0
发表于 2007-04-12 16:39 |显示全部楼层
关于这个问题的总是看的人多,回的人少,是什么原因?

有会的高手请发一下言。。。

另外,虽然windows这边的超级终端数据很乱,但是我从linux端发出的字符也可以在终端上看到,不过就是闪的很快,不注意看的话就看不到,晃一下就过去了

论坛徽章:
0
发表于 2007-04-12 16:59 |显示全部楼层
我以前做串口的时候好像页碰到过,不过我现在忘记当时是怎么解决的了 呵呵。。

论坛徽章:
0
发表于 2007-04-13 09:36 |显示全部楼层
这个问题对各位高手来说应该是不难的吧,为什么就没有人来回答呢?

论坛徽章:
0
发表于 2007-04-13 09:46 |显示全部楼层
这个问题还在啊,可能因为现在做串口的很少吧。
网上有很多串口操作的现成程序,down一个下来试试,我当初就试网上找的
我想起来了,后来我发现我的问题是因为这个串口曾经配过modem,很多参数变了导致的。

论坛徽章:
0
发表于 2007-04-13 10:18 |显示全部楼层
解决这个问题靠自己了
首先用minicom连windows看行不行
如果可以的话用tcgetattr()把minicom的设置弄出来看看是多少
然后在你自己的tcsetattr()后面做一个tcgetattr()看看和minicom的一样不
估计肯定是不一样的
对比自己的attr和minicom的attr
看到底是哪个设置设错了

论坛徽章:
0
发表于 2007-04-13 10:21 |显示全部楼层
好久前写的几个设置函数
看用得上不

  1. /*
  2. *  Desc : set uart baudrate
  3. */
  4. void set_speed(int fd, int speed)
  5. {
  6.         int   status;
  7.         struct termios Opt;

  8.         tcgetattr(fd, &Opt);
  9.         tcflush(fd, TCIOFLUSH);
  10.         cfsetispeed(&Opt, speed);
  11.         cfsetospeed(&Opt, speed);

  12.         status = tcsetattr(fd, TCSANOW, &Opt);
  13.         if  (status != 0) {
  14.                 perror("tcsetattr uart");
  15.                 return;
  16.         }
  17.         tcflush(fd,TCIOFLUSH);
  18. }

  19. int set_data_format(int fd,int databits,int stopbits,int parity)
  20. {
  21.         struct termios opt;

  22.         if( tcgetattr(fd, &opt)  !=  0) {
  23.                 perror("set uart");
  24.                 return(1);
  25.         }
  26.         opt.c_cflag &= ~CSIZE;

  27.         switch (databits) {
  28.                 case 5:
  29.                         opt.c_cflag |= CS5;
  30.                         break;
  31.                 case 6:
  32.                         opt.c_cflag |= CS6;
  33.                         break;
  34.                 case 7:
  35.                         opt.c_cflag |= CS7;
  36.                         break;
  37.                 case 8:
  38.                         opt.c_cflag |= CS8;
  39.                         break;
  40.                 default:
  41.                         fprintf(stderr,"Unsupported data size\n");
  42.                         return (1);
  43.         }
  44.         switch (parity) {
  45.                 case 'n':
  46.                 case 'N':
  47.                         opt.c_cflag &= ~PARENB;                /* Clear parity enable */
  48.                         opt.c_cflag &= ~PARODD;
  49.                         opt.c_iflag &= ~INPCK;                /* Enable parity checking */
  50.                         break;
  51.                 case 'o':
  52.                 case 'O':
  53.                         opt.c_cflag |= (PARODD | PARENB);        /* parity checking */
  54.                         opt.c_iflag |= INPCK;                        /* Disnable parity checking */
  55.                         break;
  56.                 case 'e':
  57.                 case 'E':
  58.                         //my setting
  59.                         opt.c_cflag |= PARENB;
  60.                         opt.c_cflag |= CLOCAL;
  61.                         opt.c_cflag |= CREAD;
  62.                         opt.c_cflag &= ~PARODD;
  63.                         opt.c_iflag &= ~INPCK;

  64.                         break;
  65.                 default:
  66.                         fprintf(stderr,"Unsupported parity\n");
  67.                         return (1);
  68.         }
  69.        
  70.         switch (stopbits) {
  71.                 case 1:
  72.                         opt.c_cflag &= ~CSTOPB;
  73.                         break;
  74.                 case 2:
  75.                         opt.c_cflag |= CSTOPB;
  76.                         break;
  77.                 default:
  78.                         fprintf(stderr,"Unsupported stop bits\n");
  79.                         return (1);
  80.         }
  81.         /* Set input parity option */
  82.         //opt.c_oflag = opt.c_iflag;
  83.         //opt.c_iflag &= ~INPCK;//XXXXX,my god.....
  84.         //opt.c_oflag = 0;//XXXXX,???
  85.         opt.c_lflag = 0;        //yes we need this
  86.         opt.c_cc[VTIME] = 0;
  87.         opt.c_cc[VMIN] = 1;
  88.        
  89.         tcflush(fd, TCIFLUSH); /* Update the options and do it NOW */
  90.         if (tcsetattr(fd, TCSANOW, &opt) != 0) {
  91.                 perror("SetupSerial 3");
  92.                 return (1);
  93.         }
  94.         return 0;
  95. }

  96. void set_uart_for_msur(int msur_id, int fd)
  97. {
  98.         int baudrate = 0, parity = 0, databits = 0, stopbits = 0;
  99.         struct termios opt;
  100.        
  101.         simple_get_sys_option(&baudrate, 0x8905, 1, msur_id);        //get baud rate
  102.         simple_get_sys_option(&parity, 0x8930, 1, msur_id);        //get parity
  103.         simple_get_sys_option(&databits, 0x8931, 1, msur_id);        //get databits
  104.         simple_get_sys_option(&stopbits, 0x8932, 1, msur_id);        //get stopbits

  105.         baudrate *= 300;
  106.         switch(baudrate)
  107.         {
  108.         case 300:
  109.                 baudrate = B300;
  110.                 break;
  111.         case 1200:
  112.                 baudrate = B1200;
  113.                 break;
  114.         case 2400:
  115.                 baudrate = B2400;
  116.                 break;
  117.         case 4800:
  118.                 baudrate = B4800;
  119.                 break;
  120.         case 9600:
  121.                 baudrate = B9600;
  122.                 break;
  123.         case 19200:
  124.                 baudrate = B19200;
  125.                 break;
  126.         case 38400:
  127.                 baudrate = B38400;
  128.                 break;
  129.         case 57600:
  130.                 baudrate = B57600;
  131.                 break;
  132.         case 115200:
  133.                 baudrate = B115200;
  134.                 break;
  135.         case 230400:
  136.                 baudrate = B230400;
  137.                 break;
  138.         default:
  139.                 DBG("***error set_uart_for_msur():non support baudrate\n");
  140.                 baudrate = B9600;
  141.                 break;
  142.         }
  143.         switch(stopbits)
  144.         {
  145.         case 0:
  146.                 stopbits = 1;
  147.                 break;
  148.         case 2:
  149.                 stopbits = 3;
  150.                 break;
  151.         default:
  152.                 DBG("***error set_uart_for_msur():non support stopbits\n");
  153.                 stopbits = 1;
  154.         }
  155.         switch(parity)
  156.         {
  157.         case 0:
  158.                 parity = 'N';
  159.                 break;
  160.         case 1:
  161.                 parity = 'E';
  162.                 break;
  163.         case 2:
  164.                 parity = 'O';
  165.                 break;
  166.         default:
  167.                 DBG("***error set_uart_for_msur():non support parity\n");
  168.                 parity = 'E';
  169.         }
  170.         if( tcgetattr(fd, &opt)  !=  0) {
  171.                 return;
  172.         }
  173.         if ((opt.c_ispeed != baudrate) || (opt.c_ospeed != baudrate))
  174.                 set_speed(fd, baudrate);
  175.         set_data_format(fd, databits, stopbits, parity);
  176. }
复制代码

论坛徽章:
0
发表于 2007-04-13 10:32 |显示全部楼层
已经参考了很多网上的资料,找到的东西都是大同小异的。

另外我的linux的minicom竟然不能用。一运行就会看到屏幕上有不少的乱码。。。根本看不清是什么。

论坛徽章:
0
发表于 2007-04-13 10:38 |显示全部楼层
你不如先把minicom捣鼓好
这样总算有一个可以正常连接的东西了
写程序的时候参考minicom的设置就好
或者找找linux有没有别的串口通信工具?

论坛徽章:
0
发表于 2007-04-13 10:45 |显示全部楼层
用上面那个代码,如果参数设置上没问题的划,一般是可以的,
你查查看是否还有别的进程用到了这个串口?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP