Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1579553
  • 博文数量: 239
  • 博客积分: 1760
  • 博客等级: 上尉
  • 技术积分: 1595
  • 用 户 组: 普通用户
  • 注册时间: 2011-01-08 23:53
文章分类

全部博文(239)

文章存档

2016年(1)

2015年(28)

2014年(53)

2013年(42)

2012年(50)

2011年(65)

分类: 嵌入式

2015-04-16 15:13:16

原文地址:Linux C串口程序 作者:luozhiyong131


点击(此处)折叠或打开

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<unistd.h>
  4. #include<sys/types.h>
  5. #include<sys/stat.h>
  6. #include<fcntl.h>
  7. #include<termios.h>
  8. #include<errno.h>
  9. #include<string.h>

  10. #define FALSE -1
  11. #define TRUE 0

  12. int UART_Open(int fd,char* port);
  13. void UART_Close(int fd);
  14. int UART_Set(int fd,int speed,int flow_ctrl,int databits,int stopbits,int parity);
  15. int UART_Init(int fd, int speed,int flow_ctrlint ,int databits,int stopbits,char parity);
  16. int UART_Recv(int fd, char *rcv_buf,int data_len);
  17. int UART_Send(int fd, char *send_buf,int data_len);

  18. /*****************************************************************
  19. * 名称: UART0_Open
  20. * 功能: 打开串口并返回串口设备文件描述
  21. * 入口参数: fd :文件描述符 port :串口号(ttyS0,ttyS1,ttyS2)
  22. * 出口参数: 正确返回为1,错误返回为0
  23. *****************************************************************/
  24. int UART_Open(int fd,char* port)
  25. {
  26.     
  27.       fd = open( port, O_RDWR|O_NOCTTY|O_NDELAY);
  28.       if (FALSE == fd){
  29.         perror("Can't Open Serial Port");
  30.           return(FALSE);
  31.       }
  32.     
  33.     //判断串口的状态是否为阻塞状态
  34.       if(fcntl(fd, F_SETFL, 0) < 0){
  35.         printf("fcntl failed!\n");
  36.             return(FALSE);
  37.       } else {
  38.            //    printf("fcntl=%d\n",fcntl(fd, F_SETFL,0));
  39.       }
  40.     
  41.      //测试是否为终端设备
  42.       if(0 == isatty(STDIN_FILENO)){
  43.           printf("standard input is not a terminal device\n");
  44.             return(FALSE);
  45.       }
  46.     
  47.       return fd;
  48. }

  49. void UART_Close(int fd)
  50. {
  51.     close(fd);
  52. }

  53. /*******************************************************************
  54. * 名称: UART0_Set
  55. * 功能: 设置串口数据位,停止位和效验位
  56. * 入口参数: fd 串口文件描述符
  57. * speed 串口速度
  58. * flow_ctrl 数据流控制
  59. * databits 数据位 取值为 7 或者8
  60. * stopbits 停止位 取值为 1 或者2
  61. * parity 效验类型 取值为N,E,O,,S
  62. *出口参数: 正确返回为1,错误返回为0
  63. *******************************************************************/
  64. int UART_Set(int fd,int speed,int flow_ctrl,int databits,int stopbits,int parity)
  65. {
  66.     
  67.         int i;
  68.   //    int status;
  69.       int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300,
  70.                    B38400, B19200, B9600, B4800, B2400, B1200, B300
  71.              };
  72.         int name_arr[] = {
  73.              38400, 19200, 9600, 4800, 2400, 1200, 300, 38400,
  74.                    19200, 9600, 4800, 2400, 1200, 300
  75.              };
  76.     struct termios options;

  77.    /*tcgetattr(fd,&options)得到与fd指向对象的相关参数,并将它们保存于options,该函数,还可以测试配置是否正确,该串口是否可用等。若调用成功,函数返回值为0,若调用失败,函数返回值为1.
  78.     */
  79.     if(tcgetattr( fd,&options) != 0){
  80.      perror("SetupSerial 1");
  81.      return(FALSE);
  82.         }
  83.         
  84.         //设置串口输入波特率和输出波特率
  85.     for(i= 0;i < sizeof(speed_arr) / sizeof(int);i++) {     
  86.         if (speed == name_arr[i]) {
  87.                   cfsetispeed(&options, speed_arr[i]);
  88.                   cfsetospeed(&options, speed_arr[i]);
  89.         }
  90.         }    
  91. //修改控制模式,保证程序不会占用串口        
  92.     options.c_cflag |= CLOCAL;
  93.     //修改控制模式,使得能够从串口中读取输入数据
  94.     options.c_cflag |= CREAD;
  95.     //设置数据流控制
  96.     switch(flow_ctrl){
  97.         case 0 : //不使用流控制
  98.             options.c_cflag &= ~CRTSCTS;
  99.             break;    
  100.             case 1 : //使用硬件流控制
  101.                 options.c_cflag |= CRTSCTS;
  102.                 break;
  103.             case 2 : //使用软件流控制
  104.                 options.c_cflag |= IXON | IXOFF | IXANY;
  105.                 break;
  106.     }
  107.      //设置数据位
  108.     options.c_cflag &= ~CSIZE; //屏蔽其他标志位
  109.     switch (databits){
  110.         case 5 :
  111.                 options.c_cflag |= CS5;
  112.                 break;
  113.             case 6    :
  114.                 options.c_cflag |= CS6;
  115.                 break;
  116.             case 7    :
  117.                 options.c_cflag |= CS7;
  118.                 break;
  119.             case 8:
  120.                 options.c_cflag |= CS8;
  121.                 break;
  122.                default:
  123.                 fprintf(stderr,"Unsupported data size\n");
  124.                 return (FALSE);
  125.     }
  126.      //设置校验位
  127.     switch (parity) {
  128.         case 'n':
  129.             case 'N': //无奇偶校验位。
  130.                 options.c_cflag &= ~PARENB;
  131.                 options.c_iflag &= ~INPCK;
  132.                 break;
  133.             case 'o':
  134.             case 'O': //设置为奇校验
  135.                 options.c_cflag |= (PARODD | PARENB);
  136.                 options.c_iflag |= INPCK;
  137.                 break;
  138.             case 'e':
  139.             case 'E': //设置为偶校验
  140.                 options.c_cflag |= PARENB;
  141.                 options.c_cflag &= ~PARODD;
  142.                 options.c_iflag |= INPCK;
  143.                 break;
  144.             case 's':
  145.             case 'S': //设置为空格
  146.                 options.c_cflag &= ~PARENB;
  147.                 options.c_cflag &= ~CSTOPB;
  148.                 break;
  149.             default:
  150.                 fprintf(stderr,"Unsupported parity\n");
  151.                 return (FALSE);
  152.     }
  153.      // 设置停止位
  154.     switch (stopbits){
  155.         case 1:
  156.             options.c_cflag &= ~CSTOPB;
  157.                 break;
  158.             case 2:
  159.                 options.c_cflag |= CSTOPB;
  160.                    break;
  161.             default:
  162.                  fprintf(stderr,"Unsupported stop bits\n");
  163.                  return (FALSE);
  164.     }
  165.     //修改输出模式,原始数据输出
  166.         options.c_oflag &= ~OPOST;
  167.     //设置等待时间和最小接收字符
  168.     options.c_cc[VTIME] = 1; /* 读取一个字符等待1*(1/10)s */
  169.     options.c_cc[VMIN] = 1; /* 读取字符的最少个数为1 */
  170.    
  171.     //如果发生数据溢出,接收数据,但是不再读取
  172.     tcflush(fd,TCIFLUSH);
  173.    
  174.     //激活配置 (将修改后的termios数据设置到串口中)
  175.     if (tcsetattr(fd,TCSANOW,&options) != 0)
  176.     {
  177.                perror("com set error!/n");
  178.        return (FALSE);
  179.     }
  180.     return (TRUE);
  181. }


  182. int UART_Init(int fd, int speed,int flow_ctrlint ,int databits,int stopbits,char parity)
  183. {
  184.      //设置串口数据帧格式
  185.     if (FALSE == UART_Set(fd,speed,flow_ctrlint,databits,stopbits,parity)) {         
  186.         return FALSE;
  187.         } else {
  188.            return TRUE;
  189.        }
  190. }



  191. /*******************************************************************
  192. * 名称: UART0_Recv
  193. * 功能: 接收串口数据
  194. * 入口参数: fd :文件描述符
  195. * rcv_buf :接收串口中数据存入rcv_buf缓冲区中
  196. * data_len :一帧数据的长度
  197. * 出口参数: 正确返回为1,错误返回为0
  198. *******************************************************************/
  199. int UART_Recv(int fd, char *rcv_buf,int data_len)
  200. {
  201.     int len,fs_sel;
  202.     fd_set fs_read;
  203.     
  204.     struct timeval time;
  205.     
  206.     FD_ZERO(&fs_read);
  207.     FD_SET(fd,&fs_read);
  208.     
  209.     time.tv_sec = 10;
  210.     time.tv_usec = 0;
  211.     
  212.     //使用select实现串口的多路通信
  213.     fs_sel = select(fd+1,&fs_read,NULL,NULL,&time);
  214.     if(fs_sel){
  215.      len = read(fd,rcv_buf,data_len);    
  216.      return len;
  217.         } else {
  218.         return FALSE;
  219.     }    
  220. }

  221. /*******************************************************************
  222. * 名称: UART0_Send
  223. * 功能: 发送数据
  224. * 入口参数: fd :文件描述符
  225. * send_buf :存放串口发送数据
  226. * data_len :一帧数据的个数
  227. * 出口参数: 正确返回为1,错误返回为0
  228. *******************************************************************/
  229. int UART_Send(int fd, char *send_buf,int data_len)
  230. {
  231.     int ret;
  232.     
  233.     ret = write(fd,send_buf,data_len);
  234.     if (data_len == ret ){    
  235.      return ret;
  236.     } else {
  237.      tcflush(fd,TCOFLUSH);
  238.      return FALSE;
  239.         
  240.     }
  241.     
  242. }




  243. int main(int argc, char **argv)
  244. {
  245.     int fd = FALSE;             
  246.     int ret;                          
  247.     char rcv_buf[512];
  248.     int i;
  249.     if(argc != 2){
  250.      printf("Usage: %s /dev/ttySn \n",argv[0]);    
  251.      return FALSE;    
  252.     }
  253.     fd = UART_Open(fd,argv[1]);
  254.     if(FALSE == fd){    
  255.      printf("open error\n");    
  256.      exit(1);     
  257.     }
  258.     ret = UART_Init(fd,9600,0,8,1,'N');
  259.     if (FALSE == fd){    
  260.      printf("Set Port Error\n");    
  261.      exit(1);
  262.     }
  263.     
  264.     ret = UART_Send(fd,"*IDN?\n",6);
  265.     if(FALSE == ret){
  266.      printf("write error!\n");
  267.      exit(1);
  268.     }
  269.     
  270.     printf("command: %s\n","*IDN?");
  271.     memset(rcv_buf,0,sizeof(rcv_buf));
  272.     for(i=0;;i++)
  273.     {
  274.      ret = UART_Recv(fd, rcv_buf,512);    
  275.          if( ret > 0){
  276.          rcv_buf[ret]='\0';        
  277.          printf("%s",rcv_buf);    
  278.      } else {    
  279.      printf("cannot receive data1\n");    
  280.             break;
  281.      }
  282.      if('\n' == rcv_buf[ret-1])
  283.          break;
  284.     }
  285.     UART_Close(fd);
  286.     return 0;
  287. }

阅读(5237) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~