六 linux串口编程

一.结构体

1.termios

struct termios  {    
	tcflag_t c_iflag;		/* 输入模式标志 */    
	tcflag_t c_oflag;		/* 输出模式标志 */    
	tcflag_t c_cflag;		/* 控制模式标志 */    
	tcflag_t c_lflag;		/* 本地模式标志 */    
	cc_t c_line;			/* 线路规程 */    
	cc_t c_cc[NCCS];		/* 控制字符 */    
	speed_t c_ispeed;		/* 输入速率 */    
	speed_t c_ospeed;		/* 输出速率 */
};

二.定义

1.类型定义

typedef unsigned char	cc_t;
typedef unsigned int	speed_t;
typedef unsigned int	tcflag_t;

2.c_cc

#define 	VINTR 	0	//中断 Ctrl-C
#define 	VQUIT 	1	//退出 Ctrl-Z
#define 	VERASE 	2	//擦除 空格BS
#define 	VKILL 	3	//删行 Ctrl-U
#define 	VEOF 	4	//文件结尾 Ctrl-D
#define 	VTIME 	5	//等待时间
#define 	VMIN 	6	//读取的最小字符数
#define 	VSWTC 	7	//
#define 	VSTART 	8	//软件流开始
#define 	VSTOP 	9	//软件流停止
#define 	VSUSP 	10	//
#define 	VEOL 	11	//行结尾 回车CR
#define 	VREPRINT 	12	//
#define 	VDISCARD 	13	//
#define 	VWERASE 	14	//
#define 	VLNEXT 	15	//
#define 	VEOL2 	16	//第二行结尾 进行LF

3.c_iflag

#define 	IGNBRK	0000001	//忽略任何中断条件
#define 	BRKINT	0000002	//传送SIGINT,当检测到中断
#define 	IGNPAR	0000004	//忽略校验错误
#define 	PARMRK	0000010	//标记校验错误
#define 	INPCK	0000020	//校验有效
#define 	ISTRIP	0000040	//剥离校验位
#define 	INLCR	0000100	//映射NL到CR
#define 	IGNCR	0000200	//忽略CR
#define 	ICRNL	0000400	//映射CR到NL
#define 	IUCLC	0001000	//映射大写到小写
#define 	IXON	0002000	//软件流控制输出作用
#define 	IXANY	0004000	//允许任何字符再次启动流
#define 	IXOFF	0010000	//软件流控制输入作用
#define 	IMAXBEL	0020000	//在输入线上回显BEL过长
#define 	IUTF8	0040000

4.c_oflag

#define 	OPOST	0000001	//输出后处理(不设置=行式输出)
#define 	OLCUC	0000002	//映射小写到大写
#define 	ONLCR	0000004	//映射NL到CR-NL
#define 	OCRNL	0000010	//映射CR到NL
#define 	ONOCR	0000020	//
#define 	ONLRET	0000040	//NL实现CR功能
#define 	OFILL	0000100	//对于延时用填充字符
#define 	OFDEL	0000200	//填充字符DEL
#define 	NLDLY	0000400	//在行之间,需要掩蔽延时
#define 	NL0	0000000	//NL没有延时
#define 	NL1	0000400	//在换行后,新的输出前延时100ms
#define 	CRDLY	0003000	//回车到左边,需要掩蔽的延时
#define  	CR0	0000000	//CR没有延时
#define  	CR1	0001000	//CR后的延时,依赖于当前的列位置
#define  	CR2	0002000	//CR后延时100ms
#define  	CR3	0003000	//CR后延时150ms
#define 	TABDLY	0014000	//TAB后需要延时
#define  	TAB0	0000000	//TAB后没有延时
#define  	TAB1	0004000	//TAB后的延时根据当前的列位置
#define  	TAB2	0010000	//TAB后延时100ms
#define  	TAB3	0014000	//TAB扩展为空格
#define  	XTABS	0014000	//
#define 	BSDLY	0020000	//BS后需要延时掩蔽
#define  	BS0	0000000	//BS后无延时
#define  	BS1	0020000	//BS后延时50ms
#define 	VTDLY	0040000	//VT后需要延时掩蔽
#define  VT0	0000000	//VT后无延时
#define  	VT1	0040000	//VT后延时2秒
#define 	FFDLY	0100000	//FF后需要延时掩蔽
#define 	FF0	0000000	//FF后无延时
#define  FF1	0100000	//FF后延时2秒

