1. 程式人生 > >身是菩提樹,心如明鏡臺。時時勤擦拭,勿使惹塵埃。

身是菩提樹,心如明鏡臺。時時勤擦拭,勿使惹塵埃。

        在Linux下,串列埠裝置顯示在/dev目錄下,如果用的是USB轉的串列埠,我們執行下面的命令:

        ls /dev/ | grep tty

        就可以看到下面的資訊:

        ttyUSB0
        ttyUSB1

        在Linux作業系統下,一切皆檔案,我們讀寫這兩個檔案就是利用串列埠接收和傳送資料。可以用一根母對母的交叉線,將兩個串列埠連線起來,在一端傳送資料,另外一端就能收到資料。我們可以用一個叫做XGCom的工具測試。我們在ttyUSB0這端傳送資料,在ttyUSB1那邊就可以收到資料。

        當然我們也可以用C++程式設計讀寫串列埠,程式碼如下:

/*
 * SerialPort.h
 *
 *  Created on: 2014年11月3日
 *      Author: Richard
 */

#ifndef SERIALPORT_H_
#define SERIALPORT_H_

#include <stdio.h>
#include <fcntl.h>
#include <pthread.h>

//Message Format: head:2 bytes(0xFF,0xEE) | Command:1 byte | Data Size:1 byte  | Data:DataSize bytes
static const int HeadLen = 2;
static const int CommandLen = 1;
static const int DataSizeLen = 1;

class SerialPort
{
public:
    SerialPort();
    virtual ~SerialPort();
    bool Setup(const char *PortName, int BaudRate, int ByteSize, int Parity, int StopBit);
    bool Shutdown();
    bool CheckBuffer();
    void AdvanceBuffer(int Len);
    virtual void OnRecv();

private:
    static void *ReadFunc(void *Param);
    int m_PortHandle;
    pthread_t m_ThreadID;
    unsigned char m_Buffer[1024];
    int m_BufferSize;
    bool m_ThreadRunning;
};

#endif /* SERIALPORT_H_ */
/*
 * SerialPort.cpp
 *
 *  Created on: 2014年11月3日
 *      Author: jason
 */

#include "SerialPort.h"

#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <termios.h>

SerialPort::SerialPort()
{
    // TODO Auto-generated constructor stub
    m_PortHandle = -1;
    m_ThreadID = -1;
    memset(m_Buffer, 0, 1024);
    m_BufferSize = 0;
    m_ThreadRunning = true;
}

SerialPort::~SerialPort()
{
    // TODO Auto-generated destructor stub
}

bool SerialPort::Setup(const char *PortName, int BaudRate, int ByteSize,
               int Parity, int StopBit)
{
    m_PortHandle = open(PortName, O_RDWR | O_NOCTTY | O_NDELAY);
    if (m_PortHandle < 0) {
        return false;
    }

    struct termios Opt;

    tcgetattr(m_PortHandle, &Opt);
    Opt.c_cflag |= (CLOCAL | CREAD);    //設定控制模式狀態,本地連線,接收使能
    Opt.c_cflag &= ~CSIZE;                      //字元長度,設定資料位之前一定要屏掉這個位
    Opt.c_cflag &= ~CRTSCTS;                //無硬體流控
    Opt.c_cflag |= CS8;                             //8位資料長度
    Opt.c_cflag &= ~CSTOPB;                  //1位停止位
    Opt.c_iflag |= IGNPAR;                      //無奇偶檢驗位
    Opt.c_oflag = 0;                                    //輸出模式
    Opt.c_lflag = 0;                                    //不啟用終端模式
    cfsetospeed(&Opt, B9600);                   //設定波特率
    tcflush(m_PortHandle, TCIFLUSH);    //溢位資料可以接收,但不讀
    tcsetattr(m_PortHandle, TCSANOW, &Opt);     //TCSANOW:所有改變立即生效

    pthread_create(&m_ThreadID, NULL, ReadFunc, this);

    return true;
}

