Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1247033
  • 博文数量: 105
  • 博客积分: 127
  • 博客等级: 入伍新兵
  • 技术积分: 962
  • 用 户 组: 普通用户
  • 注册时间: 2011-01-29 15:22
文章分类

全部博文(105)

文章存档

2021年(1)

2019年(3)

2018年(1)

2017年(11)

2016年(47)

2015年(32)

2014年(4)

2012年(6)

我的朋友

分类: LINUX

2016-07-30 12:39:58


  linux 串口自环测试程序。两种不同的方法。select ,以及多线程方法。

 select uart_sendrecv_notv.rar

点击(此处)折叠或打开

  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 <unistd.h>
  10. #include <string.h>
  11. #define DEVICE "/dev/ttyUSB0"

  12. #define S_TIMEOUT 1
  13.   
  14. int serial_fd = 0;
  15.   
  16. //打开串口并初始化设置

  17. init_serial(void)
  18. {
  19.     serial_fd = open(DEVICE, O_RDWR | O_NOCTTY | O_NDELAY);
  20.     if (serial_fd < 0) {
  21.         perror("open");
  22.         return -1;
  23.     }
  24.       
  25.     //串口主要设置结构体termios <termios.h>
  26.     struct termios options;
  27.       
  28.     /**1. tcgetattr函数用于获取与终端相关的参数。
  29.     *参数fd为终端的文件描述符,返回的结果保存在termios结构体中
  30.     */
  31.     tcgetattr(serial_fd, &options);
  32.     /**2. 修改所获得的参数*/
  33.     options.c_cflag |= (CLOCAL | CREAD);//设置控制模式状态,本地连接,接收使能
  34.     options.c_cflag &= ~CSIZE;//字符长度,设置数据位之前一定要屏掉这个位
  35.     options.c_cflag &= ~CRTSCTS;//无硬件流控
  36.     options.c_cflag |= CS8;//8位数据长度
  37.     options.c_cflag &= ~CSTOPB;//1位停止位
  38.     options.c_iflag |= IGNPAR;//无奇偶检验位
  39.     options.c_oflag = 0; //输出模式
  40.     options.c_lflag = 0; //不激活终端模式
  41.     cfsetospeed(&options, B115200);//设置波特率
  42.       
  43.     /**3. 设置新属性,TCSANOW:所有改变立即生效*/
  44.     tcflush(serial_fd, TCIFLUSH);//溢出数据可以接收,但不读
  45.     tcsetattr(serial_fd, TCSANOW, &options);
  46.       
  47.     return 0;
  48. }
  49.   
  50. /**
  51. *串口发送数据
  52. *@fd:串口描述符
  53. *@data:待发送数据
  54. *@datalen:数据长度
  55. */
  56. unsigned int total_send = 0 ;
  57. int uart_send(int fd, char *data, int datalen)
  58. {
  59.     int len = 0;
  60.     len = write(fd, data, datalen);//实际写入的长度
  61.     if(len == datalen) {
  62.     total_send += len ;
  63.         printf("total_send is %d\n",total_send);
  64.         return len;
  65.     } else {
  66.         tcflush(fd, TCOFLUSH);//TCOFLUSH刷新写入的数据但不传送
  67.         return -1;
  68.     }
  69.     return 0;
  70. }
  71.   
  72. /**
  73. *串口接收数据
  74. *要求启动后,在pc端发送ascii文件
  75. */
  76. unsigned int total_length = 0 ;
  77. int uart_recv(int fd, char *data, int datalen)
  78. {
  79.     int len=0, ret = 0;
  80.     fd_set fs_read;
  81.     struct timeval tv_timeout;
  82.       
  83.     FD_ZERO(&fs_read);
  84.     FD_SET(fd, &fs_read);

  85. #ifdef S_TIMEOUT    
  86.     tv_timeout.tv_sec = (10*20/115200+2);
  87.     tv_timeout.tv_usec = 0;
  88.     ret = select(fd+1, &fs_read, NULL, NULL, NULL);
  89. #elif
  90.     ret = select(fd+1, &fs_read, NULL, NULL, tv_timeout);
  91. #endif

  92. // printf("ret = %d\n", ret);
  93.     //如果返回0,代表在描述符状态改变前已超过timeout时间,错误返回-1
  94.      
  95.     if (FD_ISSET(fd, &fs_read)) {
  96.         len = read(fd, data, datalen);
  97.     total_length += len ;
  98.         printf("total len = %d\n", total_length);
  99.         return len;
  100.     } else {
  101.         perror("select");
  102.         return -1;
  103.     }
  104.       
  105.     return 0;
  106. }
  107.   
  108. int main(int argc, char **argv)
  109. {
  110.     init_serial();
  111.   
  112.     char buf[]="hello world";
  113.     char buf1[11] ;
  114.     memset(buf1,0,sizeof(char)*11);
  115.         
  116.     while(1)
  117.     {
  118.         uart_send(serial_fd, buf, 11);
  119.         printf("\n");
  120.         sleep(1);
  121.         //if(uart_recv(serial_fd, buf1, 11) > 0)
  122.         uart_recv(serial_fd, buf1, 11);
  123.         printf("receive: %s\n", buf1);
  124.         memset(buf1,0,sizeof(char)*11);
  125.     }

  126.     close(serial_fd);
  127.     return 0;
  128. }


  多线程方法sertest.rar

