您的位置:首页 > 运维架构 > Linux

linux串口编程例子

2017-02-22 07:16 351 查看
/*******************************************************************/
/*                           serial.h                              */
/*******************************************************************/
#ifndef __SERIAL_H__

#define __SERIAL_H__

extern int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop);

extern int open_port(int fd,int comport);

#endif

/*******************************************************************/
/*                          serial.c                               */
/*******************************************************************/

#include <stdio.h>

#include <string.h>

#include <sys/types.h>

#include <errno.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <unistd.h>

#include <termios.h>

#include <stdlib.h>

#include "serial.h"
/*******************************************************************

* 函数名称: set_opt

* 功能描述: 设置串口基本参数

* 输入参数: fd     打开的串口标识符 (通过open_port函数返回)

    nSpeed 波特率 2400、4800、9600、115200

    nBits  数据位 7、8

    nEvent 奇偶校验 'O' 'N' 'E'

    nStop  停止位 1、2

* 输出参数: 无

* 返 回 值: 0  设置成功

    -1 设置过程出错

* 其它说明: 无

* 修改日期   版本号     修改人     修改内容

* --------------------------------------------------------------------

* 2010/09/27      V1.0             ***     创建函数

***********************************************************************/

int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)

{

    struct termios newtio,oldtio;
//保存测试现有串口参数设置,在这里如果串口号等出错,会有相关的出错信息

    if ( tcgetattr( fd,&oldtio) != 0)

    {

        perror("SetupSerial 1");

        return -1;

    }
//extern void bzero(void *s, int n); 置字节字符串s的前n个字节为零

    bzero( &newtio, sizeof( newtio ) );
//设置字符大小

    newtio.c_cflag |= CLOCAL | CREAD;

    newtio.c_cflag &= ~CSIZE;
//设置数据位

    switch( nBits )

    {

    case 7:

        newtio.c_cflag |= CS7;

        break;

    case 8:

        newtio.c_cflag |= CS8;

        break;

    }
//设置校验位

    switch( nEvent )

    {

    case 'O':

        newtio.c_cflag |= PARENB;

        newtio.c_cflag |= PARODD;

        newtio.c_iflag |= (INPCK | ISTRIP);

        break;

    case 'E':

        newtio.c_iflag |= (INPCK | ISTRIP);

        newtio.c_cflag |= PARENB;

        newtio.c_cflag &= ~PARODD;

        break;

    case 'N':

        newtio.c_cflag &= ~PARENB;

        break;

    }
//设置波特率

switch( nSpeed )

    {

    case 2400:

        cfsetispeed(&newtio, B2400);

        cfsetospeed(&newtio, B2400);

        break;

    case 4800:

        cfsetispeed(&newtio, B4800);

        cfsetospeed(&newtio, B4800);

        break;

    case 9600:

        cfsetispeed(&newtio, B9600);

        cfsetospeed(&newtio, B9600);

        break;

    case 115200:

        cfsetispeed(&newtio, B115200);

        cfsetospeed(&newtio, B115200);

        break;

    default:

        cfsetispeed(&newtio, B9600);

        cfsetospeed(&newtio, B9600);

        break;

    }
//设置停止位

    if( nStop == 1 )

        newtio.c_cflag &= ~CSTOPB;

    else if ( nStop == 2 )

  newtio.c_cflag |= CSTOPB;
//设置等待时间和最小接收字符

    newtio.c_cc[VTIME] = 0;

    newtio.c_cc[VMIN] = 0;
//处理未接收字符

    tcflush(fd,TCIFLUSH);
//激活新配置

    if((tcsetattr(fd,TCSANOW,&newtio))!=0)

    {

        perror("com set error");//打印com set error及出错原因

        return -1;

    }

    printf("set done!\n");

    return 0;

}
/**********************************************************************

* 函数名称: open_port

* 功能描述: 打开指定串口

* 输入参数: fd 文件描述符

    comport 串口号(1、2、3)

* 输出参数: 无

* 返 回 值: 出错 返回 -1

             成功 返回 fd文件描述符

* 其它说明: 无

* 修改日期   版本号     修改人     修改内容

* --------------------------------------------------------------------

* 2010/09/27      V1.0             ***     创建函数

***********************************************************************/

int open_port(int fd,int comport)

