LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1331|回复: 3

关于串口的问题

[复制链接]
发表于 2007-8-27 10:47:16 | 显示全部楼层 |阅读模式
我的测试环境是用PC的串口和另一台嵌入设备通信,我发送多少数据它就完整的返回多少数据;
现在出现的问题每向串口write几十次数据都会有一次write不成功,不成功的几率在%2;而且在write不成功时,write函数也不会返回错误值,这样我的程序就无法知道这次write是否成功了.
不知为什么会有这样的问题,该如何解决这个问题呢?哪位大虾能提供一点帮助

  1. #include <stdio.h>  /*标准输入输出定义*/
  2. #include <stdlib.h>  /*标准函数库定义*/
  3. #include <string.h>
  4. #include <unistd.h>  /*Unix 标准函数定义*/
  5. #include <sys/types.h>
  6. #include <sys/stat.h>
  7. #include <fcntl.h>  /*文件控制定义*/
  8. #include <errno.h>  /*错误号定义*/
  9. #include <sys/ioctl.h>
  10. #include <signal.h>
  11. #include <termios.h>  /*PPSIX 终端控制定义*/
  12. //
  13. // 串口设备信息结构
  14. //
  15. typedef struct tty_info_t {
  16.         int     fd;    // 串口设备ID
  17.         char     name[24];  // 串口设备名称,例:"/dev/ttyS0"
  18.         struct termios  ntm;   // 新的串口设备选项
  19.         struct termios  otm;   // 旧的串口设备选项
  20. }
  21. TTY_INFO;

  22. ///////////////////////////////////////////////////////////////////////////////
  23. // 初始化串口设备并进行原有设置的保存
  24. TTY_INFO *readyTTY(int id) {
  25.         TTY_INFO *ptty;

  26.         ptty = (TTY_INFO *)malloc(sizeof(TTY_INFO));
  27.         if(ptty == NULL)
  28.                 return NULL;
  29.         memset(ptty,0,sizeof(TTY_INFO));
  30.         sprintf(ptty->name,"/dev/ttyS%d",id);
  31. //
  32. // 打开并且设置串口
  33. //
  34.         ptty->fd = open(ptty->name, O_RDWR | O_NOCTTY |O_NDELAY);
  35.         if (ptty->fd <0) {
  36.                 free(ptty);
  37.                 return NULL;
  38.         }
  39. //
  40. // 取得并且保存原来的设置
  41. //
  42.         tcgetattr(ptty->fd,&ptty->otm);
  43.         return ptty;
  44. }

  45. ///////////////////////////////////////////////////////////////////////////////
  46. // 清理串口设备资源
  47. int cleanTTY(TTY_INFO *ptty) {
  48. //
  49. // 关闭打开的串口设备
  50. //
  51.         if(ptty->fd>0) {
  52.                 tcsetattr(ptty->fd,TCSANOW,&ptty->otm);
  53.                 close(ptty->fd);
  54.                 ptty->fd = -1;
  55.                 free(ptty);
  56.                 ptty = NULL;
  57.         }

  58.         return 0;
  59. }

  60. int total_read = 0;

  61. size_t readn(int fd,void *vptr,size_t len) {
  62.         int nleft,nread;
  63.         char *ptr;

  64.         ptr = vptr;
  65.         nleft = len;

  66.         while(nleft > 0) {
  67.                 ioctl(fd, FIONREAD, &nread);
  68.                 if(nread > 0) {
  69.                         if((nread = read(fd,ptr,nleft)) < 0) {
  70.                                 if(errno == EINTR)
  71.                                         nread = 0;
  72.                                 else
  73.                                         return -1;
  74.                         } else if(nread == 0)
  75.                                 break;

  76.                         nleft-= nread;
  77.                         ptr += nread;
  78.                         printf("read %d bytes\n",nread);
  79.                         total_read += nread;
  80.                 } else {
  81.                         usleep(100);
  82.                 }
  83.         }
  84.         return len - nleft;
  85. }

  86. size_t writen(int fd,const void *vptr,size_t len) {
  87.         int n;
  88.         size_t left = len;
  89.         const void *ptr = vptr;
  90.         int i;

  91.         for(i = 0; i < len; i++) {
  92.                 unsigned char *c = (char *)(vptr + i);
  93.                 printf("%x ",*c);
  94.         }
  95.         while(left > 0) {
  96.                 if((n = write(fd,ptr,len)) > 0) {
  97.                         left -= n;
  98.                         ptr += n;
  99.                 }
  100.                 if(n < 0 && errno != EINTR) {
  101.                         return -1;
  102.                 }
  103.         }
  104.         return len;
  105. }

  106. static int setTTYArbitraryAttrib(TTY_INFO *ptty) {
  107.         struct termios *newtio = &ptty->ntm;
  108.        
  109.         if(tcgetattr(ptty->fd,newtio) != 0) {
  110.                 perror("tcgetattr");
  111.                 return -1;
  112.         }
  113.        
  114.         bzero(newtio,sizeof(struct termios));
  115.         newtio->c_cflag &=~CSIZE;
  116.         newtio->c_cflag |= CS8; //8位数据位

  117.         newtio->c_cflag &= ~PARENB; /* Clear parity enable */
  118.         newtio->c_iflag &= ~INPCK; /* Enable parity checking */

  119.         newtio->c_cflag &= ~CSTOPB;

  120.         newtio->c_cc[VTIME] = 0;
  121.         newtio->c_cc[VMIN] = 1;
  122.         newtio->c_cflag |= (CLOCAL|CREAD);
  123.         newtio->c_cflag |= CLOCAL | CREAD;
  124.         newtio->c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
  125.         newtio->c_oflag &= ~OPOST;
  126.         newtio->c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);

  127.         cfsetispeed(newtio,B9600);
  128.         cfsetospeed(newtio,B9600);
  129.         tcflush(ptty->fd,TCIFLUSH);
  130.         if(tcsetattr(ptty->fd,TCSANOW,newtio) != 0) {
  131.                 perror("tcsetattr");
  132.                 return -1;
  133.         }
  134.         return 0;
  135. }

  136. static void sig_int(int n) {
  137.         printf("total_read:%d\n",total_read);
  138.         exit(0);
  139. }

  140. int main(int argc,char **argv) {
  141.         TTY_INFO *ptty;
  142.         int nbyte,i;
  143.         char send_buf[] = {
  144.                             0xFF,0xFF,0xFF,0xFF,
  145.                             0x11,0x11,
  146.                             0x22,
  147.                             0x00,0x01,
  148.                             0x05,
  149.                             0x00,
  150.                             0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  151.                             0x05,
  152.                             0x53,0x02,0x02,0x01,0x01,
  153.                             0x03
  154.                           };


  155.         char recv_buf[26];

  156.         signal(SIGINT,sig_int);
  157.         ptty = readyTTY(0);
  158.         if(ptty == NULL) {
  159.                 printf("readyTTY(0)  error\n");
  160.                 return 1;
  161.         }

  162.         setTTYArbitraryAttrib(ptty);
  163.         while(1) {
  164.                 if(writen(ptty->fd,send_buf,sizeof(send_buf)) < 0) {
  165.                         printf("writen failed\n");
  166.                         return -1;
  167.                 } else {
  168.                         printf("writen successfully\n");
  169.                 }

  170.                 nbyte = readn(ptty->fd,recv_buf,sizeof(recv_buf));
  171.                 if(nbyte < 0) {
  172.                         perror("readn");
  173.                         return -1;
  174.                 }

  175.                 for(i = 0; i < nbyte; i++) {
  176.                         unsigned char c = recv_buf[i];
  177.                         printf("%x ",c);
  178.                 }
  179.                 printf("\n");
  180.         }
  181.         cleanTTY(ptty);
  182.         return 0;
  183. }