5.c_cflag

#define 	CBAUD	0010017		//波特率掩码
#define  	B0	0000000		//挂起
#define  	B50	0000001		//50 b/s
#define  	B75	0000002		//75 b/s
#define  	B110	0000003		//110 b/s
#define  	B134	0000004		//134.5 b/s
#define  	B150	0000005		//150 b/s
#define  	B200	0000006		//200 b/s
#define  	B300	0000007		//300 b/s
#define  	B600	0000010		//600 b/s
#define  	B1200	0000011		//1200 b/s
#define  	B1800	0000012		//1800 b/s
#define  	B2400	0000013		//2400 b/s
#define  	B4800	0000014		//4800 b/s
#define  	B9600	0000015		//9600 b/s
#define  	B19200	0000016		//19200 b/s
#define  	B38400	0000017		//38400 b/s
#define 	EXTA 	B19200		//外部时钟A
#define 	EXTB 	B38400		//外部时钟B
#define 	CSIZE	0000060		//位数据位掩码
#define 	CS5	0000000		//5位数据位
#define 	CS6	0000020		//6位数据位
#define 	CS7	0000040		//7位数据位
#define 	CS8	0000060		//8位数据位
#define 	CSTOPB	0000100		//2位停止位
#define 	CREAD	0000200		//接收有效
#define 	PARENB	0000400		//校验位有效
#define 	PARODD	0001000		//奇偶校验
#define 	HUPCL	0002000		//最后关闭后,挂起
#define 	CLOCAL	0004000		//本地线-不 改变端口的"拥有者"
#define 	CBAUDEX 	0010000		//
#define 	BOTHER 	0010000		//
#define 	B57600 	0010001		//57600 b/s
#define 	B115200 	0010002		//115200 b/s
#define 	B230400 	0010003		//230400 b/s
#define 	B460800 	0010004		//460800 b/s
#define 	B500000 	0010005		//500000 b/s
#define 	B576000 	0010006		//576000 b/s
#define 	B921600 	0010007		//921600 b/s
#define  B1000000 	0010010		//1000000 b/s
#define  B1152000 	0010011		//1152000 b/s
#define  B1500000 	0010012		//1500000 b/s
#define  B2000000 	0010013		//2000000 b/s
#define  B2500000 	0010014		//2500000 b/s
#define  B3000000 	0010015		//3000000 b/s
#define  B3500000 	0010016		//3500000 b/s
#define  B4000000 	0010017		//4000000 b/s
#define 	CIBAUD	002003600000	//输入波特率
#define 	CMSPAR  	010000000000	/* mark or space (stick) parity */
#define 	CRTSCTS	020000000000	/* flow control */

#define IBSHIFT	   16

6.c_lflag

#define ISIG	0000001	//使SIGINTR,SIGSUSP,SIGDSUSP,SIGQUIT等信号作用
#define ICANON	0000002	//设定规范canonical(或行式raw)
#define XCASE	0000004	//map uppercase\lowercase(废除)
#define ECHO	0000010	//回显输入字符
#define ECHOE	0000020	//回显擦除字符 BS-SP-BS
#define ECHOK	0000040	//在删除字符后,回显NL
#define ECHONL	0000100	//回显NL
#define NOFLSH	0000200	//不在中断后退出字符后刷新输入缓冲
#define TOSTOP	0000400	//传送SIGTTOU信号作为背景
#define ECHOCTL	0001000	//以^char方式回显控制字符和以~?方式显示删除字符
#define ECHOPRT	0002000	//回显提示有删除字符
#define ECHOKE	0004000	//BS-SP-BS整行,在有行删除时
#define FLUSHO	0010000	//刷新输出
#define PENDIN	0040000	//在下次读或输入时,将未决字符重打
#define IEXTEN	0100000	
#define EXTPROC	0200000

 7.其他

