linux 串口自环测试程序。两种不同的方法。select ,以及多线程方法。
select uart_sendrecv_notv.rar
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <unistd.h>
-
#include <sys/types.h>
-
#include <sys/stat.h>
-
#include <fcntl.h> //文件控制定义
-
#include <termios.h>//终端控制定义
-
#include <errno.h>
-
#include <unistd.h>
-
#include <string.h>
-
#define DEVICE "/dev/ttyUSB0"
-
-
#define S_TIMEOUT 1
-
-
int serial_fd = 0;
-
-
//打开串口并初始化设置
-
-
init_serial(void)
-
{
-
serial_fd = open(DEVICE, O_RDWR | O_NOCTTY | O_NDELAY);
-
if (serial_fd < 0) {
-
perror("open");
-
return -1;
-
}
-
-
//串口主要设置结构体termios <termios.h>
-
struct termios options;
-
-
/**1. tcgetattr函数用于获取与终端相关的参数。
-
*参数fd为终端的文件描述符,返回的结果保存在termios结构体中
-
*/
-
tcgetattr(serial_fd, &options);
-
/**2. 修改所获得的参数*/
-
options.c_cflag |= (CLOCAL | CREAD);//设置控制模式状态,本地连接,接收使能
-
options.c_cflag &= ~CSIZE;//字符长度,设置数据位之前一定要屏掉这个位
-
options.c_cflag &= ~CRTSCTS;//无硬件流控
-
options.c_cflag |= CS8;//8位数据长度
-
options.c_cflag &= ~CSTOPB;//1位停止位
-
options.c_iflag |= IGNPAR;//无奇偶检验位
-
options.c_oflag = 0; //输出模式
-
options.c_lflag = 0; //不激活终端模式
-
cfsetospeed(&options, B115200);//设置波特率
-
-
/**3. 设置新属性,TCSANOW:所有改变立即生效*/
-
tcflush(serial_fd, TCIFLUSH);//溢出数据可以接收,但不读
-
tcsetattr(serial_fd, TCSANOW, &options);
-
-
return 0;
-
}
-
-
/**
-
*串口发送数据
-
*@fd:串口描述符
-
*@data:待发送数据
-
*@datalen:数据长度
-
*/
-
unsigned int total_send = 0 ;
-
int uart_send(int fd, char *data, int datalen)
-
{
-
int len = 0;
-
len = write(fd, data, datalen);//实际写入的长度
-
if(len == datalen) {
-
total_send += len ;
-
printf("total_send is %d\n",total_send);
-
return len;
-
} else {
-
tcflush(fd, TCOFLUSH);//TCOFLUSH刷新写入的数据但不传送
-
return -1;
-
}
-
return 0;
-
}
-
-
/**
-
*串口接收数据
-
*要求启动后,在pc端发送ascii文件
-
*/
-
unsigned int total_length = 0 ;
-
int uart_recv(int fd, char *data, int datalen)
-
{
-
int len=0, ret = 0;
-
fd_set fs_read;
-
struct timeval tv_timeout;
-
-
FD_ZERO(&fs_read);
-
FD_SET(fd, &fs_read);
-
-
#ifdef S_TIMEOUT
-
tv_timeout.tv_sec = (10*20/115200+2);
-
tv_timeout.tv_usec = 0;
-
ret = select(fd+1, &fs_read, NULL, NULL, NULL);
-
#elif
-
ret = select(fd+1, &fs_read, NULL, NULL, tv_timeout);
-
#endif
-
-
// printf("ret = %d\n", ret);
-
//如果返回0,代表在描述符状态改变前已超过timeout时间,错误返回-1
-
-
if (FD_ISSET(fd, &fs_read)) {
-
len = read(fd, data, datalen);
-
total_length += len ;
-
printf("total len = %d\n", total_length);
-
return len;
-
} else {
-
perror("select");
-
return -1;
-
}
-
-
return 0;
-
}
-
-
int main(int argc, char **argv)
-
{
-
init_serial();
-
-
char buf[]="hello world";
-
char buf1[11] ;
-
memset(buf1,0,sizeof(char)*11);
-
-
while(1)
-
{
-
uart_send(serial_fd, buf, 11);
-
printf("\n");
-
sleep(1);
-
//if(uart_recv(serial_fd, buf1, 11) > 0)
-
uart_recv(serial_fd, buf1, 11);
-
printf("receive: %s\n", buf1);
-
memset(buf1,0,sizeof(char)*11);
-
}
-
-
close(serial_fd);
-
return 0;
-
}
多线程方法sertest.rar
-
/****************************************************************************
-
*
-
* Copyright (c) 2006 Dave Hylands <dhylands@gmail.com>
-
*
-
* This program is free software; you can redistribute it and/or modify
-
* it under the terms of the GNU General Public License version 2 as
-
* published by the Free Software Foundation.
-
*
-
* Alternatively, this software may be distributed under the terms of BSD
-
* license.
-
*
-
* See README and COPYING for more details.
-
*
-
****************************************************************************/
-
/**
-
*
-
* sertest.c
-
*
-
* PURPOSE:
-
*
-
* This implements a sample program for accessing the serial port.
-
*
-
*****************************************************************************/
-
-
/* ---- Include Files ---------------------------------------------------- */
-
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <string.h>
-
#include <errno.h>
-
#include <fcntl.h>
-
#include <sys/ioctl.h>
-
#include <sys/unistd.h>
-
#include <pthread.h>
-
#include <signal.h>
-
#include <getopt.h>
-
#include <termios.h>
-
-
/* ---- Public Variables ------------------------------------------------- */
-
-
int gFd = -1;
-
-
int gVal;
-
-
/* ---- Private Constants and Types -------------------------------------- */
-
/* ---- Private Variables ------------------------------------------------ */
-
-
struct option gLongOption[] =
-
{
-
// option A Flag V (has_arg, flag, val)
-
// ----------- - ---- ---
-
{ "baud", 1, NULL, 'b' },
-
{ "debug", 0, NULL, 'd' },
-
{ "help", 0, NULL, 'h' },
-
{ "port", 1, NULL, 'p' },
-
{ "verbose", 0, NULL, 'v' },
-
{ 0 },
-
-
};
-
-
struct
-
{
-
speed_t speed;
-
unsigned baudRate;
-
} gBaudTable[] =
-
{
-
{ B50, 50 },
-
{ B75, 75 },
-
{ B110, 110 },
-
{ B134, 134 },
-
{ B150, 150 },
-
{ B200, 200 },
-
{ B300, 300 },
-
{ B600, 600 },
-
{ B1200, 1200 },
-
{ B1800, 1800 },
-
{ B2400, 2400 },
-
{ B4800, 4800 },
-
{ B9600, 9600 },
-
{ B19200, 19200 },
-
{ B38400, 38400 },
-
{ B57600, 57600 },
-
{ B115200, 115200 },
-
{ B230400, 230400 }
-
};
-
-
#define ARRAY_LEN(x) ( sizeof( x ) / sizeof( x[ 0 ]))
-
-
int gVerbose = 0;
-
int gDebug = 0;
-
-
int gPortFd = -1;
-
-
/* ---- Private Function Prototypes -------------------------------------- */
-
-
void *ReadSerialThread( void *param );
-
void *ReadStdinThread( void *param );
-
char *StrMaxCpy( char *dst, const char *src, size_t maxLen );
-
char *StrMaxCat( char *dst, const char *src, size_t maxLen );
-
void Usage( void );
-
-
/* ---- Functions -------------------------------------------------------- */
-
-
#if defined(__CYGWIN__)
-
// Cygwin seems to be missing cfmakeraw, so we provide a copy here.
-
static void cfmakeraw(struct termios *termios_p)
-
{
-
termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
-
termios_p->c_oflag &= ~OPOST;
-
termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
-
termios_p->c_cflag &= ~(CSIZE|PARENB);
-
termios_p->c_cflag |= CS8;
-
}
-
#endif /* defined(__CYGWIN__) */
-
-
-
-
/***************************************************************************
-
*
-
* main
-
*
-
****************************************************************************/
-
-
int main( int argc, char **argv )
-
{
-
int sig;
-
int rc;
-
int opt;
-
char devName[ 40 ];
-
const char *baudStr = NULL;
-
const char *portStr = "ttyS2";
-
speed_t baudRate;
-
sigset_t termSig;
-
pthread_t readSerialThreadId;
-
pthread_t readStdinThreadId;
-
struct termios stdin_tio;
-
struct termios stdin_tio_org;
-
-
struct termios attr;
-
-
// Parse the command line options
-
-
while (( opt = getopt_long( argc, argv, "b:dhp:v", gLongOption, NULL )) > 0 )
-
{
-
switch ( opt )
-
{
-
case 'b':
-
{
-
baudStr = optarg;
-
break;
-
}
-
-
case 'd':
-
{
-
gDebug = 1;
-
break;
-
}
-
-
case 'p':
-
{
-
portStr = optarg;
-
break;
-
}
-
-
case 'v':
-
{
-
gVerbose = 1;
-
break;
-
}
-
case '?':
-
case 'h':
-
{
-
Usage();
-
return 1;
-
}
-
}
-
}
-
-
devName[ 0 ] = '\0';
-
if ( portStr[ 0 ] != '/' )
-
{
-
StrMaxCpy( devName, "/dev/", sizeof( devName ));
-
}
-
StrMaxCat( devName, portStr, sizeof( devName ));
-
-
-
baudRate = B0;
-
if ( baudStr == NULL )
-
{
-
baudRate = B9600;
-
}
-
else
-
{
-
int baudIdx;
-
int testBaud = atoi( baudStr );
-
-
for ( baudIdx = 0; baudIdx < ARRAY_LEN( gBaudTable ); baudIdx++ )
-
{
-
if ( gBaudTable[ baudIdx ].baudRate == testBaud )
-
{
-
baudRate = gBaudTable[ baudIdx ].speed;
-
break;
-
}
-
}
-
-
if ( baudRate == B0 )
-
{
-
fprintf( stderr, "Unrecognized baud rate: '%s'\n", baudStr );
-
exit( 1 );
-
}
-
}
-
-
// Open the serial port initially using O_NONBLOCK so that we won't block waiting for
-
// carrier detect.
-
-
if (( gPortFd = open( devName, O_RDWR | O_EXCL | O_NONBLOCK )) < 0 )
-
{
-
fprintf( stderr, "Unable to open serial port '%s': %s\n", devName, strerror( errno ));
-
exit( 2 );
-
}
-
-
// Now that the serial port is open, we can turn off the non-blocking behaviour (for us we want
-
// the reads to have blocking semantics).
-
-
fcntl( gPortFd, F_SETFL, fcntl( gPortFd, F_GETFL ) & ~O_NONBLOCK );
-
-
if ( tcgetattr( gPortFd, &attr ) < 0 )
-
{
-
fprintf( stderr, "Call to tcgetattr failed: %s\n", strerror( errno ));
-
exit( 3 );
-
}
-
-
cfmakeraw( &attr );
-
-
// CLOCAL - Disable modem control lines
-
// CREAD - Enable Receiver
-
-
attr.c_cflag |= ( CLOCAL | CREAD );
-
-
cfsetispeed( &attr, baudRate );
-
cfsetospeed( &attr, baudRate );
-
-
if ( tcsetattr( gPortFd, TCSAFLUSH, &attr ) < 0 )
-
{
-
fprintf( stderr, "Call to tcsetattr failed: %s\n", strerror( errno ));
-
exit( 4 );
-
}
-
-
// Put stdin & stdout in unbuffered mode.
-
-
setbuf( stdin, NULL );
-
setbuf( stdout, NULL );
-
-
sigemptyset( &termSig );
-
sigaddset( &termSig, SIGINT );
-
sigaddset( &termSig, SIGTERM );
-
-
pthread_sigmask( SIG_BLOCK, &termSig, NULL );
-
-
// Put stdin in raw mode (i.e. turn off canonical mode). Canonical mode
-
// causes the driver to wait for the RETURN character so that line editing
-
// can take place. We also want to turn off ECHO.
-
-
if ( tcgetattr( fileno( stdin ), &stdin_tio_org ) < 0 )
-
{
-
fprintf( stderr, "Unable to retrieve terminal settings: %s\n", strerror( errno ));
-
exit( 5 );
-
}
-
-
stdin_tio = stdin_tio_org;
-
stdin_tio.c_lflag &= ~( ICANON | ECHO );
-
stdin_tio.c_cc[VTIME] = 0;
-
stdin_tio.c_cc[VMIN] = 1;
-
-
if ( tcsetattr( fileno( stdin ), TCSANOW, &stdin_tio ) < 0 )
-
{
-
fprintf( stderr, "Unable to update terminal settings: %s\n", strerror( errno ));
-
exit( 6 );
-
}
-
-
// Kick off the serial port reader thread.
-
-
rc = pthread_create( &readSerialThreadId, NULL, ReadSerialThread, NULL );
-
if ( rc != 0 )
-
{
-
fprintf( stderr, "Error creating ReadSerialThread: %s\n", strerror( rc ));
-
exit( 7 );
-
}
-
-
// Kick off the stdin reader thread
-
-
rc = pthread_create( &readStdinThreadId, NULL, ReadStdinThread, NULL );
-
if ( rc != 0 )
-
{
-
fprintf( stderr, "Error creating ReadStdinThread: %s\n", strerror( rc ));
-
exit( 7 );
-
}
-
-
// Wait for a termmination signal
-
-
if (( rc = sigwait( &termSig, &sig )) != 0 )
-
{
-
fprintf( stderr, "sigwait failed\n" );
-
}
-
else
-
{
-
fprintf( stderr, "Exiting...\n" );
-
}
-
-
pthread_cancel( readSerialThreadId );
-
pthread_cancel( readStdinThreadId );
-
-
// Restore stdin back to the way it was when we started
-
-
if ( tcsetattr( fileno( stdin ), TCSANOW, &stdin_tio_org ) < 0 )
-
{
-
fprintf( stderr, "Unable to update terminal settings: %s\n", strerror( errno ));
-
exit( 6 );
-
}
-
-
// Unblock the termination signals so the user can kill us if we hang up
-
// waiting for the reader threads to exit.
-
-
pthread_sigmask( SIG_UNBLOCK, &termSig, NULL );
-
-
pthread_join( readSerialThreadId, NULL );
-
pthread_join( readStdinThreadId, NULL );
-
-
close( gPortFd );
-
-
if ( gVerbose )
-
{
-
fprintf( stderr, "Done\n" );
-
}
-
-
exit( 0 );
-
return 0; // Get rid of warning about not returning anything
-
}
-
-
/***************************************************************************/
-
/**
-
* Thread which processes the incoming serial data.
-
*/
-
-
void *ReadSerialThread( void *param )
-
{
-
while ( 1 )
-
{
-
char ch;
-
int bytesRead;
-
-
if (( bytesRead = read( gPortFd, &ch, 10 )) < 0 )
-
{
-
fprintf( stderr, "Serial port read failed: %s\n", strerror( errno ));
-
exit( 1 );
-
}
-
-
if ( gDebug )
-
{
-
if (( ch < ' ' ) || ( ch > '~' ))
-
{
-
fprintf( stderr, "Serial Read: 0x%02x '.'\n", ch );
-
}
-
else
-
{
-
fprintf( stderr, "Serial Read: 0x%02x '%c'\n", ch, ch );
-
}
-
-
}
-
-
putc( ch, stdout );
-
}
-
-
return NULL;
-
-
} // ReadSerialThread
-
-
/***************************************************************************/
-
/**
-
* Thread which processes the incoming serial from stdin.
-
*/
-
-
void *ReadStdinThread( void *param )
-
{
-
while ( 1 )
-
{
-
char ch;
-
int chInt = fgetc( stdin );
-
if ( chInt < 0 )
-
{
-
fprintf( stderr, "Error reading stdin...\n" );
-
break;
-
}
-
ch = (char)chInt;
-
-
if ( gDebug )
-
{
-
if (( ch < ' ' ) || ( ch > '~' ))
-
{
-
fprintf( stderr, "stdin Read: 0x%02x '.'\n", ch );
-
}
-
else
-
{
-
fprintf( stderr, "stdin Read: 0x%02x '%c'\n", ch, ch );
-
}
-
-
}
-
-
if ( write( gPortFd, &ch, 1 ) != 1 )
-
{
-
fprintf( stderr, "write to serial port failed: %s\n", strerror( errno ));
-
break;
-
}
-
}
-
-
return NULL;
-
-
} // ReadStdinThread
-
-
/***************************************************************************/
-
/**
-
* Concatenates source to the destination, but makes sure that the
-
* destination string (including terminating null), doesn't exceed maxLen.
-
*
-
* @param dst (mod) String to concatnate onto.
-
* @param src (in) String to being added to the end of @a dst.
-
* @param maxLen (in) Maximum length that @a dst is allowed to be.
-
*
-
* @return A pointer to the destination string.
-
*/
-
-
char *StrMaxCat( char *dst, const char *src, size_t maxLen )
-
{
-
size_t dstLen = strlen( dst );
-
-
if ( dstLen < maxLen )
-
{
-
StrMaxCpy( &dst[ dstLen ], src, maxLen - dstLen );
-
}
-
-
return dst;
-
-
} /* StrMaxCat */
-
-
/***************************************************************************/
-
/**
-
* Copies the source to the destination, but makes sure that the
-
* destination string (including terminating null), doesn't exceed
-
* maxLen.
-
*
-
* @param dst (out) Place to store the string copy.
-
* @param src (in) String to copy.
-
* @param maxLen (in) Maximum number of characters to copy into @a dst.
-
*
-
* @return A pointer to the destination string.
-
*/
-
-
char *StrMaxCpy( char *dst, const char *src, size_t maxLen )
-
{
-
if ( maxLen < 1 )
-
{
-
/*
-
* There's no room in the buffer?
-
*/
-
-
return "";
-
}
-
-
if ( maxLen == 1 )
-
{
-
/*
-
* There's only room for the terminating null character
-
*/
-
-
dst[ 0 ] = '\0';
-
return dst;
-
}
-
-
/*
-
* The Visual C++ version of strncpy writes to every single character
-
* of the destination buffer, so we use a length one character smaller
-
* and write in our own null (if required).
-
*
-
* This allows the caller to store a sentinel in the last byte of the
-
* buffer to detect overflows (if desired).
-
*/
-
-
strncpy( dst, src, maxLen - 1 );
-
if (( strlen( src ) + 1 ) >= maxLen )
-
{
-
/*
-
* The string exactly fits, or probably overflows the buffer.
-
* Write in the terminating null character since strncpy doesn't in
-
* this particular case.
-
*
-
* We don't do this arbitrarily so that the caller can use a sentinel
-
* in the very end of the buffer to detect buffer overflows.
-
*/
-
-
dst[ maxLen - 1 ] = '\0';
-
}
-
-
return dst;
-
-
} /* StrMaxCpy */
-
-
/***************************************************************************
-
*
-
* Usage
-
*
-
****************************************************************************/
-
-
void Usage()
-
{
-
fprintf( stderr, "Usage: sertest [option(s)]\n" );
-
fprintf( stderr, " Download a program via serial/i2c\n" );
-
fprintf( stderr, "\n" );
-
fprintf( stderr, " -b, --baud=baud Set the baudrate used\n" );
-
fprintf( stderr, " -d, --debug Turn on debug output\n" );
-
fprintf( stderr, " -h, --help Display this message\n" );
-
fprintf( stderr, " -p, --port=port Set the I/O port\n" );
-
fprintf( stderr, " -v, --verbose Turn on verbose messages\n" );
-
-
} // Usage
阅读(1569) | 评论(0) | 转发(0) |