{

    char *dev[]={"/dev/ttyS0","/dev/ttyS1","/dev/ttyS2"};

    long vdisable;//没用
//打开串口

    if (comport==1)

    {   

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

        if (-1 == fd)

  {

            perror("Can't Open Serial Port");

            return(-1);

        }

        else

            printf("open ttyS0 .....\n");

    }

    else if(comport==2)

    {   

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

        if (-1 == fd)

  {

            perror("Can't Open Serial Port");

            return(-1);

        }

        else

            printf("open ttyS1 .....\n");

    }

    else if (comport==3)

    {

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

        if (-1 == fd)

  {

            perror("Can't Open Serial Port");

            return(-1);

        }

        else

            printf("open ttyS2 .....\n");

    }

else if (comport==4)

{

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

  if (-1 == fd)

  {

   perror("Can't Open Serial Port");

   return(-1);

  }

  else

   printf("open ttyS3 .....\n");

}
//恢复串口的状态为阻塞状态,用于等待串口数据的读入

    if(fcntl(fd, F_SETFL, 0) < 0)

        printf("fcntl failed!\n");

    else

        printf("fcntl=%d\n",fcntl(fd, F_SETFL,0));
//测试打开的文件描述符是否引用一个终端设备,以进一步确认串口是否正确打开

    if(isatty(STDIN_FILENO)==0)

        printf("standard input is not a terminal device\n");

    else

        printf("isatty success!\n");
    printf("fd-open=%d\n",fd);
    return fd;

}

/*******************************************************************/
/*                          main.c                                 */
/*******************************************************************/

#include <stdio.h>

#include <string.h>

#include <sys/types.h>

#include <errno.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <unistd.h>

#include <termios.h>

#include <stdlib.h>

#include "serial.h"
int main(void)

{

int fd;

int nread,i;

char buff[512];

bzero(buff, 512);
if((fd=open_port(fd,4)) < 0)

{

  perror("open_port error");

  return -1;

}
if((i=set_opt(fd,115200,8,'N',1)) < 0)

{

  perror("set_opt error");

  return -1;

}

printf("fd=%d\n",fd);
while (1)

{

  sleep(2);

  //while ((nread = read(fd,buff,512)) > 0)

  {

   nread = read(fd,buff,512);
   printf("nread = %d\n",nread);
   printf("%s\n",buff);
   bzero(buff,nread);//清空

   //usleep(100000);

  }

}
close(fd);

return 0;

}

//下面为截取的一小段Makefile内容,Makefile是通过QT的qmake自动生成的,如果程序在开发板上跑,要稍加修改。
####### Compiler, tools and options
ARCH=arm
CROSS_COMPILE=arm-unknown-linux-gnu-

DEFINES =

#DEFINES += -DMASK_GATEWAY_CHECK
CC       = ${CROSS_COMPILE}gcc

CXX      = ${CROSS_COMPILE}g++

LEX      = ${CROSS_COMPILE}flex

YACC     = ${CROSS_COMPILE}yacc
CFLAGS   = -Wall -Wextra #-pipe -Wall -W -O2 -march=i386 -mcpu=i686 -g -DGLX_GLXEXT_LEGACY -fno-use-cxa-atexit -fno-exceptions  -DQT_NO_DEBUG

CFLAGS += $(DEFINES)

CXXFLAGS = -Wall -Wextra #-pipe -Wall -W -O2 -march=i386 -mcpu=i686 -g -DGLX_GLXEXT_LEGACY -fno-use-cxa-atexit -fno-exceptions  -DQT_NO_DEBUG

#LEXFLAGS =

#YACCFLAGS= -d

#INCPATH  = -I$(QTDIR)/mkspecs/default -I. -I$(QTDIR)/include -I.ui/ -I.moc/

LINK     = ${CROSS_COMPILE}gcc

LFLAGS   =

#LIBS     = $(SUBLIBS) -L$(QTDIR)/lib -L/usr/X11R6/lib -lqt-mt -lXext -lX11 -lm

LIBS =

#AR       = ar cqs

#RANLIB   =

#MOC      = $(QTDIR)/bin/moc

#UIC      = $(QTDIR)/bin/uic

#QMAKE    = qmake

#TAR      = tar -cf

#GZIP     = gzip -9f

#COPY     = cp -f

#COPY_FILE= $(COPY) -p

#COPY_DIR = $(COPY) -pR

DEL_FILE = rm -f

#SYMLINK  = ln -sf

#DEL_DIR  = rmdir

#MOVE     = mv -f

#CHK_DIR_EXISTS= test -d

#MKDIR    = mkdir -p

####### Output directory
OBJECTS_DIR = .obj/
####### Files
HEADERS = /mnt/hgfs/share/serial/serial.h

SOURCES = /mnt/hgfs/share/serial/serial.c \

  /mnt/hgfs/share/serial/main.c

OBJECTS = .obj/serial.o \

  .obj/main.o

FORMS =

UICDECLS =

UICIMPLS =

SRCMOC   =

OBJMOC =

DIST    = serial.pro

QMAKE_TARGET = serial

DESTDIR  =

TARGET   = serial
first: all

####### Implicit rules
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: