Linux下串口编程遇到的接收数据错误及原因Word格式文档下载.docx

上传人:b****5 文档编号:18121168 上传时间:2022-12-13 格式:DOCX 页数:24 大小:21.80KB
下载 相关 举报
Linux下串口编程遇到的接收数据错误及原因Word格式文档下载.docx_第1页
第1页 / 共24页
Linux下串口编程遇到的接收数据错误及原因Word格式文档下载.docx_第2页
第2页 / 共24页
Linux下串口编程遇到的接收数据错误及原因Word格式文档下载.docx_第3页
第3页 / 共24页
Linux下串口编程遇到的接收数据错误及原因Word格式文档下载.docx_第4页
第4页 / 共24页
Linux下串口编程遇到的接收数据错误及原因Word格式文档下载.docx_第5页
第5页 / 共24页
点击查看更多>>
下载资源
资源描述

Linux下串口编程遇到的接收数据错误及原因Word格式文档下载.docx

《Linux下串口编程遇到的接收数据错误及原因Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《Linux下串口编程遇到的接收数据错误及原因Word格式文档下载.docx(24页珍藏版)》请在冰豆网上搜索。

Linux下串口编程遇到的接收数据错误及原因Word格式文档下载.docx

fd=open(“/dev/ttyS0”,O_RDWR);

if(fd==-1)

{

Perror(“串口1打开失败!

”);

}

//else

//fcntl(fd,F_SETFL,FNDELAY);

除了使用O_RDWR标志之外,通常还会使用O_NOCTTY和O_NDELAY这两个标志。

O_NOCTTY:

告诉Unix这个程序不想成为“控制终端”控制的程序,不说明这个标志的话,任何输入都会影响你的程序。

O_NDELAY:

告诉Unix这个程序不关心DCD信号线状态,即其他端口是否运行,不说明这个标志的话,该程序就会在DCD信号线为低电平时停止。

3.设置波特率

最基本的串口设置包括波特率、校验位和停止位设置,且串口设置主要使用termios.h头文件中定义的termios结构,如下:

structtermios

tcflag_tc_iflag;

//输入模式标志

tcflag_tc_oflag;

//输出模式标志

tcflag_tc_cflag;

//控制模式标志

tcflag_tc_lflag;

//本地模式标志

cc_tc_line;

//linediscipline

cc_tc_cc[NCC];

//controlcharacters

intspeed_arr[]={B38400,B19200,B9600,B4800,B2400,B1200,B300,B38400,B19200,B9600,B4800,B2400,B1200,B300,};

intname_arr[]={38400,19200,9600,4800,2400,1200,300,38400,19200,9600,4800,2400,1200,300,};

voidSetSpeed(intfd,intspeed)

inti;

structtermiosOpt;

//定义termios结构

if(tcgetattr(fd,&

amp;

Opt)!

=0)

perror(“tcgetattrfd”);

return;

for(i=0;

i&

sizeof(speed_arr)/sizeof(int);

i++)

if(speed==name_arr[i])

tcflush(fd,TCIOFLUSH);

cfsetispeed(&

Opt,speed_arr[i]);