点击(此处)折叠或打开

  1. /****************************************************************************
  2. *
  3. * Copyright (c) 2006 Dave Hylands <dhylands@gmail.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * Alternatively, this software may be distributed under the terms of BSD
  10. * license.
  11. *
  12. * See README and COPYING for more details.
  13. *
  14. ****************************************************************************/
  15. /**
  16. *
  17. * sertest.c
  18. *
  19. * PURPOSE:
  20. *
  21. * This implements a sample program for accessing the serial port.
  22. *
  23. *****************************************************************************/

  24. /* ---- Include Files ---------------------------------------------------- */

  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <errno.h>
  29. #include <fcntl.h>
  30. #include <sys/ioctl.h>
  31. #include <sys/unistd.h>
  32. #include <pthread.h>
  33. #include <signal.h>
  34. #include <getopt.h>
  35. #include <termios.h>

  36. /* ---- Public Variables ------------------------------------------------- */

  37. int gFd = -1;

  38. int gVal;

  39. /* ---- Private Constants and Types -------------------------------------- */
  40. /* ---- Private Variables ------------------------------------------------ */

  41. struct option gLongOption[] =
  42. {
  43.     // option A Flag V (has_arg, flag, val)
  44.     // ----------- - ---- ---
  45.     { "baud", 1, NULL, 'b' },
  46.     { "debug", 0, NULL, 'd' },
  47.     { "help", 0, NULL, 'h' },
  48.     { "port", 1, NULL, 'p' },
  49.     { "verbose", 0, NULL, 'v' },
  50.     { 0 },

  51. };

  52. struct
  53. {
  54.     speed_t speed;
  55.     unsigned baudRate;
  56. } gBaudTable[] =
  57. {
  58.     { B50, 50 },
  59.     { B75, 75 },
  60.     { B110, 110 },
  61.     { B134, 134 },
  62.     { B150, 150 },
  63.     { B200, 200 },
  64.     { B300, 300 },
  65.     { B600, 600 },
  66.     { B1200, 1200 },
  67.     { B1800, 1800 },
  68.     { B2400, 2400 },
  69.     { B4800, 4800 },
  70.     { B9600, 9600 },
  71.     { B19200, 19200 },
  72.     { B38400, 38400 },
  73.     { B57600, 57600 },
  74.     { B115200, 115200 },
  75.     { B230400, 230400 }
  76. };

  77. #define ARRAY_LEN(x) ( sizeof( x ) / sizeof( x[ 0 ]))

  78. int gVerbose = 0;
  79. int gDebug = 0;

  80. int gPortFd = -1;

  81. /* ---- Private Function Prototypes -------------------------------------- */

  82. void *ReadSerialThread( void *param );
  83. void *ReadStdinThread( void *param );
  84. char *StrMaxCpy( char *dst, const char *src, size_t maxLen );
  85. char *StrMaxCat( char *dst, const char *src, size_t maxLen );
  86. void Usage( void );

  87. /* ---- Functions -------------------------------------------------------- */

  88. #if defined(__CYGWIN__)
  89. // Cygwin seems to be missing cfmakeraw, so we provide a copy here.
  90. static void cfmakeraw(struct termios *termios_p)
  91. {
  92.     termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
  93.     termios_p->c_oflag &= ~OPOST;
  94.     termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
  95.     termios_p->c_cflag &= ~(CSIZE|PARENB);
  96.     termios_p->c_cflag |= CS8;
  97. }
  98. #endif /* defined(__CYGWIN__) */



  99. /***************************************************************************
  100. *
  101. * main
  102. *
  103. ****************************************************************************/

  104. int main( int argc, char **argv )
  105. {
  106.     int sig;
  107.     int rc;
  108.     int opt;
  109.     char devName[ 40 ];
  110.     const char *baudStr = NULL;
  111.     const char *portStr = "ttyS2";
  112.     speed_t baudRate;
  113.     sigset_t termSig;
  114.     pthread_t readSerialThreadId;
  115.     pthread_t readStdinThreadId;
  116.     struct termios stdin_tio;
  117.     struct termios stdin_tio_org;

  118.     struct termios attr;

  119.     // Parse the command line options

  120.     while (( opt = getopt_long( argc, argv, "b:dhp:v", gLongOption, NULL )) > 0 )
  121.     {
  122.         switch ( opt )
  123.         {
  124.             case 'b':
  125.             {
  126.                 baudStr = optarg;
  127.                 break;
  128.             }

  129.             case 'd':
  130.             {
  131.                 gDebug = 1;
  132.                 break;
  133.             }

  134.             case 'p':
  135.             {
  136.                 portStr = optarg;
  137.                 break;
  138.             }

  139.             case 'v':
  140.             {
  141.                 gVerbose = 1;
  142.                 break;
  143.             }
  144.             case '?':
  145.             case 'h':
  146.             {
  147.                 Usage();
  148.                 return 1;
  149.             }
  150.         }
  151.     }

  152.     devName[ 0 ] = '\0';
  153.     if ( portStr[ 0 ] != '/' )
  154.     {
  155.         StrMaxCpy( devName, "/dev/", sizeof( devName ));
  156.     }
  157.     StrMaxCat( devName, portStr, sizeof( devName ));


  158.     baudRate = B0;
  159.     if ( baudStr == NULL )
  160.     {
  161.         baudRate = B9600;
  162.     }
  163.     else
  164.     {
  165.         int baudIdx;
  166.         int testBaud = atoi( baudStr );

  167.         for ( baudIdx = 0; baudIdx < ARRAY_LEN( gBaudTable ); baudIdx++ )
  168.         {
  169.             if ( gBaudTable[ baudIdx ].baudRate == testBaud )
  170.             {
  171.                 baudRate = gBaudTable[ baudIdx ].speed;
  172.                 break;
  173.             }
  174.         }

  175.         if ( baudRate == B0 )
  176.         {
  177.             fprintf( stderr, "Unrecognized baud rate: '%s'\n", baudStr );
  178.             exit( 1 );
  179.         }
  180.     }

  181.     // Open the serial port initially using O_NONBLOCK so that we won't block waiting for
  182.     // carrier detect.

  183.     if (( gPortFd = open( devName, O_RDWR | O_EXCL | O_NONBLOCK )) < 0 )
  184.     {
  185.         fprintf( stderr, "Unable to open serial port '%s': %s\n", devName, strerror( errno ));
  186.         exit( 2 );
  187.     }

  188.     // Now that the serial port is open, we can turn off the non-blocking behaviour (for us we want
  189.     // the reads to have blocking semantics).

  190.     fcntl( gPortFd, F_SETFL, fcntl( gPortFd, F_GETFL ) & ~O_NONBLOCK );

  191.     if ( tcgetattr( gPortFd, &attr ) < 0 )
  192.     {
  193.         fprintf( stderr, "Call to tcgetattr failed: %s\n", strerror( errno ));
  194.         exit( 3 );
  195.     }

  196.     cfmakeraw( &attr );

  197.     // CLOCAL - Disable modem control lines
  198.     // CREAD - Enable Receiver

  199.     attr.c_cflag |= ( CLOCAL | CREAD );

  200.     cfsetispeed( &attr, baudRate );
  201.     cfsetospeed( &attr, baudRate );

  202.     if ( tcsetattr( gPortFd, TCSAFLUSH, &attr ) < 0 )
  203.     {
  204.         fprintf( stderr, "Call to tcsetattr failed: %s\n", strerror( errno ));
  205.         exit( 4 );
  206.     }

  207.     // Put stdin & stdout in unbuffered mode.

  208.     setbuf( stdin, NULL );
  209.     setbuf( stdout, NULL );

  210.     sigemptyset( &termSig );
  211.     sigaddset( &termSig, SIGINT );
  212.     sigaddset( &termSig, SIGTERM );

  213.     pthread_sigmask( SIG_BLOCK, &termSig, NULL );

  214.     // Put stdin in raw mode (i.e. turn off canonical mode). Canonical mode
  215.     // causes the driver to wait for the RETURN character so that line editing
  216.     // can take place. We also want to turn off ECHO.

  217.     if ( tcgetattr( fileno( stdin ), &stdin_tio_org ) < 0 )
  218.     {
  219.         fprintf( stderr, "Unable to retrieve terminal settings: %s\n", strerror( errno ));
  220.         exit( 5 );
  221.     }

  222.     stdin_tio = stdin_tio_org;
  223.     stdin_tio.c_lflag &= ~( ICANON | ECHO );
  224.     stdin_tio.c_cc[VTIME] = 0;
  225.     stdin_tio.c_cc[VMIN] = 1;

  226.     if ( tcsetattr( fileno( stdin ), TCSANOW, &stdin_tio ) < 0 )
  227.     {
  228.         fprintf( stderr, "Unable to update terminal settings: %s\n", strerror( errno ));
  229.         exit( 6 );
  230.     }

  231.     // Kick off the serial port reader thread.

  232.     rc = pthread_create( &readSerialThreadId, NULL, ReadSerialThread, NULL );
  233.     if ( rc != 0 )
  234.     {
  235.         fprintf( stderr, "Error creating ReadSerialThread: %s\n", strerror( rc ));
  236.         exit( 7 );
  237.     }

  238.     // Kick off the stdin reader thread

  239.     rc = pthread_create( &readStdinThreadId, NULL, ReadStdinThread, NULL );
  240.     if ( rc != 0 )
  241.     {
  242.         fprintf( stderr, "Error creating ReadStdinThread: %s\n", strerror( rc ));
  243.         exit( 7 );
  244.     }

  245.     // Wait for a termmination signal

  246.     if (( rc = sigwait( &termSig, &sig )) != 0 )
  247.     {
  248.         fprintf( stderr, "sigwait failed\n" );
  249.     }
  250.     else
  251.     {
  252.         fprintf( stderr, "Exiting...\n" );
  253.     }

  254.     pthread_cancel( readSerialThreadId );
  255.     pthread_cancel( readStdinThreadId );

  256.     // Restore stdin back to the way it was when we started

  257.     if ( tcsetattr( fileno( stdin ), TCSANOW, &stdin_tio_org ) < 0 )
  258.     {
  259.         fprintf( stderr, "Unable to update terminal settings: %s\n", strerror( errno ));
  260.         exit( 6 );
  261.     }

  262.     // Unblock the termination signals so the user can kill us if we hang up
  263.     // waiting for the reader threads to exit.

  264.     pthread_sigmask( SIG_UNBLOCK, &termSig, NULL );

  265.     pthread_join( readSerialThreadId, NULL );
  266.     pthread_join( readStdinThreadId, NULL );

  267.     close( gPortFd );

  268.     if ( gVerbose )
  269.     {
  270.         fprintf( stderr, "Done\n" );
  271.     }

  272.     exit( 0 );
  273.     return 0; // Get rid of warning about not returning anything
  274. }

  275. /***************************************************************************/
  276. /**
  277. * Thread which processes the incoming serial data.
  278. */

  279. void *ReadSerialThread( void *param )
  280. {
  281.     while ( 1 )
  282.     {
  283.         char ch;
  284.         int bytesRead;

  285.         if (( bytesRead = read( gPortFd, &ch, 10 )) < 0 )
  286.         {
  287.             fprintf( stderr, "Serial port read failed: %s\n", strerror( errno ));
  288.             exit( 1 );
  289.         }

  290.         if ( gDebug )
  291.         {
  292.             if (( ch < ' ' ) || ( ch > '~' ))
  293.             {
  294.                 fprintf( stderr, "Serial Read: 0x%02x '.'\n", ch );
  295.             }
  296.             else
  297.             {
  298.                 fprintf( stderr, "Serial Read: 0x%02x '%c'\n", ch, ch );
  299.             }

  300.         }

  301.         putc( ch, stdout );
  302.     }

  303.     return NULL;

  304. } // ReadSerialThread

  305. /***************************************************************************/
  306. /**
  307. * Thread which processes the incoming serial from stdin.
  308. */

  309. void *ReadStdinThread( void *param )
  310. {
  311.     while ( 1 )
  312.     {
  313.         char ch;
  314.         int chInt = fgetc( stdin );
  315.         if ( chInt < 0 )
  316.         {
  317.             fprintf( stderr, "Error reading stdin...\n" );
  318.             break;
  319.         }
  320.         ch = (char)chInt;

  321.         if ( gDebug )
  322.         {
  323.             if (( ch < ' ' ) || ( ch > '~' ))
  324.             {
  325.                 fprintf( stderr, "stdin Read: 0x%02x '.'\n", ch );
  326.             }
  327.             else
  328.             {
  329.                 fprintf( stderr, "stdin Read: 0x%02x '%c'\n", ch, ch );
  330.             }

  331.         }

  332.         if ( write( gPortFd, &ch, 1 ) != 1 )
  333.         {
  334.             fprintf( stderr, "write to serial port failed: %s\n", strerror( errno ));
  335.             break;
  336.         }
  337.     }

  338.     return NULL;

  339. } // ReadStdinThread

  340. /***************************************************************************/
  341. /**
  342. * Concatenates source to the destination, but makes sure that the
  343. * destination string (including terminating null), doesn't exceed maxLen.
  344. *
  345. * @param dst (mod) String to concatnate onto.
  346. * @param src (in) String to being added to the end of @a dst.
  347. * @param maxLen (in) Maximum length that @a dst is allowed to be.
  348. *
  349. * @return A pointer to the destination string.
  350. */

  351. char *StrMaxCat( char *dst, const char *src, size_t maxLen )
  352. {
  353.         size_t dstLen = strlen( dst );

  354.         if ( dstLen < maxLen )
  355.         {
  356.                 StrMaxCpy( &dst[ dstLen ], src, maxLen - dstLen );
  357.         }

  358.         return dst;

  359. } /* StrMaxCat */

  360. /***************************************************************************/
  361. /**
  362. * Copies the source to the destination, but makes sure that the
  363. * destination string (including terminating null), doesn't exceed
  364. * maxLen.
  365. *
  366. * @param dst (out) Place to store the string copy.
  367. * @param src (in) String to copy.
  368. * @param maxLen (in) Maximum number of characters to copy into @a dst.
  369. *
  370. * @return A pointer to the destination string.
  371. */

  372. char *StrMaxCpy( char *dst, const char *src, size_t maxLen )
  373. {
  374.         if ( maxLen < 1 )
  375.         {
  376.                 /*
  377.                  * There's no room in the buffer?
  378.                  */

  379.                 return "";
  380.         }

  381.         if ( maxLen == 1 )
  382.         {
  383.                 /*
  384.                  * There's only room for the terminating null character
  385.                  */

  386.                 dst[ 0 ] = '\0';
  387.                 return dst;
  388.         }

  389.         /*
  390.          * The Visual C++ version of strncpy writes to every single character
  391.          * of the destination buffer, so we use a length one character smaller
  392.          * and write in our own null (if required).
  393.      *
  394.      * This allows the caller to store a sentinel in the last byte of the
  395.      * buffer to detect overflows (if desired).
  396.          */

  397.         strncpy( dst, src, maxLen - 1 );
  398.         if (( strlen( src ) + 1 ) >= maxLen )
  399.         {
  400.                 /*
  401.                  * The string exactly fits, or probably overflows the buffer.
  402.                  * Write in the terminating null character since strncpy doesn't in
  403.                  * this particular case.
  404.                  *
  405.                  * We don't do this arbitrarily so that the caller can use a sentinel
  406.                  * in the very end of the buffer to detect buffer overflows.
  407.                  */

  408.                 dst[ maxLen - 1 ] = '\0';
  409.         }

  410.         return dst;

  411. } /* StrMaxCpy */

  412. /***************************************************************************
  413. *
  414. * Usage
  415. *
  416. ****************************************************************************/

  417. void Usage()
  418. {
  419.     fprintf( stderr, "Usage: sertest [option(s)]\n" );
  420.     fprintf( stderr, " Download a program via serial/i2c\n" );
  421.     fprintf( stderr, "\n" );
  422.     fprintf( stderr, " -b, --baud=baud Set the baudrate used\n" );
  423.     fprintf( stderr, " -d, --debug Turn on debug output\n" );
  424.     fprintf( stderr, " -h, --help Display this message\n" );
  425.     fprintf( stderr, " -p, --port=port Set the I/O port\n" );
  426.     fprintf( stderr, " -v, --verbose Turn on verbose messages\n" );

  427. } // Usage
                                                                                                                                                                                                                                  
阅读(7094) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~