2009-10-20 87 views
2

問題: 我有一個手持設備,可以掃描所有包裝上的圖形顏色條形碼。有一個我可以使用的軌道設備會自動滑動設備。該跟蹤設備通過串行端口接收ascii碼來運行。我需要讓這個東西在Mac上的FileMaker中工作。所以沒有終端程序等...C++串行端口問題

我到目前爲止: 我買了Keyspan USB /串行適配器。使用名爲ZTerm的程序,我成功地向設備發送命令。 示例: 「C,7^M^J」

我還能夠使用該命令做同樣的事情在終端:屏幕/dev/tty.KeySerial1 57600 ,然後在上述相同的命令鍵入(但是當我輸入時,我只是命中Control-M和Control-J進行回車和換行)

現在我正在爲FileMaker編寫一個插件(當然是C++)。我想要得到上面我在C++中所做的事情,因此當我在FileMaker中安裝該插件時,我可以調用其中一個函數,並讓整個過程在那裏進行。

我可以連接到設備,但我無法與之通話。它沒有迴應任何事情。

我試着使用這些連接設備(成功):

FILE *comport; 
if ((comport = fopen("/dev/tty.KeySerial1", "w")) == NULL){...} 

int fd; 
fd = open("/dev/tty.KeySerial1", O_RDWR | O_NOCTTY | O_NDELAY); 

這是我一直在聊到設備的方式到目前爲止已經試過:

fputs ("C,7^M^J",comport); 

fprintf(comport,"C,7^M^J"); 

char buffer[] = { 'C' , ',' , '7' , '^' , 'M' , '^' , 'J' }; 
fwrite (buffer , 1 , sizeof(buffer) , comport); 

fwrite('C,7^M^J', 1, 1, comport); 

問題: 當我連接到從終端設備使用ZTerm,我能夠把我的波特我認爲這可能是它在這裏沒有迴應的原因。但我不知道如何在這裏做... ....有人知道如何做到這一點?我試過了,但它沒有工作:

comport->BaudRate = 57600; 

有很多類的解決方案,但他們都稱這些包括文件,如termios.h和stdio.h。我沒有這些,無論出於何種原因,我都找不到它們下載。我已經下載了一些例子,但是其中有20個文件,並且它們都調用了我找不到的其他文件(如上面列出的那些文件)。我需要找到這些,如果是的話,在哪裏?我只是不太瞭解C++有沒有一個網站,我可以下載庫?

另一種解決方案可能是將這些終端命令放在C++中。有沒有辦法做到這一點?

所以這一直讓我瘋狂。我不是C++的人,我只知道基本的編程概念。有沒有人有C++專家?理想情況下,我希望使用我已有的函數,比如fwrite,fputs等。 謝謝!

回答

5

發送一個^然後一個M不發送control-M,那就是你寫它的方式, 發送一個控制字符最簡單的方法就是使用ascii control代碼。

ps。^M是回車即「\ r」,^ J是換行符「\ n」

編輯:可能比您希望知道的要多 - 但在繼續閱讀之前請閱讀The Serial Port Howto

0

你確定你已經正確安裝了所有的編譯工具嗎?在我的OS X 10.5.8 Mac上, termios.h和stdio.h正好在/ usr/include下,正如我所期望的那樣。您已經在其他Unix變體的串行端口編程中找到的 代碼 僅需要在Mac上進行較小的更改(如果有)。你能告訴我們更多關於 你試過了什麼,出了什麼問題?

mgb對控制字符如何表示也有一個好的觀點。

1

這不是一個C++問題。你在問如何與TTY驅動程序交互來設置波特率。事實上,你打開/ dev下的文件告訴我你正在使用unix衍生產品,因此在linux系統上閱讀的相關手冊頁是「man 3 termios」。

基本上,您使用上面的open()變體,並將文件描述符傳遞給tcsetattr/tcgetattr。

0

您可以使用ioctl設置波特率。這是一個link to an example

+0

不幸的是,沒有便攜式TTY ioctl API。相反,使用POSIX API會更好。 C.F. termios,tcsetattr等。人。 – 2009-10-20 19:10:51

0

你不指定你使用的是哪個Unix,所以下面我發佈了一些我使用的Linux生產代碼。

請注意下面的代碼是一個類方法,因此忽略任何外部(即未聲明的)引用。

步驟如下 -

配置您的termio結構,這是你設置任何需要的標誌等(即您使用zterm下的termio設置來配置端口8個數據位,1個停止位完成的一步,沒有奇偶校驗(8-n-1),端口也會處於「原始」模式(與熟化模式相反),所以它的字符流,文本不會成幀等等。波特率常量與實際值匹配, 56700個波特率使用「57600」。

時序參數表示的字符從設備,儘快爲他們提供返回。

設置完Termainal參數後,打開設備(使用POSIX open()),然後可以使用tcgetattr/tcsetattr通過fd配置設備。

此時,您可以使用read()/ write()系統調用讀取/寫入設備。

請注意,在下面的示例中,如果沒有數據可用,則read()將會阻塞,因此如果阻塞不可取,則可能需要使用select()/ poll()。

希望有所幫助。

termios termio  
tcflag_t baud_specifier; 

    //reset device state... 
    memset (&termio, 0, sizeof (termios)); 
    read_buffer.clear(); 

    //get our boad rate... 
    if (!(baud_specifier = baud_constant (baud))) { 
     ostringstream txt; 
     txt << "invalid baud - " << baud; 
     device_status_msg = txt.str(); 
     status = false; 

     return (true); 
    } 


    //configure device state... 
    termio.c_cflag = baud_specifier | CS8 | CLOCAL | CREAD; 

    //do we want handshaking? 
    if (rtscts) { 
     termio.c_cflag |= CRTSCTS; 
    } 

    termio.c_iflag = IGNPAR; 
    termio.c_oflag = 0; 
    termio.c_lflag = 0; 

    //com port timing, no wait between characters and read unblocks as soon as there is a character 
    termio.c_cc[VTIME] = 0; 
    termio.c_cc[VMIN]  = 0; 

    //open device... 
    if ((fd = open (device.c_str(), O_RDWR | O_NOCTTY)) == -1) { 

     ostringstream txt; 
     txt << "open(\"" << device << "\") failed with " << errno << " - " 
      << std_error_msg (errno); 
     device_status_msg = txt.str(); 
     status = false; 

     return (true); 
    } 

    //keep a copy of curret device state... 
    if (tcgetattr (fd, &old_termio) == -1) { 

     ostringstream txt; 
     txt << "tcgetattr() failed with " << errno << " - " << std_error_msg (errno); 
     device_status_msg = txt.str(); 
     status = false; 

     return (true); 
    } 

    //flush any unwanted bytes 
    if (tcflush (fd, TCIOFLUSH) == -1) { 

     ostringstream txt; 
     txt << "tcflush() failed with " << errno << " - " << std_error_msg (errno); 
     device_status_msg = txt.str(); 
     status = false; 

     return (true); 
    } 

    //apply our device config... 
    if (tcsetattr (fd, TCSANOW, &termio) == -1) { 

     ostringstream txt; 
     txt << "tcsetattr() failed with " << errno << " - " << std_error_msg (errno); 
     device_status_msg = txt.str(); 
     status = false; 

     return (true); 
    } 

    node_log_f ("successfully initialised device %s at %i baud", "open_device()", 
       device.c_str(), baud); 

    status = true; 
    return (true); 
}