0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

英創(chuàng)信息技術(shù)嵌入式Linux串口通訊的C++設(shè)計(jì)概述

英創(chuàng)信息技術(shù) ? 來(lái)源:英創(chuàng)信息技術(shù) ? 作者:英創(chuàng)信息技術(shù) ? 2019-11-18 09:32 ? 次閱讀

嵌入式Linux主板EM9160提供了6個(gè)標(biāo)準(zhǔn)異步串口:ttyS1——ttyS6,其中ttyS4、ttyS5、ttyS6和GPIO的管腳復(fù)用,每個(gè)串口都有獨(dú)立的中斷模式,使得多個(gè)串口能夠同時(shí)實(shí)時(shí)進(jìn)行數(shù)據(jù)收發(fā)。各個(gè)串口的驅(qū)動(dòng)均已經(jīng)包含在嵌入式Linux操作系統(tǒng)的內(nèi)核中,EM9160在嵌入式Linux系統(tǒng)啟動(dòng)完成時(shí),各個(gè)串口已作為字符設(shè)備完成了注冊(cè)加載,用戶的應(yīng)用程序可以以操作文件的方式對(duì)串口進(jìn)行讀寫(xiě),從而實(shí)現(xiàn)數(shù)據(jù)收發(fā)的功能。

串口編程接口函數(shù)

在嵌入式Linux系統(tǒng)下,所有的設(shè)備文件都位于“/dev”目錄下,EM9160上6個(gè)串口所對(duì)應(yīng)的設(shè)備名依次為“/dev/ttyS1”——“/dev/ttyS6”。

嵌入式Linux下操作設(shè)備的方式和操作文件的方式是一樣的:調(diào)用open( )打開(kāi)設(shè)備文件,再調(diào)用read( )、write( )對(duì)串口進(jìn)行數(shù)據(jù)讀寫(xiě)操作。這里需要注意的是打開(kāi)串口除了設(shè)置普通的讀寫(xiě)之外,還需要設(shè)置O_NOCTTY和O_NDLEAY,以避免該串口成為一個(gè)控制終端,因?yàn)槿绻鳛橐粋€(gè)終端有可能會(huì)影響到用戶的進(jìn)程。打開(kāi)的方式如下:

sprintf( portname, ‘/dev/ttyS%d’, PortNo ); //PortNo為串口端口號(hào),從1開(kāi)始

m_fd = open( portname,O_RDWR | O_NOCTTY | O_NONBLOCK);

作為串口通訊還需要一些通訊參數(shù)的配置,包括波特率、數(shù)據(jù)位、停止位、校驗(yàn)位等參數(shù)。在實(shí)際的操作中,主要是通過(guò)設(shè)置struct termios結(jié)構(gòu)體的各個(gè)成員值來(lái)實(shí)現(xiàn),一般會(huì)用到的函數(shù)包括:

tcgetattr( ) ;

tcflush( );

cfsetispeed( );

cfsetospeed( );

tcsetattr( );

其中各個(gè)函數(shù)的具體使用方法這里就不一一介紹了,用戶可以參考嵌入式Linux應(yīng)用程序開(kāi)發(fā)的相關(guān)書(shū)籍,也可參看Step2_SerialTest中Serial.cpp模塊中set_port( )函數(shù)代碼。

串口應(yīng)用的C++設(shè)計(jì)

Step2 _SerialTest是一個(gè)支持異步串口數(shù)據(jù)通訊的示例,該例程采用了面向?qū)ο蟮腃++編程,把串口數(shù)據(jù)通訊作為一個(gè)對(duì)象進(jìn)行封裝,用戶調(diào)用該對(duì)象提供的接口函數(shù)即可方便地完成串口通訊的操作。

CSerial類介紹

利用上一小節(jié)中介紹的串口API函數(shù),封裝了一個(gè)支持異步讀寫(xiě)的串口類CSerial,CSerial類中提供了4個(gè)公共函數(shù)、一個(gè)串口數(shù)據(jù)接收線程以及數(shù)據(jù)接收用到的數(shù)據(jù)Buffer。

class CSerial

{

private:

//通訊線程標(biāo)識(shí)符ID

pthread_t m_thread;

// 串口數(shù)據(jù)接收線程

static int ReceiveThreadFunc( void* lparam );

public:

CSerial();

virtual ~CSerial();

int m_fd; // 已打開(kāi)的串口文件描述符

int m_DatLen;

char DatBuf[1500];

int m_ExitThreadFlag;

// 按照指定的串口參數(shù)打開(kāi)串口,并創(chuàng)建串口接收線程

int OpenPort( int PortNo, int baudrate, char databits, char stopbits, char parity );

// 關(guān)閉串口并釋放相關(guān)資源

int ClosePort( );

// 向串口寫(xiě)數(shù)據(jù)

int WritePort( char* Buf, int len );

// 接收串口數(shù)據(jù)處理函數(shù)

virtual int PackagePro( char* Buf, int len );

};

OpenPort函數(shù)用于根據(jù)輸入串口參數(shù)打開(kāi)串口,并創(chuàng)建串口數(shù)據(jù)接收線程。在嵌入式Linux環(huán)境中是通過(guò)函數(shù)pthread_create( )創(chuàng)建線程,通過(guò)函數(shù)pthread_exit( )退出線程。嵌入式Linux線程屬性存在有非分離(缺省)和分離兩種,在非分離情況下,當(dāng)一個(gè)線程結(jié)束時(shí),它所占用的系統(tǒng)資源并沒(méi)有被釋放,也就是沒(méi)有真正的終止;只有調(diào)用pthread_join( )函數(shù)返回時(shí),創(chuàng)建的線程才能釋放自己占有的資源。在分離屬性下,一個(gè)線程結(jié)束時(shí)立即釋放所占用的系統(tǒng)資源?;谶@個(gè)原因,在我們提供的例程中通過(guò)相關(guān)函數(shù)將數(shù)據(jù)接收線程的屬性設(shè)置為分離屬性。如:

// 設(shè)置線程綁定屬性

res = pthread_attr_setscope( &attr, PTHREAD_SCOPE_SYSTEM );

// 設(shè)置線程分離屬性

res += pthread_attr_setdetachstate( &attr, THREAD_CREATE_DETACHED );

ReceiveThreadFunc函數(shù)是串口數(shù)據(jù)接收和處理的主要核心代碼,在該函數(shù)中調(diào)用select( ),阻塞等待串口數(shù)據(jù)的到來(lái)。對(duì)于接收到的數(shù)據(jù)處理也是在該函數(shù)中實(shí)現(xiàn),在本例程中處理為簡(jiǎn)單的數(shù)據(jù)回發(fā),用戶可結(jié)合實(shí)際的應(yīng)用修改此處代碼,修改PackagePro( )函數(shù)即可。流程如下:

int CSerial::ReceiveThreadFunc(void* lparam)

{

CSerial *pSer = (CSerial*)lparam;

//定義讀事件集合

fd_set fdRead;

int ret;

struct timeval aTime;

while( 1 )

{

//收到退出事件,結(jié)束線程

if( pSer-》m_ExitThreadFlag )

{

break;

}

FD_ZERO(&fdRead);

FD_SET(pSer-》m_fd,&fdRead);

aTime.tv_sec = 0;

aTime.tv_usec = 300000;

ret = select( pSer-》m_fd+1,&fdRead,NULL,NULL,&aTime );

if (ret 《 0 )

{

//關(guān)閉串口

pSer-》ClosePort( );

break;

}

if (ret 》 0)

{

//判斷是否讀事件

if (FD_ISSET(pSer-》m_fd,&fdRead))

{

//data available, so get it!

pSer-》m_DatLen = read( pSer-》m_fd, pSer-》DatBuf, 1500 );

// 對(duì)接收的數(shù)據(jù)進(jìn)行處理,這里為簡(jiǎn)單的數(shù)據(jù)回發(fā)

if( pSer-》m_DatLen 》 0 )

{

pSer-》PackagePro( pSer-》DatBuf, pSer-》m_DatLen);

}

// 處理完畢

}

}

}

printf( ‘ReceiveThreadFunc finished\n’);

pthread_exit( NULL );

return 0;

}

需要注意的是,select( )函數(shù)中的時(shí)間參數(shù)在嵌入式Linux中每次都需要重新賦值,否則會(huì)自動(dòng)歸0。

CSerial類的實(shí)現(xiàn)代碼請(qǐng)參見(jiàn)Serial.CPP文件。

CSerial類的調(diào)用

CSerial類的具體使用也比較簡(jiǎn)單,主要是對(duì)于類中定義的4個(gè)公共函數(shù)的調(diào)用,以下為 Step2_SerialTest.cpp中相關(guān)代碼。

class CSerial m_Serial;

int main( int argc,char* argv[] )

{

int i1;

int portno, baudRate;

char cmdline[256];

printf( ‘Step2_SerialTest V1.0\n’ );

// 解析命令行參數(shù):串口號(hào) 波特率

if( argc 》 1 ) strcpy( cmdline, argv[1] );

else portno = 1;

if( argc 》 2 )

{

strcat( cmdline, ‘ ’ );

strcat( cmdline, argv[2] );

scanf( cmdline, ‘%d %d’, &portno, &baudRate );

}

else

{

baudRate = 115200;

}

printf( ‘port:%d baudrate:%d\n’, portno, baudRate);

//打開(kāi)串口相應(yīng)地啟動(dòng)了串口數(shù)據(jù)接收線程

i1 = m_Serial.OpenPort( portno, baudRate, ‘8’, ‘1’, ‘N’);

if( i1《0 )

{

printf( ‘serial open fail\n’);

return -1;

}

//進(jìn)入主循環(huán),這里每隔1s輸出一個(gè)提示信息

for( i1=0; i1《10000;i1++)

{

sleep(1);

printf( ‘%d \n’, i1+1);

}

m_Serial.ClosePort( );

return 0;

}

從上面的代碼可以看出,程序的主循環(huán)只需要實(shí)現(xiàn)一些管理性的功能,在本例程中僅僅是每隔1s輸出一個(gè)提示信息,在實(shí)際的應(yīng)用中,可以把一些定時(shí)查詢狀態(tài)的操作、看門狗的喂狗等操作放在主循環(huán)中,這樣充分利用了嵌入式Linux多任務(wù)的編程優(yōu)勢(shì),利用內(nèi)核的任務(wù)調(diào)度機(jī)制,將各個(gè)應(yīng)用功能模塊化,以便于程序的設(shè)計(jì)和管理。這里順便再提一下,在進(jìn)行多個(gè)串口編程時(shí),也可以利用本例程中的CSerial類為基類,根據(jù)應(yīng)用需求派生多個(gè)CSerial派生類實(shí)例,每一個(gè)派生類只是重新實(shí)現(xiàn)虛函數(shù)PackagePro(…),這樣每個(gè)串口都具有一個(gè)獨(dú)立的串口數(shù)據(jù)處理線程,利用Linux內(nèi)核的任務(wù)調(diào)度機(jī)制以實(shí)現(xiàn)多串口通訊功能。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11207

    瀏覽量

    208713
  • 嵌入式主板
    +關(guān)注

    關(guān)注

    7

    文章

    6084

    瀏覽量

    35154
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    創(chuàng)嵌入式主板的無(wú)線通訊解決方案

    WiFi模塊。ETA6210模塊繼續(xù)保持了PPP撥號(hào)模式,使得無(wú)論是Linux平臺(tái)的主板還是CE平臺(tái)的主板,都能方便的使用。  下表列出了當(dāng)前創(chuàng)嵌入式主板支持的無(wú)線模塊。模塊型號(hào)模
    發(fā)表于 03-24 14:00

    嵌入式linux培訓(xùn)教程 嵌入式linux學(xué)習(xí)方法步驟

      嵌入式開(kāi)發(fā)技術(shù)入門易,精通難。當(dāng)然,如果相對(duì)于其他的開(kāi)發(fā)技術(shù)來(lái)說(shuō),嵌入式學(xué)習(xí)門檻相對(duì)較高。但嵌入式如今的發(fā)展前景也要高于其他開(kāi)發(fā)
    發(fā)表于 07-03 18:25

    嵌入式Linux C概述

    嵌入式Linux C概述嵌入式系統(tǒng)是現(xiàn)在最熱門的計(jì)算機(jī)應(yīng)用領(lǐng)域之一,嵌入式
    發(fā)表于 12-15 08:32

    創(chuàng)信息技術(shù)WinCE系統(tǒng)多串口擴(kuò)展方案簡(jiǎn)介

     異步串行通訊口(UART)是在工業(yè)自動(dòng)化中應(yīng)用最為廣泛的通訊接口之一,其接口形式包括RS232C、RS485、RS422。作為以網(wǎng)絡(luò)通訊為特色的
    的頭像 發(fā)表于 10-31 15:15 ?1640次閱讀
    <b class='flag-5'>英</b><b class='flag-5'>創(chuàng)</b><b class='flag-5'>信息技術(shù)</b>WinCE系統(tǒng)多<b class='flag-5'>串口</b>擴(kuò)展方案簡(jiǎn)介

    創(chuàng)信息技術(shù)C#使用COM組件接口進(jìn)行串口操作介紹

    嵌入式主板采用WinCE操作系統(tǒng),很多客戶都選擇了界面友好、開(kāi)發(fā)便利的C#語(yǔ)言(使用Visual Studio 2005.NET集成開(kāi)發(fā)環(huán)境);在VS2005中,微軟提供了一個(gè)標(biāo)準(zhǔn)的串口
    的頭像 發(fā)表于 11-14 09:37 ?2240次閱讀
    <b class='flag-5'>英</b><b class='flag-5'>創(chuàng)</b><b class='flag-5'>信息技術(shù)</b><b class='flag-5'>C</b>#使用COM組件接口進(jìn)行<b class='flag-5'>串口</b>操作介紹

    創(chuàng)信息技術(shù)嵌入式系統(tǒng)設(shè)備驅(qū)動(dòng)接口的C#編程

    創(chuàng)ARM9系列嵌入式主板,均預(yù)裝了WinCE 5.0、WinCE 6.0操作系統(tǒng),用戶可使用標(biāo)準(zhǔn)的C/C++
    的頭像 發(fā)表于 01-15 11:29 ?1260次閱讀

    創(chuàng)信息技術(shù)嵌入式系統(tǒng)通訊線程的C#編程方法

    在使用創(chuàng)ARM9系列嵌入式主板的COM口,CAN口,網(wǎng)口時(shí),一般會(huì)使用到timer或線程來(lái)實(shí)現(xiàn)數(shù)據(jù)的接收。使用timer控件較為方便,通過(guò)InterVal值來(lái)設(shè)定調(diào)用間隔,但是靈活性不如線程。并且
    的頭像 發(fā)表于 01-15 11:25 ?1261次閱讀

    創(chuàng)信息技術(shù)嵌入式Linux主板Qt串口應(yīng)用程序簡(jiǎn)介

    串口和其他設(shè)備一樣,在Linux系統(tǒng)中都是以設(shè)備文件的形式存在的,在創(chuàng)公司提供的Linux主板配套光盤中,已經(jīng)提供了基于
    的頭像 發(fā)表于 01-17 09:41 ?1754次閱讀
    <b class='flag-5'>英</b><b class='flag-5'>創(chuàng)</b><b class='flag-5'>信息技術(shù)</b><b class='flag-5'>嵌入式</b><b class='flag-5'>Linux</b>主板Qt<b class='flag-5'>串口</b>應(yīng)用程序簡(jiǎn)介

    創(chuàng)信息技術(shù)Linux嵌入式工控板支持電容屏介紹

    隨著嵌入式應(yīng)用對(duì)GUI圖形界面需求的增加,Qt在Linux嵌入式設(shè)備中的使用越來(lái)越廣泛,許多應(yīng)用也都對(duì)人機(jī)交互界面有一定的要求。因此觸摸屏、鼠標(biāo)等設(shè)備等支持也變得重要起來(lái),
    的頭像 發(fā)表于 02-03 09:37 ?6019次閱讀
    <b class='flag-5'>英</b><b class='flag-5'>創(chuàng)</b><b class='flag-5'>信息技術(shù)</b><b class='flag-5'>Linux</b><b class='flag-5'>嵌入式</b>工控板支持電容屏介紹

    創(chuàng)信息技術(shù)嵌入式主板的無(wú)線通訊解決方案

    無(wú)線通訊是指利用公共2G / 3G / 4G網(wǎng)絡(luò)進(jìn)行的無(wú)線數(shù)據(jù)通訊,以及利用無(wú)線局域網(wǎng)WiFi的數(shù)據(jù)通訊。在當(dāng)前嵌入式領(lǐng)域,無(wú)線通訊單元的主
    的頭像 發(fā)表于 02-05 11:03 ?1396次閱讀

    創(chuàng)信息技術(shù)JAVA操作創(chuàng)主板SPI接口簡(jiǎn)介

    2017年9月,創(chuàng)Linux的文件系統(tǒng)中移植了針對(duì)嵌入式Linux的JRE(Java Runtime Environment),能夠支持
    的頭像 發(fā)表于 02-06 11:09 ?1861次閱讀
    <b class='flag-5'>英</b><b class='flag-5'>創(chuàng)</b><b class='flag-5'>信息技術(shù)</b>JAVA操作<b class='flag-5'>英</b><b class='flag-5'>創(chuàng)</b>主板SPI接口簡(jiǎn)介

    創(chuàng)信息技術(shù)JAVA操作創(chuàng)主板I2C接口簡(jiǎn)介

    2017年9月,創(chuàng)Linux的文件系統(tǒng)中移植了針對(duì)嵌入式Linux的JRE(Java Runtime Environment),能夠支持
    的頭像 發(fā)表于 02-06 11:06 ?1631次閱讀
    <b class='flag-5'>英</b><b class='flag-5'>創(chuàng)</b><b class='flag-5'>信息技術(shù)</b>JAVA操作<b class='flag-5'>英</b><b class='flag-5'>創(chuàng)</b>主板I2<b class='flag-5'>C</b>接口簡(jiǎn)介

    創(chuàng)信息技術(shù)Linux雙進(jìn)程應(yīng)用示例

    控制流程,應(yīng)用程序采用C/C++語(yǔ)言來(lái)編寫(xiě)。圖1表現(xiàn)了典型工控設(shè)備的組成關(guān)系。 典型工控設(shè)備框圖 工控設(shè)備的另一個(gè)特點(diǎn)是鑒于設(shè)備大多是24小時(shí)連續(xù)運(yùn)行,且無(wú)人值守,所以基本的工控設(shè)備是無(wú)顯示的。
    的頭像 發(fā)表于 02-06 11:34 ?1087次閱讀
    <b class='flag-5'>英</b><b class='flag-5'>創(chuàng)</b><b class='flag-5'>信息技術(shù)</b><b class='flag-5'>Linux</b>雙進(jìn)程應(yīng)用示例

    創(chuàng)信息技術(shù)嵌入式Linux主板多網(wǎng)口多路由方案

    主流的創(chuàng)嵌入式主板均支持雙網(wǎng)絡(luò)接口,其中支持ISA擴(kuò)展總線的主板型號(hào),如:EM335x、ESM335x、ESM6802、ESM6800V等,還可以通過(guò)ISA總線外接ETA728模塊,再擴(kuò)展兩路獨(dú)立
    的頭像 發(fā)表于 02-07 10:48 ?1737次閱讀
    <b class='flag-5'>英</b><b class='flag-5'>創(chuàng)</b><b class='flag-5'>信息技術(shù)</b><b class='flag-5'>嵌入式</b><b class='flag-5'>Linux</b>主板多網(wǎng)口多路由方案

    嵌入式Linux UART

    文章目錄前言串口連接串口測(cè)試C代碼微信公眾號(hào)前言這是前篇:嵌入式Linux i.MX開(kāi)發(fā)板嵌入式
    發(fā)表于 11-01 16:26 ?8次下載
    <b class='flag-5'>嵌入式</b><b class='flag-5'>Linux</b> UART