/* tcflow() and TCXONC use these */
#define	TCOOFF	0
#define	TCOON	1
#define	TCIOFF	2
#define	TCION	3

/* tcflush() and TCFLSH use these */
#define	TCIFLUSH		0
#define	TCOFLUSH		1
#define	TCIOFLUSH		2

/* tcsetattr 使用到这些参数*/
#define	TCSANOW		0	//立即改变,不等待数据结束
#define	TCSADRAIN		1	//等待直到所有的都传完
#define	TCSAFLUSH		2	//刷新输入输出缓冲,然后改变


三.API函数

1.基本操作

打开串口 O_NOCTTY表示不是系统终端,这样就不会受键盘Ctrl-C等操作影响

fd = open("/dev/ttyXXX", O_RDWR | O_NOCTTY | O_NDELAY);

写(返回写入字节数)

ssize_t write(int fildes, const void *buf, size_t nbyte);

读(返回读取字节数)

ssize_t read(int fildes, void *buf, size_t nbyte);

关闭串口

close(unsigned int fd)

控制

int fcntl(int fildes, int cmd, ...);
fcntl(fd,F_SETFD,FNDELAY);	//非阻塞
fcntl(fd,F_SETFD,0);		//阻塞

控制命令还有以下几个针对tty的(魔数为0x54xx或‘T’),具体使用参考tty_ioctl函数,

#define TCGETS		0x5401
#define TCSETS		0x5402
#define TCSETSW		0x5403
#define TCSETSF		0x5404
#define TCGETA		0x5405
#define TCSETA		0x5406
#define TCSETAW		0x5407
#define TCSETAF		0x5408
#define TCSBRK		0x5409
#define TCXONC		0x540A
#define TCFLSH		0x540B
#define TIOCEXCL	0x540C
#define TIOCNXCL	0x540D
#define TIOCSCTTY	0x540E
#define TIOCGPGRP	0x540F
#define TIOCSPGRP	0x5410
#define TIOCOUTQ	0x5411
#define TIOCSTI		0x5412
#define TIOCGWINSZ	0x5413
#define TIOCSWINSZ	0x5414
#define TIOCMGET	0x5415
#define TIOCMBIS	0x5416
#define TIOCMBIC	0x5417
#define TIOCMSET	0x5418
#define TIOCGSOFTCAR	0x5419
#define TIOCSSOFTCAR	0x541A
#define FIONREAD	0x541B
#define TIOCINQ		FIONREAD
#define TIOCLINUX	0x541C
#define TIOCCONS	0x541D
#define TIOCGSERIAL	0x541E
#define TIOCSSERIAL	0x541F
#define TIOCPKT		0x5420
#define FIONBIO		0x5421
#define TIOCNOTTY	0x5422
#define TIOCSETD	0x5423
#define TIOCGETD	0x5424
#define TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
#define TIOCSBRK	0x5427  /* BSD compatibility */
#define TIOCCBRK	0x5428  /* BSD compatibility */
#define TIOCGSID	0x5429  /* Return the session ID of FD */
#define TCGETS2		_IOR('T', 0x2A, struct termios2)
#define TCSETS2		_IOW('T', 0x2B, struct termios2)
#define TCSETSW2	_IOW('T', 0x2C, struct termios2)
#define TCSETSF2	_IOW('T', 0x2D, struct termios2)
#define TIOCGRS485	0x542E
#ifndef TIOCSRS485
#define TIOCSRS485	0x542F
#endif
#define TIOCGPTN	_IOR('T', 0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TIOCSPTLCK	_IOW('T', 0x31, int)  /* Lock/unlock Pty */
#define TCGETX		0x5432 /* SYS5 TCGETX compatibility */
#define TCSETX		0x5433
#define TCSETXF		0x5434
#define TCSETXW		0x5435
#define TIOCSIG		_IOW('T', 0x36, int)  /* pty: generate signal */