cfsetospeed(&

if(tcsetattr(fd,TCSANOW,&

perror(“tcsetattrfd”);

注意tcsetattr函数中使用的标志:

TCSANOW:

立即执行而不等待数据发送或者接受完成。

TCSADRAIN:

等待所有数据传递完成后执行。

TCSAFLUSH:

Flushinputandoutputbuffersandmakethechange

4.设置数据位、停止位和校验位

以下是

几个数据位、停止位和校验位的设置方法:

(以下均为1位停止位)

8位数据位、无校验位:

Opt.c_cflag&

=~PARENB;

=~CSTOPB;

=~CSIZE;

Opt.c_cflag|=CS8;

7位数据位、奇校验:

Opt.c_cflag|=PARENB;

Opt.c_cflag|=PARODD;

Opt.c_cflag|=CS7;

7位数据位、偶校验:

=~PARODD;

7位数据位、Space校验:

intSetParity(intfd,intdatabits,intstopbits,intparity)

perror(&

quot;

tcgetattrfd&

);

returnFALSE;

Opt.c_cflag|=(CLOCAL|CREAD);

//一般必设置的标志

switch(databits)//设置数据位数

case7:

break;

case8:

berak;

default:

fprintf(stderr,&

Unsupporteddatasize.\n&

switch(parity)//设置校验位

case&

#39;

n&

:

N&

//清除校验位

Opt.c_iflag&

=~INPCK;

//enableparitychecking

o&

O&

//enableparity

//奇校验

Opt.c_iflag|=INPCK//disableparitychecking

e&

E&

//偶校验

Opt.c_iflag|=INPCK;

//disablepairtychecking

s&

S&

//?

?

Unsupportedparity.\n&

switch(stopbits)//设置停止位

case1:

case2:

Opt.c_cflag|=CSTOPB;

Unsupportedstopbits.\n&

opt.c_cflag|=(CLOCAL|CREAD);

opt.c_lflag&

=~(ICANON|ECHO|ECHOE|ISIG);

opt.c_oflag&

=~OPOST;

=~(ONLCR|OCRNL);

//添加的

opt.c_iflag&

=~(ICRNL|INLCR);

=~(IXON|IXOFF|IXANY);

tcflush(fd,TCIFLUSH);

Opt.c_cc[VTIME]=0;

//设置超时为15sec

Opt.c_cc[VMIN]=0;

//UpdatetheOptanddoitnow

tcsetattrfd&

returnTRUE;

5.某些设置项

在第四步中我们看到一些比较特殊的设置,下面简述一下他们的作用。

c_cc数组的VSTART和VSTOP元素被设定成DC1和DC3,代表ASCII标准的XON和XOFF字符,如果在传输这两个字符的时候就传不过去,需要把软件流控制屏蔽,即:

=~(IXON|IXOFF|IXANY);

有时候,在用write发送数据时没有键入回车,信息就发送不出去,这主要是因为我们在输入输出时是按照规范模式接收到回车或换行才发送,而更多情况下我们是不必键入回车或换行的。

此时应转换

到行方式输入,不经处理直接发送,设置如下:

Opt.c_lflag&

=~(ICANON|ECHO|ECHOE|ISIG);

还存在这样的情况:

发送字符0X0d的时候,往往接收端得到的字符是0X0a,原因是因为在串口设置中c_iflag和c_oflag中存在从NL-CR和CR-NL的映射,即串口能把回车和换行当成同一个字符,可以进行如下设置屏蔽之:

=~(INLCR|ICRNL|IGNCR);

Opt.c_oflag&

6.读写串口

发送数据方式如下,write函数将返回写的位数或者当错误时为-1。

charbuffer[1024];

intlength;

intnByte;

nByte=write(fd,buffer,length);

读取数据方式如下,原始数据模式下每个read函数将返回实际串口收到的字符数,如果串口中没有字符可用,回叫将会阻塞直到以下几种情况:

有字符进入;

一个间隔计时器失效;

错误发送。

在打开串口成功后,使用fcntl(fd,F_SETFL,FNDELAY)语句,可以使read函数立即返回而不阻塞。

FNDELAY选项使read函数在串口无字符时立即返回且为0。

intreadByte;

readByte=read(fd,buffer,len);

注意:

设置为原始模式传输数据的话,read函数返回的字符数是实际串口收到的字符数。

Linux下直接用read读串口可能会造成堵塞,或者数据读出错误,此时可使用tcntl或者select等函数实现异步读取。

用select先查询com口,再用read去读就可以避免上述错误。

7.关闭串口

串口作为文件来处理,所以一般的关闭文件函数即可:

close(fd);

8.例子

这个例子中,需要打开串口1,设置9600波特率、8位数据位、1位停止位以及空校验,之后利用while语句循环判断串口中是否可以读出数据,将串口中数据连续读出后重新写回到串口中。

该程序可与minicom联合测试。

main()

intlen;

intn=0;

charread_buf[256];

charwrite_buf[256];

structtermiosopt;

fd=open(&

/dev/ttyS0&

O_RDWR|O_NOCTTY);

//默认为阻塞读方式

openserial0\n&

exit(0);

tcgetattr(fd,&

opt);

opt,B9600);

opt)!

=0)

tcsetattrerror&

return-1;

opt.c_cflag&

opt.c_cflag|=CS8;

opt.c_cc[VTIME]=0;

opt.c_cc[VMIN]=0;

printf(&

configurecomplete\n&

serialerror&

startsendandreceivedata\n&

 

while

(1)

n=0;

len=0;

bzero(read_buf,sizeof(read_buf));

//类似于memset

bzero(write_buf,sizeof(write_buf));

while((n=read(fd,read_buf,sizeof(read_buf)))&

0)

for(i=len;

(len+n);

write_buf[i]=read_buf[i-len];

len+=n;

write_buf[len]=&

\0&

;

Len%d\n&

len);

%s\n&

write_buf);

n=write(fd,write_buf,len);

write%dchars\n&

n);

