本文探討了一種簡單而經(jīng)濟的方法,通過使用DS80C400/DS80C410/DS80C411網(wǎng)絡(luò)微控制器改造基于微型互聯(lián)網(wǎng)接口(TINI?)平臺的傳統(tǒng)系統(tǒng),將獨立串行設(shè)備遷移到以太網(wǎng)。一旦設(shè)備連接到以太網(wǎng),實現(xiàn) TINI Web 服務(wù)(如 HTTP 服務(wù)器)就非常簡單了。
概述
使用串行端口作為與其他電子設(shè)備通信手段的設(shè)備數(shù)量驚人。事實上,對于許多人來說,串行端口提供了與外界通信的唯一機制 - 包括恒溫器、銷售點系統(tǒng)、遠程監(jiān)視器、條形碼閱讀器、收據(jù)打印機、RFID 收發(fā)器、血壓計等等,涉及從傳統(tǒng)測試工具到最新的樓宇自動化等領(lǐng)域。這些設(shè)備沒有直接參與更大的計算機網(wǎng)絡(luò)的方法,但新的應(yīng)用程序需要TCP / IP連接和以太網(wǎng)功能。通常,昂貴且耗時的重新設(shè)計不是一種選擇。
本文探討了一種簡單而經(jīng)濟的方法,通過使用DS80C400微控制器改造基于TINI?平臺的傳統(tǒng)系統(tǒng),將獨立串行設(shè)備遷移到以太網(wǎng)。一旦設(shè)備連接到以太網(wǎng),實現(xiàn) TINI Web 服務(wù)(如 HTTP 服務(wù)器)就非常簡單了。
RS-232 串行端口
本文中討論的異步串行通信基于RS-232-C標(biāo)準(zhǔn),該標(biāo)準(zhǔn)可以追溯到記錄計算機歷史的早期;RS-232-C 于 1969 年發(fā)布1。大多數(shù)現(xiàn)代串行端口不支持標(biāo)準(zhǔn)中定義的所有信號 - 并且實現(xiàn)的信號的使用方式僅與標(biāo)準(zhǔn)中定義的方式“相當(dāng)接近”。我們將忽略純粹的歷史定義,專注于RS-232的使用方式。
空格和標(biāo)記
RS-232-C將+3V至+25V的電壓電平指定為“SPACE”(二進制0),將-3V至-25V的電壓電平指定為“MARK”(二進制1)。-3V和+3V之間的區(qū)域是“開關(guān)區(qū)域”。許多UART(通用異步接收器發(fā)送器)對0和5使用更現(xiàn)代(相對而言)的TTL電壓電平0V和+1V。專用電平轉(zhuǎn)換器,如著名的MAX-232,在TTL和RS-232電平之間轉(zhuǎn)換。由于DS80C400/DS80C410/DS80C411上的串行端口是TTL電平,因此在與另一個TTL電平UART接口時不需要電平轉(zhuǎn)換器。
DCE(數(shù)據(jù)通信設(shè)備)和DTE(數(shù)據(jù)終端設(shè)備)是通信通道的兩個端點。主要區(qū)別在于串行連接器引腳排列(所謂的零調(diào)制解調(diào)器可用于在兩者之間進行轉(zhuǎn)換)。
表 1 顯示了使用零調(diào)制解調(diào)器時 DB-9 DTE 串行連接器上的信號和另一個 DTE 上的相應(yīng)信號。
表 1.DB-9 DTE 串行連接器信號 | ||
DTE 引腳 | 信號名稱 | 零調(diào)制解調(diào)器 |
1 | 光盤(載波檢測) | 4 (DTR) |
2 | RD(接收數(shù)據(jù)) | 3 (道明) |
3 | TD(傳輸數(shù)據(jù)) | 2 (RD) |
4 | DTR(數(shù)據(jù)終端就緒) | 6 (DSR) 和 1 (CD) |
5 | 公共(信號接地) | 5(普通) |
6 | DSR(數(shù)據(jù)集就緒) | 4 (DTR) |
7 | 即時戰(zhàn)略(請求發(fā)送) | 8 (CTS) |
8 | CTS(清除發(fā)送) | 7 (即時戰(zhàn)略) |
9 | RI (環(huán)形指示器) | 不適用 |
流控制
串行通信可以通過在一個引腳(TD)上發(fā)送并在另一個引腳(RD)上偵聽來實現(xiàn)。但是,當(dāng)兩臺通過RD通信的設(shè)備時,TD隨意傳輸,其中一個可能會溢出另一個,從而導(dǎo)致數(shù)據(jù)丟失。通常有兩種方式實現(xiàn)流控制:
- XON/XOFF(通常松散地稱為軟件流控制) - RTS/CTS(通常松散地稱為硬件流控制)
XON/XOFF 流控制方案傳輸帶內(nèi)字符,導(dǎo)致另一端暫停(XOFF,13h)和恢復(fù)(XON,11h)傳輸。XON 和 XOFF 字符必須由發(fā)送方在軟件中轉(zhuǎn)義,如果它們出現(xiàn)在二進制數(shù)據(jù)流中,則由接收方解開包裝。
RTS/CTS使用額外的信令線。RTS(發(fā)送請求)由發(fā)送方斷言。當(dāng)接收方準(zhǔn)備好接收數(shù)據(jù)時,接收方使用 CTS(清除發(fā)送)進行響應(yīng),在其接收緩沖區(qū)已滿時清除 CTS。
有些設(shè)備支持流控制,有些則不支持。因此,默認(rèn)值通常設(shè)置為“無流控制”,如果已知設(shè)備實現(xiàn)流控制,則應(yīng)覆蓋該默認(rèn)值。
速度、數(shù)據(jù)位、停止位和奇偶校驗
為了使通信成功,必須正確設(shè)置的其他參數(shù)當(dāng)然是傳輸速度(比特率),數(shù)據(jù)和停止位的數(shù)量以及奇偶校驗的類型(如果有的話)。大多數(shù)新設(shè)備使用“8N1”設(shè)置,這意味著 8 個數(shù)據(jù)位、無奇偶校驗和 1 個停止位。但是,眾所周知,遺留系統(tǒng)使用所有可能性,因此正確的設(shè)置實際上可能不是那么簡單。
天尼與網(wǎng)絡(luò)
TINI(微型互聯(lián)網(wǎng)接口)是達拉斯半導(dǎo)體公司開發(fā)的技術(shù)平臺,允許在DS80C400/DS80C410/DS80C411微控制器上快速開發(fā)。具體來說,TINI包含一個芯片組定義,以及一個與高度優(yōu)化的Java? 1.1運行時環(huán)境集成的嵌入式操作系統(tǒng)。使用Java,程序員可以從嵌入式開發(fā)中不常見的強大功能中受益:多線程,垃圾收集,繼承,虛擬化,跨平臺功能,強大的網(wǎng)絡(luò)支持,以及最后但并非最不重要的一點是,大量的免費開發(fā)工具。TINI用戶通常不受匯編語言編碼的影響。但是,支持并鼓勵使用本機語言子例程來優(yōu)化速度關(guān)鍵路徑或低級硬件訪問(TINI 操作系統(tǒng)是用本機代碼編寫的,因此串行 I/O 吞吐量與現(xiàn)代 PC 沒有顯著差異)。
除了完全支持 java.net 包之外,TINI Java 1.1 運行時還包含 javax.comm 子系統(tǒng)的實現(xiàn)。由于TCP/IP和串行端口都可以從Java輕松訪問,因此TINI系統(tǒng)很容易實現(xiàn)串行到以太網(wǎng)橋接。
TINI環(huán)境在TINI規(guī)范和開發(fā)人員指南(Addison-Welsey,2001)中有詳細的記錄。
例子
我們將從兩個具體的應(yīng)用程序開始,然后介紹一個通用串行到以太網(wǎng)程序的簡短摘錄,該程序可以修改以適應(yīng)幾乎任何特定應(yīng)用程序。這些示例是使用 TINIm400 驗證模塊構(gòu)建的。
圖1.
TINI驗證模塊可以用作“黑匣子”,將多個串行設(shè)備連接到以太網(wǎng)。根據(jù)終端設(shè)備的需要,TINI可以直接傳遞數(shù)據(jù),也可以解析、解釋和修改數(shù)據(jù)流。
請注意,雖然您可以在 TINIm400 上運行 slush 開發(fā)人員外殼中的示例,但更完善的應(yīng)用程序?qū)Ⅰv留在閃存中,在斷電時自啟動,并使用其他 TINI 構(gòu)造技術(shù)使成品幾乎堅不可摧。
需要一些基本的網(wǎng)絡(luò)知識和編程經(jīng)驗才能修改示例。工作示例代碼也可從Maxim下載。
虛擬調(diào)制解調(diào)器
第一個示例是“虛擬調(diào)制解調(diào)器”2,它使用 TINIm400 將物理調(diào)制解調(diào)器和電話線替換為 TCP/IP 連接。假設(shè)像工廠“機器狀態(tài)監(jiān)視器”這樣的傳統(tǒng)設(shè)備,它使用調(diào)制解調(diào)器每天多次撥入中央服務(wù)器,以報告機器狀態(tài)、負(fù)載和效率數(shù)據(jù)。為了消除服務(wù)器端對不斷增長的調(diào)制解調(diào)器庫的需求,并且能夠使用現(xiàn)有的LAN而不是設(shè)備的電話線,可以
- 將服務(wù)器軟件重寫為基于 TCP/IP 和
- 使用 TINI 虛擬調(diào)制解調(diào)器替換每臺計算機上的原始調(diào)制解調(diào)器
但是,機器狀態(tài)監(jiān)視器不必修改,因為就終端設(shè)備而言,虛擬調(diào)制解調(diào)器的行為類似于真正的調(diào)制解調(diào)器!
當(dāng)然,虛擬調(diào)制解調(diào)器也可以成對使用,而不是上述配置。使用兩個虛擬調(diào)制解調(diào)器時,根本不需要更改服務(wù)器軟件,TINI模塊是現(xiàn)有調(diào)制解調(diào)器的直接替代品。
在后臺,虛擬調(diào)制解調(diào)器在收到“ATD”調(diào)制解調(diào)器撥號命令時建立 TCP 連接。“ATH”斷開連接命令將關(guān)閉 TCP 連接。該軟件還實現(xiàn)了許多其他經(jīng)典的AT調(diào)制解調(diào)器命令,例如,被Microsoft? Windows?網(wǎng)絡(luò)識別為真正的調(diào)制解調(diào)器。此外,虛擬調(diào)制解調(diào)器偵聽TCP端口本身,并可以應(yīng)答由“RING”向終端設(shè)備發(fā)出信號的傳入“呼叫”。
以下代碼片段演示如何初始化 TINIm400 上的串行端口:
public static void main(String args[]) { TINIOS.setSerialBootMessagesState(false); TINIOS.setDebugMessagesState(false); TINIOS.setConsoleOutputEnabled(false); System.out.println("Connecting to serial0 at 9600bps, " "listening on TCP port 8001"); try { CommPortIdentifier portId = CommPortIdentifier.getPortIdentifier("serial0"); SerialPort port = (SerialPort) portId.open("VModemTINI", 10000); TINIOS.setRTSCTSFlowControlEnable(1, false); TINIOS.setRTSCTSFlowControlEnable(0, true); TCPSerialVirtualModem modem = new TCPSerialVirtualModem(port, /* Comm speed */ 9600, /*TCP Port */ 8001); modem.processInput(); } catch (Exception e) { System.out.println("Exception: "+e.toString()); } }
該代碼首先禁用所有 TINI 操作系統(tǒng)調(diào)試輸出,這是 TINI 的標(biāo)準(zhǔn)做法。獲取端口標(biāo)識符后,將打開該端口(第二個參數(shù)告訴 open 如果該端口當(dāng)前正由另一個應(yīng)用程序使用,則等待多長時間)。接下來,設(shè)置硬件流控制的狀態(tài)。由于 TINIm400 只有一組用于串行端口 0 和 1 的 RTS/CTS 線路,因此程序應(yīng)始終禁用另一個端口上的流量控制,然后再在所需端口上啟用它。接下來,實例化 Java 虛擬調(diào)制解調(diào)器。
虛擬調(diào)制解調(diào)器類由 AT 命令解釋器(此處未顯示,盡管到目前為止是示例的最大部分)和網(wǎng)絡(luò)代碼組成。以下代碼設(shè)置串行端口比特率、數(shù)據(jù)和停止位以及奇偶校驗,并顯示處理入站連接的難易程度:
/** Creates a new VirtualModem connected to a serial port on * one end and a TCP port on the data side. * serial -- the serial port this VirtualModem talks to. * speed -- the speed the serial port should be set to. * tcpport -- the TCP port this VirtualModem listens on. * throws IOException when there's a problem with the serial or TCP port. */ public TCPSerialVirtualModem(SerialPort serial, int speed, int tcpport) throws IOException { super(serial); try { serial.setSerialPortParams(speed, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); } catch (UnsupportedCommOperationException e) { throw new IOException(); } ... serverSock = new ServerSocket(tcpport, 1); // backlog of one listenThread = new listenInbound(); listenThread.start(); }
最后,以下 listenThread() 摘錄接受傳入的連接請求:
public void run() { int rc; Socket s; while (running) { s = null; // No incoming connection request try { answered = false; s = serverSock.accept(); // Discard incoming connection if already connected if (connected) throw new IOException(); sock = s; // for answer() ...
不間斷電源監(jiān)控器
第二個示例將 TINIm400 連接到不間斷電源的串行端口。該軟件實現(xiàn)了網(wǎng)絡(luò)UPS工具協(xié)議3,允許各種平臺上的各種客戶端監(jiān)控UPS狀態(tài)和運行狀況(該項目源于需要從沒有任何串行端口的新Macintosh計算機監(jiān)控現(xiàn)有UPS)。
UPS設(shè)備有兩種基本類型:所謂的“智能”設(shè)備和簡單(或“啞”)的設(shè)備。一個簡單的UPS在幾個串行引腳上發(fā)出其狀態(tài)信號,它實際上并不發(fā)送任何ASCII數(shù)據(jù)。由于串行引腳不是很多,它只能報告非常有限的一組信息,例如:
信號 | 意義 |
即時戰(zhàn)略(來自不間斷電源)) | 低電量 |
道明(來自 UPS) | 使用電池 |
CTS(來自 UPS) | 終止 UPS 電源 |
javax.comm.notifyOn...() 方法可以在 Java 中用于輕松實現(xiàn)對狀態(tài)更改做出反應(yīng)的代碼,例如:
... // Listen for DTR changes try { port.addEventListener(this); } catch (TooManyListenersException e) { ... } port.notifyOnDSR(true); ... public void serialEvent(SerialPortEvent ev) { try { if (ev.getEventType() == SerialPortEvent.DSR) ... } catch ... ... }
智能UPS更有趣,因為它實現(xiàn)了串行協(xié)議,并且可以返回電池充電百分比或溫度等值。不同供應(yīng)商之間的協(xié)議差異很大,而且通常沒有記錄。
以下代碼演示如何接收 UDP 請求并通過 UDP 發(fā)送 UPS 狀態(tài)信息。
// Listen to incoming UDP requests private class listenUDPThread extends Thread { private DatagramSocket sock; private byte[] buffer; private DatagramPacket dp; public listenUDPThread(DatagramSocket s) { sock = s; buffer = new byte[BUF_SIZE]; dp = new DatagramPacket(buffer, buffer.length); } public void run() { while (running) { try { sock.receive(dp); byte[] data = parseCommand(buffer, dp.getLength()); sock.send(new DatagramPacket(data, data.length, dp.getAddress(), dp.getPort())); } catch (Exception e) { } } try { sock.close(); } catch (Exception e) { } } }
由于 Java 中內(nèi)置了強大的網(wǎng)絡(luò)支持,此示例幾乎是不言自明的。while() 循環(huán)中的代碼會等待,直到它收到 UDP 請求,解析它并向請求的發(fā)起方發(fā)送答案(在傳入數(shù)據(jù)包上使用 getAddress()。
通用串行到以太網(wǎng)應(yīng)用
完整的串行到以太網(wǎng)示例超出了本文的范圍。(完整的示例在 TINI 規(guī)范和開發(fā)人員指南中顯示和解釋。但是,以下代碼片段演示如何有效地使用多線程在串行到以太網(wǎng)網(wǎng)橋的串行和網(wǎng)絡(luò)部分之間傳輸數(shù)據(jù)。串行端口和TCP端口被抽象為輸入/輸出流dataIn和dataOut,因此這一層代碼實際上根本不需要知道有關(guān)網(wǎng)絡(luò)的任何信息,并且還可以在CAN和1-Wire之間橋接數(shù)據(jù)。
public GenericBridge() { ... running = true; dcThread = new dataCopy(); dcThread.start(); } // Thread that copies everything from dataIn to dataOut private class dataCopy extends Thread { public void run() { int r = 0; while (running && r >= 0) { try { synchronized (threadLock) { r = dataIn.read(dataBuffer); if (r > 0) dataOut.write(dataBuffer, 0, r); } } catch (Exception e) { r = -1; ... // Handle error } } } }
結(jié)論
許多傳統(tǒng)設(shè)備僅支持異步串行通信,但當(dāng)前應(yīng)用需要以太網(wǎng)連接和 TCP/IP 網(wǎng)絡(luò)。DS80C400/DS80C410/DS80C411微控制器采用強大的Java運行時和TINI技術(shù),開發(fā)串行到以太網(wǎng)轉(zhuǎn)換器非常簡單,只需幾個小時即可完成。
審核編輯:郭婷
-
微控制器
+關(guān)注
關(guān)注
48文章
7649瀏覽量
152097 -
以太網(wǎng)
+關(guān)注
關(guān)注
40文章
5460瀏覽量
172713 -
JAVA
+關(guān)注
關(guān)注
19文章
2974瀏覽量
105135
發(fā)布評論請先 登錄
相關(guān)推薦
評論