#define FIONCLEX	0x5450
#define FIOCLEX		0x5451
#define FIOASYNC	0x5452
#define TIOCSERCONFIG	0x5453
#define TIOCSERGWILD	0x5454
#define TIOCSERSWILD	0x5455
#define TIOCGLCKTRMIOS	0x5456
#define TIOCSLCKTRMIOS	0x5457
#define TIOCSERGSTRUCT	0x5458 /* For debugging only */
#define TIOCSERGETLSR   0x5459 /* Get line status register */
#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
#define TIOCSERSETMULTI 0x545B /* Set multiport config */

#define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
#define TIOCGICOUNT	0x545D	/* read serial port __inline__ interrupt counts */

2.串口设置

int tcgetattr(int fildes, struct termios *termios_p);//获取串口参数
int tcsetattr(int fildes, int optional_actions,const struct termios *termios_p);//设置串口参数
speed_t cfgetispeed(const struct termios *termios_p);//获取输入波特率
int cfsetispeed(struct termios *termios_p, speed_t speed);//设置输入波特率
speed_t cfgetospeed(const struct termios *termios_p);//获取输出波特率
int cfsetospeed(struct termios *termios_p, speed_tspeed);//设置输出波特率

大致这样使用

struct termios options;

tcgetattr(fd, &options);	//--------获取属性

//--------设置波特率
if(cfgetispeed(&options)!=B115200)	//获取输入波特率
	cfsetispeed(&options, B19200);	//设置输入波特率

cfsetospeed(&options, B19200);	//设置输出波特率
if(cfgetospeed(&options)!=B19200)	//获取输出波特率
	perror("set baud rates fail!\n");

//--------本地模式|串行数据接收
options.c_cflag!=(CLOCAL|CREAD);	

//--------设置数据位格式
ifdef UART_8N1
//8N1 - 无校验
	options.c_cflag &= ~PARENB;
	options.c_cflag &= ~CSTOPB;
	options.c_cflag &= ~CSIZE;
	options.c_cflag |= CS8;
#endif 

ifdef UART_7E1
//7E1 - 偶校验
	options.c_cflag |= PARENB;
	options.c_cflag &= ~PARODD;
	options.c_cflag &= ~CSTOPB;
	options.c_cflag &= ~CSIZE;
	options.c_cflag |= CS7;
#endif 

ifdef UART_7O1
//7O1 - 奇校验
	options.c_cflag |= PARENB;
	options.c_cflag |= PARODD;
	options.c_cflag &= ~CSTOPB;
	options.c_cflag &= ~CSIZE;
	options.c_cflag |= CS7;
#endif 

ifdef UART_7S1
//7S1 - 空校验设置同无校验
	options.c_cflag &= ~PARENB;
	options.c_cflag &= ~CSTOPB;
	options.c_cflag &= ~CSIZE;
	options.c_cflag |= CS8;
#endif 

//--------硬件流控制
#ifdef CTSRTS
	options.c_cflag |= CNEW_RTSCTS;
#else
	options.c_cflag &= ~CNEW_RTSCTS;
#endif

tcsetattr(fd, TCSANOW, &options);	//--------设置属性
3.其他API函数

int tcflow(int fildes, int action);//软件流控制
int tcflush(int fildes, int queue_selector);//丢弃要写入引用的对象,但是尚未传输的数据,或者收到但是尚未读取的数据
int tcdrain(int fildes);//等待直到所有写入
int tcsendbreak(int fildes, int duration);//传送连续的0值比特流,持续一段时间
pid_t tcgetpgrp(int fildes);	//获取组id
int tcsetpgrp(int fildes, pid_t pgid_id);	//设置组id
pid_t tcgetsid(int fildes);	//获取sid
int isatty(int fildes);	//判断使用的是不是tty终端
char *ttyname(int fildes);	//获取tty路径名

