/*******************************************************************/
/* serial.c */
/*******************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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
#include
#include
#include
#include
#include
#include
#include
#include
#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