bool SerialPort::Shutdown()
{
    m_ThreadRunning = false;

    pthread_join(m_ThreadID, NULL);

    close(m_PortHandle);
    return true;
}

void SerialPort::AdvanceBuffer(int Len)
{
    for (int i = Len; i < m_BufferSize; i++)
    {
        m_Buffer[i - Len] = m_Buffer[i];
    }

    for (int i = m_BufferSize - Len; i < m_BufferSize; i++)
    {
        m_Buffer[i] = 0;
    }

    m_BufferSize -= Len;
}

void SerialPort::OnRecv()
{
    if (CheckBuffer())
    {
        int TotalLen = HeadLen + CommandLen + DataSizeLen + m_Buffer[3];

        char buff[200];
        memset(buff, 0, 200);

        int Index = sprintf(buff, "Received Data: ");
        for (int i = 0; i < TotalLen; i++)
        {
            Index += sprintf(buff + Index, "%.2X ", m_Buffer[i]);
        }

        sprintf(buff + Index, "\n");
        printf(buff);

        write(m_PortHandle, m_Buffer, TotalLen);

        AdvanceBuffer(TotalLen);
    }
}

bool SerialPort::CheckBuffer()
{
    bool Ret = false;


    if (m_BufferSize >= HeadLen + CommandLen + DataSizeLen )
    {
        if (m_Buffer[0] == 0xFF && m_Buffer[1] == 0xEE)
        {
            int TotalLen = HeadLen + CommandLen + DataSizeLen + m_Buffer[3];

            if ((m_Buffer[TotalLen] == 0xFF || m_Buffer[TotalLen] == 0x00) &&
                m_Buffer[TotalLen - 1] != 0x00)
            {
                Ret = true;
            }
        }
    }

    return Ret;
}

void *SerialPort::ReadFunc(void *Param)
{
    SerialPort *Port = (SerialPort *)Param;

    fd_set HandleSet;
    while(1)
    {
        FD_ZERO(&HandleSet);
        FD_SET(Port->m_PortHandle, &HandleSet);

        struct timeval tv;
        tv.tv_sec = 1;
        tv.tv_usec = 0;

        int Ret = select(Port->m_PortHandle + 1, &HandleSet, NULL, NULL, &tv);
        if (Ret < 0) {
            break;
        }

        if (FD_ISSET(Port->m_PortHandle, &HandleSet)) {
            int Len = read(Port->m_PortHandle, Port->m_Buffer + Port->m_BufferSize, 100);
            if (Len > 0) {
                   Port->m_BufferSize += Len;
                   Port->OnRecv();
            }
        }

        if (Port->m_ThreadRunning == false) {
            break;
        }

    }

    return NULL;
}

     我們在main函式裡面寫下測試程式碼:
/*
 * main.cpp
 *
 *  Created on: 2014年12月3日
 *      Author: Richard
 */

#include "SerialPort.h"
#include <unistd.h>

int main(int argc, char **argv) {
    SerialPort Port;
    Port.Setup("/dev/ttyUSB1", 9600, 8, 0, 0);

    for (int i = 0;  i < 20; ++ i) {
        sleep(1);
    }

    Port.Shutdown();
    return 0;
}


然後以root許可權執行:


        我們用XGCom開啟/dev/ttyUSB0,然後傳送0xFFEE0A09010203040506070809,在控制檯那邊就顯示收到的資料。我們程式開啟的是/dev/ttyUSB1,然後我們用收到的資料寫/dev/ttyUSB1,這樣XGCom那裡也收到了資料。就是我們剛才傳送的資料。

相關推薦

菩提樹鏡臺時時擦拭使塵埃

        在Linux下,串列埠裝置顯示在/dev目錄下,如果用的是USB轉的串列埠,我們執行下面的命令:         ls /dev/ | grep tty         就可以看到下面的資訊:         ttyUSB0         ttyUSB1

陳皓專欄 【空谷幽蘭皓月】