四.例子

网上找来个好的例子

/************************Copyright(c)******************************* 
**                       西安邮电学院 
**                       graduate school 
**                       XNMS项目组 
**                       WebSite :blog.csdn.net/tigerjb 
**------------------------------------------FileInfo------------------------------------------------------- 
** File name:                 main.c 
** Last modified Date:  2011-01-31 
** Last Version:              1.0 
** Descriptions:             
**------------------------------------------------------------------------------------------------------ 
** Created by:               冀博 
** Created date:            2011-01-31 
** Version:                            1.0 
** Descriptions:             The original version 
**------------------------------------------------------------------------------------------------------ 
** Modified by: 
** Modified date: 
** Version: 
** Descriptions: 
*******************************************************************/  
   
   
//串口相关的头文件   
#include<stdio.h>      /*标准输入输出定义*/   
#include<stdlib.h>     /*标准函数库定义*/   
#include<unistd.h>     /*Unix 标准函数定义*/   
#include<sys/types.h>    
#include<sys/stat.h>      
#include<fcntl.h>      /*文件控制定义*/   
#include<termios.h>    /*PPSIX 终端控制定义*/   
#include<errno.h>      /*错误号定义*/   
#include<string.h>   
   
//宏定义   
#define FALSE  -1   
#define TRUE   0   
   
/******************************************************************* 
* 名称:                  UART0_Open 
* 功能:                打开串口并返回串口设备文件描述 
* 入口参数:        fd    :文件描述符     port :串口号(ttyS0,ttyS1,ttyS2) 
* 出口参数:        正确返回为1,错误返回为0 
*******************************************************************/  
int UART0_Open(int fd,char* port)  
{  
	fd = open( port, O_RDWR|O_NOCTTY|O_NDELAY);  
	if(FALSE == fd){  
		perror("Can't Open Serial Port");  
		return(FALSE);  
	}  
	//恢复串口为阻塞状态                                  
	if(fcntl(fd, F_SETFL, 0) < 0){  
		printf("fcntl failed!\n");  
		return(FALSE);  
	}       
	else{  
		printf("fcntl=%d\n",fcntl(fd, F_SETFL,0));  
	}  
	//测试是否为终端设备       
	if(0 == isatty(STDIN_FILENO)){  
		printf("standard input is not a terminal device\n");  
		return(FALSE);  
	}  
	else{  
		printf("isatty success!\n");  
	}                
	printf("fd->open=%d\n",fd);  
	return fd;  
}  
/******************************************************************* 
* 名称:                UART0_Close 
* 功能:                关闭串口并返回串口设备文件描述 
* 入口参数:        fd    :文件描述符     port :串口号(ttyS0,ttyS1,ttyS2) 
* 出口参数:        void 
*******************************************************************/  
   
void UART0_Close(int fd)  
{  
	close(fd);  
}  
   
