Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1247569
  • 博文数量: 261
  • 博客积分: 4196
  • 博客等级: 上校
  • 技术积分: 3410
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-17 17:05
文章分类

全部博文(261)

文章存档

2018年(1)

2017年(22)

2016年(2)

2015年(8)

2014年(27)

2013年(40)

2012年(161)

分类: C/C++

2014-07-15 11:01:12

许多流行的linux串口编程的版本中都没对c_iflag(termios成员变量)这个变量进行有效的设置,这样传送ASCII码时没什么问题,但传送二进制数据时遇到0x0d,0x11和0x13却会被丢掉。不用说也知道,这几个肯定是特殊字符,被用作特殊控制了。关掉ICRNL和IXON选项即可解决。

c_iflag &= ~(ICRNL | IXON);

0x0d 回车符CR

0x11 ^Q VSTART字符

0x13 ^S VSTOP字符

ICRNL 将输入的CR转换为NL  

IXON 使起动/停止输出控制流起作用


  1. #include <fcntl.h>
  2. #include <errno.h>
  3. #include <termios.h>
  4. #include <stdio.h>

  5. #include <pthread.h>
  6. #include <sys/times.h>
  7. #include <sys/select.h>
  8. #include <assert.h>
  9. #include <sys/types.h>
  10. #include <cutils/atomic.h>
  11. #include <hardware/hardware.h>

  12. #include "serial.h"


  13. //串口相关
  14. struct termios serial_oldtio;
  15. struct termios serial_newtio;
  16. fd_set read_fds;
  17.     

  18.  static int set_serial_opts(int fd, int nSpeed, int nBits, char nEvent, int nStop)
  19.  {
  20.     int ret = -1;
  21.     
  22.     if (fd < 0)
  23.         return -1;
  24.     
  25.     //将目前终端机参数保存到结构体变量serial_oldtio中
  26.     if (tcgetattr(fd, &serial_oldtio) != 0)
  27.     {
  28.         goto fail;
  29.     }
  30.     
  31.     //结构体serial_newtio清0
  32.     memset(&serial_newtio, 0, sizeof(serial_newtio));
  33.             
  34.     //设置串口参数
  35.     serial_newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
  36.     serial_newtio.c_oflag &= ~OPOST;
  37.     serial_newtio.c_iflag &= ~(ICRNL | IXON | IGNCR);
  38.     serial_newtio.c_cflag |= CLOCAL | CREAD; //启动接收器
  39.     serial_newtio.c_cflag &= ~CSIZE;

  40.     serial_newtio.c_cc[VTIME] = 0;
  41.     serial_newtio.c_cc[VMIN] = 0;
  42.     
  43.     serial_newtio.c_cc[VINTR] = 0;
  44.     serial_newtio.c_cc[VQUIT] = 0;
  45.     serial_newtio.c_cc[VERASE] = 0;
  46.     serial_newtio.c_cc[VKILL] = 0;
  47.     serial_newtio.c_cc[VEOF] = 0;
  48.     serial_newtio.c_cc[VTIME] = 1;
  49.     serial_newtio.c_cc[VMIN] = 0;
  50.     serial_newtio.c_cc[VSWTC] = 0;
  51.     serial_newtio.c_cc[VSTART] = 0;
  52.     serial_newtio.c_cc[VSTOP] = 0;
  53.     serial_newtio.c_cc[VSUSP] = 0;
  54.     serial_newtio.c_cc[VEOL] = 0;
  55.     serial_newtio.c_cc[VREPRINT] = 0;
  56.     serial_newtio.c_cc[VDISCARD] = 0;
  57.     serial_newtio.c_cc[VWERASE] = 0;
  58.     serial_newtio.c_cc[VLNEXT] = 0;
  59.     serial_newtio.c_cc[VEOL2] = 0;


  60.     
  61.     switch (nBits)
  62.     {
  63.         case 7: serial_newtio.c_cflag |= CS7;break;
  64.         case 8: serial_newtio.c_cflag |= CS8;break;
  65.         default:
  66.             serial_newtio.c_cflag |= CS8;break;
  67.     }
  68.     
  69.     
  70.     switch (nEvent)
  71.     {
  72.         case 'O':
  73.             serial_newtio.c_cflag |= PARENB;
  74.             serial_newtio.c_cflag |= PARODD;
  75.             serial_newtio.c_iflag |= (INPCK|ISTRIP);
  76.             break;
  77.             
  78.         case 'E':
  79.             serial_newtio.c_cflag |= PARENB;
  80.             serial_newtio.c_cflag &= ~PARODD;
  81.             serial_newtio.c_iflag |= (INPCK|ISTRIP);
  82.             break;
  83.         
  84.         case 'N':
  85.             serial_newtio.c_cflag &= ~PARENB;
  86.             break;
  87.         
  88.         default:
  89.             serial_newtio.c_cflag &= ~PARENB;
  90.             break;
  91.     }
  92.     
  93.     switch (nSpeed)
  94.     {
  95.         case 9600:
  96.             cfsetispeed(&serial_newtio, B9600);
  97.             cfsetospeed(&serial_newtio, B9600);
  98.             break;
  99.         
  100.         case 19200:
  101.             cfsetispeed(&serial_newtio, B19200);
  102.             cfsetospeed(&serial_newtio, B19200);
  103.             break;
  104.             
  105.         case 38400:
  106.             cfsetispeed(&serial_newtio, B38400);
  107.             cfsetospeed(&serial_newtio, B38400);
  108.             break;
  109.         
  110.         case 57600:
  111.             cfsetispeed(&serial_newtio, B57600);
  112.             cfsetospeed(&serial_newtio, B57600);
  113.             break;
  114.             
  115.         case 115200:
  116.             cfsetispeed(&serial_newtio, B115200);
  117.             cfsetospeed(&serial_newtio, B115200);
  118.             break;
  119.             
  120.         default:
  121.             cfsetispeed(&serial_newtio, B9600);
  122.             cfsetospeed(&serial_newtio, B9600);
  123.             break;
  124.     }
  125.     
  126.     if (nStop == 1)
  127.         serial_newtio.c_cflag &= ~CSTOPB;
  128.     else if (nStop == 2)
  129.         serial_newtio.c_cflag = CSTOPB;
  130.         
  131.     //刷新在串口中的输入输出数据
  132.     tcflush(fd, TCIFLUSH);
  133.             
  134.     //设置当前的的串口参数为flydvd_newtio
  135.     if (tcsetattr(fd, TCSANOW, &serial_newtio) != 0)
  136.     {
  137.         goto fail;
  138.     }
  139.     
  140.     ret = 0;
  141.             
  142.     fail:
  143.         return ret;
  144.  }
  145.  
  146.  int serial_write(int fd, unsigned char *buf, int len)
  147.  {
  148.     int ret = -1;
  149.     
  150.     if (fd < 0)
  151.         return ret;
  152.         
  153.     //写入数据
  154.     ret = write(fd, buf, len);
  155.     
  156.     return ret;
  157.  }

  158.  long serial_read(int fd, unsigned char *buf, int len)
  159.  {
  160.     long ret = -1;
  161.     struct timeval tv_timeout;

  162.     FD_ZERO(&read_fds);
  163.     FD_SET(fd, &read_fds);
  164.     tv_timeout.tv_sec = 1;
  165.     tv_timeout.tv_usec = 0;

  166.     switch (select(fd+1, &read_fds, NULL, NULL, &tv_timeout))
  167.     {
  168.         case -1:
  169.             printf("select error");
  170.             break;
  171.                 
  172.         case 0:
  173.             printf("select timeout");
  174.             break;
  175.                 
  176.         default:
  177.             if (1)
  178.             //if (FD_ISSET(fd, &read_fds))
  179.             {
  180.                 //读取数据
  181.                 ret = read(fd, buf, len);
  182.             }
  183.             break;
  184.         }
  185.         
  186.     return ret;
  187.  }

  188. int serial_open(char* serialName,int nSpeed)
  189. {
  190.     int fd = -1;
  191.     int res = 0;
  192.     pthread_t thread_id;
  193.     
  194.     fd = open(serialName,O_RDWR | O_NOCTTY | O_NDELAY);

  195.     if (fd > 0)
  196.     {
  197.         if (set_serial_opts(fd, nSpeed, 8, 'N', 1) == -1)
  198.         {
  199.             return -1;
  200.         }
  201.         
  202.         FD_ZERO(&read_fds);
  203.     }

  204.     return fd;
  205. }

  206. int serial_close(int fd)
  207. {
  208.     if (fd < 0)
  209.         return -1;
  210.         
  211.     //恢复旧的端口参数
  212. // tcsetattr(fd, TCSANOW, &serial_oldtio);
  213.         
  214.     //关闭串口
  215.     if (!close(fd))
  216.     {
  217.         return 0;
  218.     }
  219.     
  220.     return -1;
  221. }

阅读(1109) | 评论(0) | 转发(0) |
0

上一篇:HAL简要

下一篇: ubuntu下添加交换文件

给主人留下些什么吧!~~