讓我們再來看一下使用者管理和程式所有者方面的東西。在Unix下,需要你做的是配置NIS伺服器和NFS伺服器(以Autofs自動mount),簡潔,清楚。到了Windows下,與其相似的是一個叫Domain的東西(主域控制器),首先,為了加入域,你需要重啟電腦(Unix下只需要配置/etc/nsswitch.c

無綵鳳【雙飛翼】有靈犀一點通

雙飛翼佈局 一、頁面佈局 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="wi

back-不忘初方得始終講講我主場3個月的經歷題外話

自己的 如果 主場 的人 公司 教訓 勞動力 好的 藝術品   終於過了這段糾結的時光,有人問,為什麽要工作?可能有的人會說,為了金錢,為了生存,不得已的去工作。但是我覺得工作的意義不僅在此。如果你不熱愛你的工作,你不對你的工作充滿熱情,你的工作不能帶給你成就感。那麽你一定

10.16輸入一個字符串內有數字和非數字字符,如: a123x456 17960? 302tab5876 將其中連續的數字作為一個整數依次存放到一數組num中例如123放在num[0]中456放在num[1]中……統計共有多少個整數並輸出這些數

tab lnp zip sm2 cuc ycm rds qt5 tft 10.16輸入一個字符串,內有數字和非數字字符,如: a123x456 17960? 302tab5876 將其中連續的數字作為一個整數,依次存放到一數組num中。例

蘭酒真正的洞藏美酒

好酒 車間 決定 制造 協調 般的 價值 作用 完成 什麽叫洞藏酒?洞藏酒的好處是什麽呢?白酒的儲藏是白酒制造的過程中必不可少的一道工序,白酒在釀造之後都要儲藏一年以上才能飲用。眾所周知,酒時間越長越好,但是這種觀念是片面的,決定酒品質的儲藏工藝有三大要素:時間、容器、環境

到底是個怎麽樣的人看她這樣對待自己的孩子你就知道了……

class html clas targe tar zha 1025. 自己 title http://www.jobccn.com/zhaopin/job_11684.htmlhttp://www.jobccn.com/zhaopin/job_11682.htmlhttp

1.為什麽 要需要變量二進制方便2.變量是什麽 ,3.聲變量

http info mage .com 技術分享 圖片 alt 什麽 png 1.為什麽 要需要變量。二進制,方便,2.變量是什麽 ,3.聲明變量

a=[123456]用程式碼求出a裡面三個數字組合並求出組合裡面的最大數可以組成123456125634563412561234341256345612

這個題目主要用到迴圈、字串拼接和排序,程式碼如下: a = [12,34,56] d = []  #儲存新的list for i in a:   for j in a:     for k in a:       if (i != j) and (j != k) and (i != k)

a=[123456]用代碼求出a裏面三個數字組合並求出組合裏面的最大數可以組成123456125634563412561234341256345612

eve rev 重復 最大 字符串拼接 代碼 lis end pen 這個題目主要用到循環、字符串拼接和排序,代碼如下: a = [12,34,56] d = [] #保存新的list for i in a:   for j in a:     for k in a:  

從命令列讀入一個字串表示一個年份輸出該年的世界盃冠軍是哪支球隊 果該年沒有舉辦世界盃則輸出:沒有舉辦世界盃

從命令列讀入一個字串,表示一個年份,輸出該年的世界盃冠軍是哪支球隊。如 果該年沒有舉辦世界盃,則輸出:沒有舉辦世界盃。 附錄:截止2009 年,歷屆世界盃冠軍、世界盃冠軍以及對應的奪冠年份: package cn.sc.test; import java.util.HashMap;

設有n個正整數將他們連線成一排組成一個最大的多位整數 :n=3時3個整數13,312,343,連成的最大整數為34331213

題目描述 設有n個正整數,將他們連線成一排,組成一個最大的多位整數。 如:n=3時,3個整數13,312,343,連成的最大整數為34331213。 如:n=4時,4個整數7,13,4,246連線成的最大整數為7424613。 輸入描述: 有多組測試樣例,每組測試樣例包含兩行,第一行為一

實現一個算法尋找字符串中出現次數最少的、並且首次出現位置最前的字符 "cbaacfdeaebb"符合要求的是"f"因為他只出現了一次(次數最少)並且比其他只出現一次的字符("d")首次出現的位置最靠前

出現一次 ole for else 尋找 cti 要求 最小值 一次 實現一個算法,尋找字符串中出現次數最少的、並且首次出現位置最前的字符如"cbaacfdeaebb",符合要求的是"f",因為他只出現了一次(次數最少)。並且比其他只出現一次的字符(如"d")首次出現的位置

12.15有一種數叫回文數正讀和反讀都一樣12321便是一個迴文數編寫一個程式從命令列得到一個整數判斷該數是不是迴文數

有一種數叫回文數,正讀和反讀都一樣,如12321便是一個迴文數。編寫一個程式,從命令列得到一個整數,判斷該數是不是迴文數 package Text6; import java.util.Scanner; public class Zuoyexuanzuo5 { public st

【疾風知勁草智者必懷仁】此生之路我將走過;走過這一次便再也無法重來所有力所能及的善行所有充盈於的善意我將毫不吝惜即刻傾於我將不再拖延再不淡漠只因此生之路再也無法重來醒掌天下事醉臥美人膝

此生之路,我將走過;走過這一次,便再也無法重來。所有力所能及的善行,所有充盈於心的善意,我將毫不吝惜,即刻傾於。我將不再拖延,再不淡漠,只因此生之路,再也無法重來。醒掌天下事,醉臥美人膝...

【倚天屠龍記】志是IBM全球敏捷官方發言人,有10年一線敏捷研發、測試、技術支援、管理、諮詢經驗為多家世界500強企業做敏捷諮詢和轉型服務期望通過自己在IBM親身經歷、經驗、感悟的分享幫助您實踐真正敏捷

倚天屠龍記 明志是IBM全球敏捷官方發言人,有10年一線敏捷研發、測試、技術支援、管理、諮詢經驗,為多家世界500強企業做敏捷諮詢和轉型服務。期望通過自己在IBM親身經歷、經驗、感悟的分享幫助您實踐真正敏捷。...

【《致青春》——雲夢澤】記住那些天 我找出這素水漫出的青蓮; 像是山間的流水溫柔 輕拍著湖石岸卻流淌著歡快憂愁; 像是天空的白鳥掠過眼隙 飛翔著園幽夢而忘不記你年輕時的嬌羞

記住那些天, 我找出這素水漫出的青蓮; 像是山間的流水溫柔, 輕拍著心湖石岸卻流淌著歡快憂愁; 像是天空的白鳥掠過眼隙, 飛翔著心園幽夢而忘不記你年輕時的嬌羞。...

【zoe 【 銀鈴花--給予幸福的勇氣】】【花語】鈴蘭誕生的憂傷傳說一樣鈴蘭的幸福會來得額外艱難並且伴隨著隱約的宿命的憂傷鈴蘭的守候是風中星星若有若無的嘆息茫然而幽靜只有有心才能感應;鈴蘭的氣質如同風中女子堅貞溫婉的愛的信仰一般純粹剔透

【花語】如鈴蘭誕生的憂傷傳說一樣,鈴蘭的幸福會來得額外艱難,並且伴隨著隱約的宿命的憂傷。鈴蘭的守候是風中星星若有若無的嘆息,茫然而幽靜,只有有心才能感應;鈴蘭的氣質如同風中女子堅貞溫婉的愛的信仰一般純...

C++入門題目:輸入一行電報文字將字母變成其下一字母(’a’變成’b’……’z’變成’a’其它字元不變)

#include<iostream> #include<string.h> #include<stdio.h> using namespace std; int main() {     char x[10000];     int b,d;          gets(x

努力+堅持而且還很年輕(夢在翱翔在路上不忘初砥礪前行

UML學習筆記詳解 最近一直在學習UML的基礎知識,對於UML的學習和理解需要不斷地進行,總結是必不可少,在此為大家分享一下我的UML學習筆記。