/******************************************************************* 
* 名称:                UART0_Set 
* 功能:               设置串口数据位,停止位和效验位 
* 入口参数:fd       串口文件描述符 
* 	speed     串口速度 
*        	flow_ctrl 数据流控制 0不使用 1硬件流控制 2软件流控制
*        databits   数据位   取值为 7 或者8 
*        stopbits   停止位   取值为 1 或者2 
*        parity     效验类型 取值为N,E,O,,S 
*出口参数:   	正确返回为1,错误返回为0 
*******************************************************************/  
int UART0_Set(int fd,int speed,int flow_ctrl,int databits,int stopbits,int parity)  
{  
	int   i;  
	int   status;  
	int   speed_arr[] = { B115200, B19200, B9600, B4800, B2400, B1200, B300};  
	int   name_arr[] = {115200,  19200,  9600,  4800,  2400,  1200,  300};  
    	struct termios options;  
	/*tcgetattr(fd,&options)得到与fd指向对象的相关参数,并将其保存于options,该函数还可以测试配置是否正确,
		该串口是否可用等。若调用成功,函数返回值为0,若调用失败,函数返回值为1*/  
	if (tcgetattr( fd,&options)!= 0){  
		perror("SetupSerial 1");      
		return(FALSE);   
	}  
    
    //设置串口输入波特率和输出波特率   
	for ( i= 0;  i < sizeof(speed_arr) / sizeof(int);  i++){  
		if(speed == name_arr[i]){               
			cfsetispeed(&options, speed_arr[i]);   
			cfsetospeed(&options, speed_arr[i]);    
		}  
	}       
     
    //修改控制模式,保证程序不会占用串口   
	options.c_cflag |= CLOCAL;  
    //修改控制模式,使得能够从串口中读取输入数据   
	options.c_cflag |= CREAD;  
    
    //设置数据流控制   
	switch(flow_ctrl)  
    {      
	case 0://不使用流控制   
		options.c_cflag &= ~CRTSCTS;  
		break;     
        
	case 1://使用硬件流控制   
		options.c_cflag |= CRTSCTS;  
		break;  
	case 2://使用软件流控制   
		options.c_cflag |= IXON | IXOFF | IXANY;  
		break;  
    }  
    //设置数据位   
    //屏蔽其他标志位   
    options.c_cflag &= ~CSIZE;  
    switch (databits)  
    {    
	case 5:  
		options.c_cflag |= CS5;  
		break;  
	case 6:  
		options.c_cflag |= CS6;  
		break;  
	case 7:      
		options.c_cflag |= CS7;  
		break;  
	case 8:      
		options.c_cflag |= CS8;  
		break;    
	default:     
		fprintf(stderr,"Unsupported data size\n");  
		return (FALSE);   
    }  
    //设置校验位   
    switch (parity)  
    {    
	case 'n':  
	case 'N': //无奇偶校验位。   
		options.c_cflag &= ~PARENB;   
		options.c_iflag &= ~INPCK;      
		break;   
	case 'o':    
	case 'O'://设置为奇校验       
		options.c_cflag |= (PARODD | PARENB);   
		options.c_iflag |= INPCK;               
		break;   
	case 'e':   
	case 'E'://设置为偶校验     
		options.c_cflag |= PARENB;         
		options.c_cflag &= ~PARODD;         
		options.c_iflag |= INPCK;        
		break;  
	case 's':  
	case 'S': //设置为空格    
		options.c_cflag &= ~PARENB;  
		options.c_cflag &= ~CSTOPB;  
		break;   
	default:    
		fprintf(stderr,"Unsupported parity\n");      
		return (FALSE);   
    }   
    // 设置停止位    
	switch (stopbits)  
    {    
	case 1:     
		options.c_cflag &= ~CSTOPB; break;   
	case 2:     
		options.c_cflag |= CSTOPB; break;  
	default:     
		fprintf(stderr,"Unsupported stop bits\n");   
		return (FALSE);  
    }  
     
	//修改输出模式,原始数据输出   
	options.c_oflag &= ~OPOST;  
    
	options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);//我加的   
	//options.c_lflag &= ~(ISIG | ICANON);   
     
    //设置等待时间和最小接收字符   
    options.c_cc[VTIME] = 1; /* 读取一个字符等待1*(1/10)s */    
    options.c_cc[VMIN] = 1; /* 读取字符的最少个数为1 */  
     
    //如果发生数据溢出,接收数据,但是不再读取 刷新收到的数据但是不读   
    tcflush(fd,TCIFLUSH);  
     
    //激活配置 (将修改后的termios数据设置到串口中)   
    if (tcsetattr(fd,TCSANOW,&options) != 0){  
	perror("com set error!\n");    
	return (FALSE);   
	}  
    return (TRUE);   
}  
/******************************************************************* 
* 名称:		UART0_Init() 
* 功能:		串口初始化 
* 入口参数:fd	:  文件描述符    
*		speed  	:  串口速度 
*		flow_ctrl  数据流控制 
*		databits   数据位   取值为 7 或者8 
*		stopbits   停止位   取值为 1 或者2 
*		parity     效验类型 取值为N,E,O,,S 
*                       
* 出口参数:        正确返回为1,错误返回为0 
*******************************************************************/  
int UART0_Init(int fd, int speed,int flow_ctrl,int databits,int stopbits,int parity)  
{  
    int err;  
    //设置串口数据帧格式   
    if (UART0_Set(fd,19200,0,8,1,'N') == FALSE){                                                           
		return FALSE;  
	}  
    else{  
		return  TRUE;  
	}  
}  
   