sleep

(2);

9.附录

c_cflag用于设置控制参数,除了波特率外还包含以下内容:

EXTAExternalrateclock

EXTBExternalrateclock

CSIZEBitmaskfordatabits

CS55个数据位

CS66个数据位

CS77个数据位

CS88个数据位

CSTOPB2个停止位(清除该标志表示1个停止位

PARENB允许校验位

PARODD使用奇校验(清除该标志表示使用偶校验)

CREADEnablereceiver

HUPCLHangup(dropDTR)onlastclose

CLOCALLocalline–donotchange“owner”ofport

LOBLKBlockjobcontroloutpu

c_cflag标志可以定义CLOCAL和CREAD,这将确保该程序不被其他端口控制和信号干扰,同时串口驱动将读取进入的数据。

CLOCAL和CREAD通常总是被是能的。

c_lflag用于设置本地模式,决定串口驱动如何处理输入字符,设置内容如下:

ISIGEnableSIGINTR,SIGSUSP,SIGDSUSP,andSIGQUITsignals

ICANONEnablecanonicalinput(elseraw)

XCASEMapuppercase\lowercase(obsolete)

ECHOEnableechoingofinputcharacters

ECHOEEchoerasecharacterasBS-SP-BS

ECHOKEchoNLafterkillcharacter

ECHONLEchoNL

NOFLSHDisableflushingofinputbuffersafterinterruptorquitcharacters

IEXTENEnableextendedfunctions

ECHOCTLEchocontrolcharactersas^charanddeleteas~?

ECHOPRTEchoerasedcharacterascharactererased

ECHOKEBS-SP-BSentirelineonlinekill

FLUSHOOutputbeingflushed

PENDINRetypependinginputatnextreadorinputchar

TOSTOPSendSIGTTOUforbackgroundoutput

c_iflag用于设置如何处理串口上接收到的数据,包含如下内容:

INPCKEnableparitycheck

IGNPARIgnoreparityerrors

PARMRKMarkparityerrors

ISTRIPStripparitybits

IXONEnablesoftwareflowcontrol(outgoing)

IXOFFEnablesoftwareflowcontrol(incoming)

IXANYAllowanycharactertostartflowagain

IGNBRKIgnorebreakcondition

BRKINTSendaSIGINTwhenabreakconditionisdetected

INLCRMapNLtoCR

IGNCRIgnoreCR

ICRNLMapCRtoNL

IUCLCMapuppercasetolowercase

IMAXBELEchoBELoninputlinetoolong

c_oflag用于设置如何处理输出数据,包含如下内容:

OPOSTPostprocessoutput(notset=rawoutput)

OLCUCMaplowercasetouppercase

ONLCRMapNLtoCR-NL

OCRNLMapCRtoNL

NOCRNoCRoutputatcolumn0

ONLRETNLperformsCRfunction

OFILLUsefillcharactersfordelay

OFDELFillcharacterisDEL

NLDLYMaskfordelaytimeneededbetweenlines

NL0NodelayforNLs

NL1Delayfurtheroutputafternewlinefor100milliseconds

CRDLYMaskfordelaytimeneededtoreturncarriagetoleftcolumn

CR0NodelayforCRs

CR1DelayafterCRsdependingoncu

rrentcolumnposition

CR2Delay100millisecondsaftersendingCRs

CR3Delay150millisecondsaftersendingCRs

TABDLYMaskfordelaytimeneededafterTABs

TAB0NodelayforTABs

TAB1DelayafterT

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 艺术

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1