日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

串口初始化配置

發(fā)布時(shí)間:2023/12/9 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 串口初始化配置 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在基于AT91的嵌入式linux中接收串口數(shù)據(jù)時(shí),發(fā)現(xiàn)對(duì)于接收的數(shù)據(jù)經(jīng)常出現(xiàn)接收不完整的現(xiàn)象。一幀的數(shù)據(jù)可能會(huì)被當(dāng)做兩幀接收,導(dǎo)致對(duì)于一幀數(shù)據(jù)接收出現(xiàn)問題。雖然這種情況在一般情況下,并不是經(jīng)常出現(xiàn),但是只要數(shù)據(jù)量稍微大一些,情況就會(huì)出現(xiàn)。

于是仔細(xì)看了程序中關(guān)于串口配置這一塊的程序,

[cpp]?view plaincopy
  • int?set_opt(int?fd,int?nSpeed,?int?nBits,?char?nEvent,?int?nStop)??
  • {??
  • struct?termios?oldtio;??
  • ????struct?termios?newtio;??
  • ??
  • ????if(?tcgetattr(fd,?&oldtio)??!=??0)?{??
  • ????????perror("SetupSerial?1");??
  • ????????return?-1;??
  • ????}??
  • ??????
  • ????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?;??
  • ????????break;??
  • ????????case?'E':??
  • ????????newtio.c_iflag?|=?INPCK?;??
  • ????????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;??
  • ????????case?460800:??
  • ????????????cfsetispeed(&newtio,?B460800);??
  • ????????????cfsetospeed(&newtio,?B460800);??
  • ????????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]?=?1;??
  • ??????
  • ????tcflush(fd,TCIFLUSH);??
  • ????if((tcsetattr(fd,TCSANOW,&newtio))!=0)??
  • ????{??
  • ????????perror("com?set?error");??
  • ????????return?-1;??
  • }??
  • ??????
  • ????tcflush(fd,TCIFLUSH);//The?`tcflush'?function?is?used?to?clear?the?input?and/or?output??
  • ????return?0;???
  • }??


  • 在分析完程序后發(fā)現(xiàn)可能導(dǎo)致出問題的地方:在使用oldtio讀取串口配置后,卻沒有將其復(fù)制給newtio,并且將newtio清零,這造成下邊的設(shè)置操作,修改了一些原來的設(shè)置。

    根據(jù)程序修改VTIMEVMIN可推知這里要使用非規(guī)范方式,

    根據(jù)APUE可知由VTIMEVMIN的設(shè)置共可以有四種選擇

    AVTIME?>?0,?VMIN?>?0

    B:?VTIME?=?0,?VMIN?>?0

    C:?VTIME?>?0,?VMIN?=?0

    D:?VTIME?=?0,?VMIN?=?0

    由程序修改的值

    ?newtio.c_cc[VTIME]??=?0;
    ?newtio.c_cc[VMIN]???=?1;

    可知這里要設(shè)置為第二種方式:只有接收到MIN個(gè)字節(jié)數(shù)據(jù),read才返回;否則,read將阻塞。

    因?yàn)檫@里沒有將oldtio復(fù)制給newtio所以這里的ICANON標(biāo)識(shí)一定沒有設(shè)置,所以是處于非規(guī)范模式下。這里的VTIME,?VMIN對(duì)這里的設(shè)置也是有效的。

    但是這樣難免修改一些我們沒有注意的選項(xiàng),根據(jù)這里的設(shè)置,結(jié)合APUE中的示例程序,發(fā)現(xiàn)APUE中將終端設(shè)置為原始模式(raw?modle)與這里的設(shè)置較為相似,于是想采用APUE中的部分參數(shù)設(shè)置,來修改此處的程序。

    ==================APUE中?put?terminal?into?a?raw?modle?===========================

    [cpp]?view plaincopy
  • int??
  • tty_raw(int?fd)?/*?put?terminal?into?a?raw?mode?*/??
  • {??
  • ?int?err;??
  • ?struct?termios?buf;??
  • ??
  • ??
  • ?if?(ttystate?!=?RESET)?{??
  • ?errno?=?EINVAL;??
  • ?return(-1);??
  • ?}??
  • ?if?(tcgetattr(fd,?&buf)?<?0)??
  • ?return(-1);??
  • ?save_termios?=?buf;?/*?structure?copy?*/??
  • ??
  • ?/*?
  • ??*?Echo?off,?canonical?mode?off,?extended?input?
  • ??*?processing?off,?signal?chars?off.?
  • ??*/??
  • ?buf.c_lflag?&=?~(ECHO?|?ICANON?|?IEXTEN?|?ISIG);??
  • ??
  • ?/*?
  • ??*?No?SIGINT?on?BREAK,?CR-to-NL?off,?input?parity?
  • ??*?check?off,?don't?strip?8th?bit?on?input,?output?
  • ??*?flow?control?off.?
  • ??*/??
  • ?buf.c_iflag?&=?~(BRKINT?|?ICRNL?|?INPCK?|?ISTRIP?|?IXON);??
  • ??
  • ?/*?
  • ??*?Clear?size?bits,?parity?checking?off.?
  • ??*/??
  • ?buf.c_cflag?&=?~(CSIZE?|?PARENB);??
  • ??
  • ?/*?
  • ??*?Set?8?bits/char.?
  • ??*/??
  • ?buf.c_cflag?|=?CS8;??
  • ??
  • ?/*?
  • ??*?Output?processing?off.?
  • ??*/??
  • ?buf.c_oflag?&=?~(OPOST);??
  • ??
  • ?/*?
  • ??*?Case?B:?1?byte?at?a?time,?no?timer.?
  • ??*/??
  • ?buf.c_cc[VMIN]?=?1;??
  • ?buf.c_cc[VTIME]?=?0;??
  • ?if?(tcsetattr(fd,?TCSAFLUSH,?&buf)?<?0)??
  • ?return(-1);??
  • ??
  • ?/*?
  • ??*?Verify?that?the?changes?stuck.??tcsetattr?can?return?0?on?
  • ??*?partial?success.?
  • ??*/??
  • ?if?(tcgetattr(fd,?&buf)?<?0)?{??
  • ?err?=?errno;??
  • ?tcsetattr(fd,?TCSAFLUSH,?&save_termios);??
  • ?errno?=?err;??
  • ?return(-1);??
  • ?}??
  • ?if?((buf.c_lflag?&?(ECHO?|?ICANON?|?IEXTEN?|?ISIG))?||??
  • ???(buf.c_iflag?&?(BRKINT?|?ICRNL?|?INPCK?|?ISTRIP?|?IXON))?||??
  • ???(buf.c_cflag?&?(CSIZE?|?PARENB?|?CS8))?!=?CS8?||??
  • ???(buf.c_oflag?&?OPOST)?||?buf.c_cc[VMIN]?!=?1?||??
  • ???buf.c_cc[VTIME]?!=?0)?{??
  • ?/*?
  • ??*?Only?some?of?the?changes?were?made.??Restore?the?
  • ??*?original?settings.?
  • ??*/??
  • ?tcsetattr(fd,?TCSAFLUSH,?&save_termios);??
  • ?errno?=?EINVAL;??
  • ?return(-1);??
  • ?}??
  • ??
  • ?ttystate?=?RAW;??
  • ?ttysavefd?=?fd;??
  • ?return(0);??
  • }??

  • 從英文注釋,可以了解到,各個(gè)參數(shù)的具體意義,

    同時(shí)參考博客http://blog.csdn.net/awei_xu/article/details/3725329?中的紅色標(biāo)記部分設(shè)置來補(bǔ)充,

    [cpp]?view plaincopy
  • ?if((fd?=?open(dev,O_RDWR?|?O_NOCTTY?|?O_NDELAY))?==?-1)???
  • ??/*----------------------??重要----------------------*/???
  • ????//保證本程序不會(huì)成為端口的所有者,從而妨礙控制工作和掛起信號(hào).??
  • ????opt.c_cflag?????|=?(CLOCAL?|?CREAD);??
  • //選擇原始輸入方式:?原始輸入方式是不經(jīng)處理的.??
  • opt.c_lflag??&=?~(ICANON?|?ECHO?|?ECHOE?|?ISIG);???
  • //輸出不經(jīng)處理??
  • opt.c_oflag??&=?~OPOST;????
  • ???//取消軟件流控制(不設(shè)置可能存在丟碼)??
  • ???opt.c_iflag?&=?~(IXON?|?IXOFF?|?IXANY);??/*----------------------------------------------------*/??

  • 修改后的程序:

    [cpp]?view plaincopy
  • int?set_opt(int?fd,int?nSpeed,?int?nBits,?char?nEvent,?int?nStop)??
  • {??
  • ????struct?termios?oldtio;??
  • struct?termios?newtio;??
  • ????if(?tcgetattr(fd,?&oldtio)??!=??0)?{??
  • ????????perror("SetupSerial?1");??
  • ????????return?-1;??
  • ????}??
  • ????newtio?=?oldtio;??
  • /*************Debug*******************/??
  • ????newtio.c_cflag??|=??CLOCAL?|?CREAD;??
  • ????newtio.c_cflag??&=?~(CSIZE?|?PARENB);??
  • ????newtio.c_lflag??&=?~(ICANON?|?ISIG?|?ECHO?|?ECHOE?|?IEXTEN);??
  • ????newtio.c_oflag??&=?~OPOST;??
  • ????newtio.c_iflag??&=?~(IXON?|?IXOFF?|?IXANY?|?ICRNL?|?BRKINT??
  • ???????????????????????|?INPCK?|?ISTRIP);??
  • /***************************************/??
  • ????switch(?nBits?)??
  • ????{??
  • ????????case?7:??
  • ????????????newtio.c_cflag?|=?CS7;??
  • ????????????break;??
  • ????????case?8:??
  • ????????????newtio.c_cflag?|=?CS8;??
  • ????????????break;??
  • ????}??
  • ????switch(?nEvent?)??
  • ????{??
  • ????????case?'O':??
  • ????????????/*odd?parity*/??
  • ????????????newtio.c_iflag?|=?INPCK?;??
  • ????????????newtio.c_cflag?|=?PARENB;??
  • ????????????newtio.c_cflag?|=?PARODD;??
  • ????????????break;??
  • ????????case?'E':??
  • ????????????/*even?parity*/??
  • ????????????newtio.c_iflag?|=?INPCK?;??
  • ????????????newtio.c_cflag?|=?PARENB;??
  • ????????????newtio.c_cflag?&=?~PARODD;??
  • ????????????break;??
  • ????????case?'N':??
  • ????????????/*no?parity*/??
  • ????????????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;??
  • ????????case?460800:??
  • ????????????cfsetispeed(&newtio,?B460800);??
  • ????????????cfsetospeed(&newtio,?B460800);??
  • ????????????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]???=?1;??
  • ??????
  • ????tcflush(fd,TCIFLUSH);??
  • ????if((tcsetattr(fd,TCSANOW,&newtio))!=0)??
  • ????{??
  • ????????perror("com?set?error");??
  • ????????return?-1;??
  • ????}??
  • tcflush(fd,TCIFLUSH);??
  • return?0;??
  • }??

  • 修改完的初步測(cè)試中發(fā)現(xiàn)有些地方還有問題,

    待下一步測(cè)試,找到原因所在。

    總結(jié)

    以上是生活随笔為你收集整理的串口初始化配置的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。