复制代码
发表于 2007-9-2 11:38:14 | 显示全部楼层
无限循环?  速率太快了吧
回复 支持 反对

使用道具 举报

发表于 2007-9-14 00:01:38 | 显示全部楼层
是程序循环比硬件发送快,导致发送缓冲区满,继续write将丢失数据。linux可以通过ioctl(fd,FIONREAD,&noread)来获取接收缓冲区内字节数,却没有ioctl(fd,FIONWRITE,&nowrite)获取发送缓冲区内字节数,而vxWorks是有的!很不方便,现在我是write完后usleep固定延时的,但总觉得不好!希望大侠能提供帮助!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-9-15 13:34:01 | 显示全部楼层
Post by minuet
是程序循环比硬件发送快,导致发送缓冲区满,继续write将丢失数据。linux可以通过ioctl(fd,FIONREAD,&noread)来获取接收缓冲区内字节数,却没有ioctl(fd,FIONWRITE,&nowrite)获取发送缓冲区内字节数,而vxWorks是有的!很不方便,现在我是write完后usleep固定延时的,但总觉得不好!希望大侠能提供帮助!

我现在的解决方式是每写1个字节睡眠100微妙,这样才能保证串口输出的稳定,我看了cutecom的源代码,它是默认每写1个字节睡眠1毫妙
回复 支持 反对

使用道具 举报

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

本版积分规则

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