/******************************************************************* 
* 名称:		UART0_Recv 
* 功能:		接收串口数据 
* 入口参数:	fd	:文件描述符     
*		rcv_buf	:接收串口中数据存入rcv_buf缓冲区中 
*		data_len	:一帧数据的长度 
* 出口参数:	正确返回为1,错误返回为0 
*******************************************************************/  
int UART0_Recv(int fd, char *rcv_buf,int data_len)  
{  
    int len,fs_sel;  
    fd_set fs_read;  
     
    struct timeval time;  
     
    FD_ZERO(&fs_read);  
    FD_SET(fd,&fs_read);  
     
    time.tv_sec = 10;  
    time.tv_usec = 0;  
     
    //使用select实现串口的多路通信   
    fs_sel = select(fd+1,&fs_read,NULL,NULL,&time);  
    if(fs_sel){  
		len = read(fd,rcv_buf,data_len);  
		printf("I am right!(version1.2) len = %d fs_sel = %d\n",len,fs_sel);  
			return len;  
	}  
    else{  
		printf("Sorry,I am wrong!");  
		return FALSE;  
	}       
}  
/******************************************************************** 
* 名称:		UART0_Send 
* 功能:		发送数据 
* 入口参数:fd	:文件描述符     
*	send_buf :存放串口发送数据 
*	data_len :一帧数据的个数 
* 出口参数:正确返回为1,错误返回为0 
*******************************************************************/  
int UART0_Send(int fd, char *send_buf,int data_len)  
{  
    int len = 0;  
     
    len = write(fd,send_buf,data_len);  
    if (len == data_len )  
              {  
                     return len;  
              }       
    else     
        {  
                 
                tcflush(fd,TCOFLUSH);  
                return FALSE;  
        }  
     
}  
   
int main(int argc, char **argv)  
{  
    int fd;		//文件描述符   
    int err;	//返回调用函数的状态   
    int len;                          
    int i;  
    char rcv_buf[100];         
    char send_buf[20]="tiger john";  
    if(argc != 3){  
		printf("Usage: %s /dev/ttySn 0(send data)/1 (receive data) \n",argv[0]);  
		return FALSE;  
	}  
    fd = UART0_Open(fd,argv[1]); //打开串口,返回文件描述符   
    do{  
		err = UART0_Init(fd,19200,0,8,1,'N');  
		printf("Set Port Exactly!\n");  
	}while(FALSE == err || FALSE == fd);  
     
    if(0 == strcmp(argv[2],"0")){  
		for(i = 0;i < 10;i++){  
			len = UART0_Send(fd,send_buf,10);  
			if(len > 0)  
				printf(" %d send data successful\n",i);  
			else  
				printf("send data failed!\n");  
			sleep(2);  
		}  
		UART0_Close(fd);               
	}  
    else{  
		while (1){    //循环读取数据 
			len = UART0_Recv(fd, rcv_buf,9);  
			if(len > 0){  
				rcv_buf[len] = '\0';  
				printf("receive data is %s\n",rcv_buf);  
				printf("len = %d\n",len);  
			}  
			else{  
				printf("cannot receive data\n");  
			}  
			sleep(2);  
		}              
		UART0_Close(fd);   
	}  
}  
    
/*********************************************************************
                            End Of File                          
*********************************************************************/  


 

必须的表

 六 linux串口编程_第1张图片

你可能感兴趣的:(六 linux串口编程)