王明輝,雷衛(wèi)延,黃海,譚晗凌
(廣東省氣象探測數(shù)據(jù)中心,廣東廣州 510640)
在自動氣象觀測領(lǐng)域,有大量觀測設(shè)備和通信設(shè)施通過串口配置參數(shù)或輸出氣象報文,需要借助電腦才能準(zhǔn)確檢查串口通信是否正常[1-3]。由于筆記本電腦配備成本高、攜帶不方便,因此,很多維保人員在維修現(xiàn)場無電腦可用,對串口通信故障束手無策,難以準(zhǔn)確定位故障點。
Android是Google公司主導(dǎo)開發(fā)的一種基于Linux的開源操作系統(tǒng),廣泛應(yīng)用于通信、物流、互聯(lián)網(wǎng)行業(yè),基于Android系統(tǒng)的智能手機在全球智能手機市場占有率已經(jīng)超過Apple公司搭載ios系統(tǒng)的iphone,排名第1。近年來,氣象行業(yè)已經(jīng)基于Android智能手機開展了一些應(yīng)用,顯著地提高了效率[4-9]。本研究基于Android手機的USB-OTG功能研發(fā)了一套便攜的串口通信套件,實現(xiàn)Android手機APP與氣象觀測設(shè)備串口雙向通信,使維保人員在維修現(xiàn)場能夠通過Android手機方便、高效、準(zhǔn)確地檢查設(shè)備的串口工況,具有很高的業(yè)務(wù)應(yīng)用價值。
套件架構(gòu)如圖1所示。
圖1 套件架構(gòu)示意圖
USB協(xié)議是一種用于計算機與外設(shè)方便連接的數(shù)據(jù)總線,建立連接的2個USB設(shè)備分為主設(shè)備 host和從設(shè)備 device(又稱 slave),僅當(dāng)host與device連接時才能傳輸數(shù)據(jù)。OTG是對USB 2.0協(xié)議的補充,其最重要的擴展是更節(jié)能的電源管理和允許設(shè)備以host和device兩種形式工作[10-12]。目前絕大部分Android手機支持OTG協(xié)議,當(dāng)該種手機通過USB連接電腦時,電腦為host,手機為device。在本方案中,串口通信套件包含硬件轉(zhuǎn)換模塊和運行在Android手機上的APP軟件,Android手機工作形式為host,硬件轉(zhuǎn)換模塊為device。轉(zhuǎn)換模塊擁有一個Micro-USB接口和一個RS232串口,當(dāng)模塊的Micro-USB接口與Android手機相連時,APP軟件自動啟動,再將RS232串口與自動氣象站等設(shè)備的串口連接,即可建立手機到設(shè)備的RS232串口通信。
常用的 USB轉(zhuǎn)串口芯片有 CH340、FT232、PL2303等系列[13-15],這些芯片的最新版本多已加入對 Android系統(tǒng)的支持。PL2303HXD是Prolific公司PL2303系列第5代USB轉(zhuǎn)TTL電平串口芯片,支持Android系統(tǒng),因性價比最高而廣泛商用。該芯片自帶12 MHz晶振,支持75~12 Mbp波特率,完全滿足自動氣象觀測設(shè)備常采用的1 200、9 600波特率。芯片支持以5、6、7、8位數(shù)據(jù)位和1、2位停止位收發(fā),校驗方式可選奇校驗、偶校驗或無校驗,滿足自動氣象觀測設(shè)備常用的串口配置,如7位數(shù)據(jù)位、1位停止位、偶校驗,或8位數(shù)據(jù)位、1位停止位、無校驗。芯片具有可配置的512 Byte雙向數(shù)據(jù)緩沖器,本套件將輸入和輸出緩沖區(qū)分別配置為256 Byte,通過編程循環(huán)讀取、寫入緩沖區(qū)實現(xiàn)串口讀取、發(fā)送。由于自動氣象站等設(shè)備的串口為RS232電平,在與PL2303HXD通信時還需要做RS232-TTL電平的轉(zhuǎn)換。該套件采用了 NI公司的MAX202芯片與PL2303HXD配合,實現(xiàn)RS232電平和TTL電平的相互轉(zhuǎn)換。硬件轉(zhuǎn)換模塊在物理上實現(xiàn)了USB-RS232信號轉(zhuǎn)換。
硬件轉(zhuǎn)換模塊設(shè)計通過Micro-USB型接口與手機建立OTG連接,該接口為5線制,依次定義為 VBUS、DM、DP、ID、GND。PL2303HXD和MAX202芯片工作電壓均為+5 V,典型電流分別為20和8 mA,滿足手機OTG接口的帶負(fù)載能力,故設(shè)計轉(zhuǎn)換模塊通過VBUS、GND從手機的Micro-USB接口獲取+5 V供電。為防止芯片經(jīng)電源線從手機引入干擾,或轉(zhuǎn)換模塊傳輸數(shù)據(jù)時產(chǎn)生高頻信號通過電源線傳入手機,在VBUS、GND傳輸線上各設(shè)計一個80μH的電感抑制高頻信號。根據(jù)OTG協(xié)議,手機USB端口內(nèi)部ID線上拉,默認(rèn)工作在device狀態(tài)。轉(zhuǎn)換模塊設(shè)計ID線與GND短接,與手機連接后將手機USB端口的ID線下拉,使手機進入host狀態(tài)。
DM、DP是一對傳輸數(shù)據(jù)的差分信號線,在手機USB端口內(nèi)部,DM和DP各連接一個15 kΩ的下拉電阻,設(shè)計轉(zhuǎn)換模塊的DP接口連接一個1.5 kΩ的上拉電阻,兩者連接時手機的DP電平被拉高,從而將 PL2303HXD識別為全速USB。為防止數(shù)據(jù)傳輸過程中的高速信號在端口附近產(chǎn)生反射,模塊在盡量靠近PL2303HXD芯片的DM和DP上各串聯(lián)一個22Ω的匹配電阻。在數(shù)據(jù)傳輸時,芯片U1、U2間TTL電平的TXD、RXD信號線會發(fā)生高速的高低電平翻轉(zhuǎn),模塊在VBUS和TXD、RXD之間設(shè)計了LED用于顯示數(shù)據(jù)傳輸情況。當(dāng)TXD、RXD信號線為低電平時,利用1 kΩ的限流電阻使得通過LED的電流<3 mA,LED導(dǎo)通發(fā)光。轉(zhuǎn)換模塊核心電路如圖2所示。
圖2 轉(zhuǎn)換模塊核心電路示意圖
為實現(xiàn)Android手機的OTG通信,需要開發(fā)與轉(zhuǎn)換模塊匹配的APP軟件。PL2303HXD芯片原廠提供了JAR驅(qū)動庫,支持系統(tǒng)版本3.2(API Level 13)以上的Android手機,不需要root即可實現(xiàn)OTG通信。本研究搭建了Eclipse+ADT+Android SDK開發(fā)環(huán)境,基于JAVA語言和驅(qū)動庫pl2303multilib.jar開發(fā)了APP軟件,軟件可運行在Android 3.2及以上版本的Android手機上。軟件測試平臺為魅族牌Android手機,Android版本7.1.2。
軟件設(shè)計為單Activity窗體,包含串口參數(shù)設(shè)置、串口讀取顯示、串口發(fā)送3個功能區(qū),如圖3所示。串口參數(shù)包括波特率、校驗位、數(shù)據(jù)位、停止位,均采用Spinner控件進行選擇。Android手機檢測到轉(zhuǎn)換模塊插入后自動啟動軟件,設(shè)置串口參數(shù)后點擊“打開”Button打開串口,軟件自動讀取串口信息并顯示在TextView控件中,當(dāng)收到下一條信息時自動刷新顯示。發(fā)送時,將待發(fā)送信息輸入EditText控件,點擊“發(fā)送”Button實現(xiàn)信息發(fā)送。
圖3 APP軟件界面
軟件打開是Activity窗體進入Running狀態(tài)的過程,Activity需要依次經(jīng)過onCreate()-->onStart()-->onResume()3個生命周期。在onCreate()方法中對窗體界面進行渲染,將控件初始化并設(shè)置事件監(jiān)聽,一旦觸發(fā)則執(zhí)行相應(yīng)方法。在Spinner控件初始化時設(shè)置選擇條目監(jiān)聽setOnItemSelectedListener,當(dāng)選擇串口參數(shù)時,觸發(fā)執(zhí)行MyOnItemSelectedListener類的onItem-Selected()方法,實現(xiàn)串口參數(shù)修改。
//渲染窗體
setContentView(R.layout.activity_main);//波特率選擇控件初始化
spBaudRate1=(Spinner)findViewById(R.id.DevSpinner1);
ArrayAdapter<CharSequence>adapter=ArrayAdapter.createFromResource(this,R.array.BaudRateList,android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spBaudRate1.setAdapter(adapter);
spBaudRate1.setOnItemSelectedListener(new MyOnItemSelectedListener());
APP軟件的串口參數(shù)缺省設(shè)置為9 600、N、8、1。以波特率為例,9 600在Spinner下拉列表中排序第5,在初始化時,需通過setSelection()方法將第5項設(shè)置為缺省。
//缺省波特率設(shè)置為9 600
spBaudRate1.setSelection(5);
spBaudRate1.setEnabled(false);
在 Button、CheckBox、EditText等控件初始化時,設(shè)置點擊事件監(jiān)聽setOnClickListener。在點擊“打開”Button時,觸發(fā)執(zhí)行 OpenUARTDevice()方法。
//設(shè)置“打開”Button的點擊事件監(jiān)聽
btOpen1 = (Button)findViewById(R.id.OpenButton1);
btOpen1.setOnClickListener(new Button.On-ClickListener(){
public void onClick(View v){
OpenUARTDevice(DeviceIndex1);
}
});
在OpenUARTDevice()方法中,根據(jù)onItem-Selected()方法設(shè)置的串口參數(shù)或缺省串口參數(shù)打開串口,其中boolean型返回值res如為true,表明串口打開成功。
//按照預(yù)設(shè)串口參數(shù)打開串口
res=mSerialMulti.PL2303OpenDevByUARTSetting (index, info.mBaudrate,info.mDataBits,info.mStopBits,info.mParity,info.mFlowControl);
在串口打開后,依然可以在onItemSelected()方法中修改串口參數(shù),并重新建立串口連接。
//重設(shè)串口參數(shù)
res=mSerialMulti.PL2303SetupCOMPort(iSelected,info.mBaudrate,info.mDataBits,info.mStopBits,info.mParity,info.mFlowControl);
APP軟件在讀取串口信息時,并不知道信息何時發(fā)送,也不知道信息的長度,需要定時檢查是否有信息傳來。本研究建立了一個單獨的串口讀取子線程,在子線程中持續(xù)訪問PL2303HXD芯片輸出緩沖區(qū),以便在溢出或覆蓋前及時將串口發(fā)來的信息取出,流程如圖4所示。
圖4 串口讀取流程示意圖
利用Runnable接口創(chuàng)建子線程是Android系統(tǒng)中常用的技術(shù),通過重寫其run()方法來實現(xiàn)程序功能。本研究基于此建立了串口讀取子線程ReadLoop1,在其run()方法中通過for循環(huán)不斷讀取串口輸出緩沖區(qū)。子線程在主線程中通過Thread實例創(chuàng)建并運行,直至軟件退出才結(jié)束。
//啟動串口讀取子線程
new Thread(ReadLoop1).start();
……
//子線程的實現(xiàn)
private Runnable ReadLoop1=new Runnable(){
public void run(){
for(;;){
//延時 50ms
DelayTime(50);
……
}
}
};
驅(qū)動庫pl2303multilib.jar提供了串口的讀取方法PL2303Read(),本研究在每個for循環(huán)中讀取一次輸出緩沖區(qū),讀取的信息保存在字節(jié)型數(shù)組ReadBuf1中,int型返回值ReadLen1為本次讀取信息的長度。緩沖區(qū)內(nèi)的數(shù)據(jù)為Byte格式,讀出后轉(zhuǎn)換為字符串并追加到ReadBufOrig中,多次讀取的數(shù)據(jù)長度累加為ReadLen。for循環(huán)需要在PL2303HXD芯片輸出緩沖區(qū)寫滿之前將數(shù)據(jù)讀出,并將緩沖區(qū)清空,以便后續(xù)信息從緩沖區(qū)的開始位置繼續(xù)寫入。在for循環(huán)中檢測到某次讀取為空時,表明一次數(shù)據(jù)傳輸完畢,整條數(shù)據(jù)已完全存放于字符串ReadBufOrig中,總長度為ReadLen。
//讀取PL2303HXD芯片輸出緩沖區(qū)
ReadLen1=mSerialMulti.PL2303Read(DeviceIndex1,ReadBuf1);
for(int j=0;j<ReadLen1;j++){
sbHex.append((char) (ReadBuf1[j]&0x000000FF));
}
ReadBufOrig=ReadBufOrig+sbHex.toString();
ReadLen+=ReadLen1;
在Android系統(tǒng)中,主線程只負(fù)責(zé)初始化和界面顯示等任務(wù),費時的操作全部放到子線程執(zhí)行,在子線程完成運算需要顯示時,必須將要顯示的信息傳遞給主線程,通過主線程完成顯示。一次數(shù)據(jù)傳輸完畢后,需要將讀取到的信息顯示到軟件窗體的TextView控件上。本研究利用Handler.post(Runnable)方法將讀取完整的字符串格式信息傳遞到主線程,在主線程更新Text-View顯示控件tvRead1,實現(xiàn)讀取數(shù)據(jù)的顯示。在接收到下一條串口信息時,tvRead1刷新顯示新接收的信息。DZZ1-2新型自動氣象站在開機時通過串口輸出一系列中文編碼的系統(tǒng)說明[16],為兼容顯示,字符串在顯示前轉(zhuǎn)換為GBK字符集編碼。
//在主線程中創(chuàng)建Handler
HandlermHandler1=new Handler();……
//在子線程中通過 Handler.post(Runnable)方法更新主線程UI
mHandler1.post(new Runnable(){public void run(){
//轉(zhuǎn)換為GBK字符集編碼ReadBuf=new String(ReadBufOrig.getBytes(“ISO-8859-1”),“GBK”);
//更新 TextView顯示
tvRead1.setText(ReadBuf);
……}
});
軟件的串口發(fā)送功能需要人工輸入待發(fā)送內(nèi)容,通過點擊“發(fā)送”按鍵完成串口發(fā)送。程序初始化時對串口“發(fā)送”Button控件設(shè)置了點擊事件監(jiān)聽 setOnClickListener,重寫其 WriteT-oUARTDevice()方法,利用驅(qū)動庫pl2303multilib.jar提供的串口發(fā)送方法PL2303Write()將要發(fā)送的信息按字節(jié)寫入PL2303HXD芯片輸入緩沖區(qū),通過串口發(fā)送出去。由于要發(fā)送的信息長度可能超過輸入緩沖區(qū)容量,本研究將待發(fā)送信息打斷,逐64 Byte發(fā)送,剩余長度不足64 Byte時則一次性發(fā)送。
while(strWrite.length()/64! =0){
String tmp=new String(strWrite.substring(0,64));
//串口逐64 Byte發(fā)送
res = mSerialMulti.PL2303Write(index,tmp.getBytes(“GBK”));
strWrite=strWrite.substring(64);
DelayTime(50);
}
//不足64 Byte則一次性發(fā)送
res=mSerialMulti.PL2303Write(index,str-Write.getBytes(“GBK”));
根據(jù)中國氣象局綜合觀測司的要求,新型自動氣象(氣候)站的指令以<回車> <換行>(“\r\n”)結(jié)尾[17,18]。在 PC的串口助手中,只需要敲擊鍵盤的“回車”鍵即可輸入<回車><換行>,但在Android系統(tǒng)的輸入法中,“回車”鍵只能輸入 <換行 >(“\n”),而無 <回車 >(“\r”)。為此,軟件設(shè)計了“指令”CheckBox控件,勾選后自動在待發(fā)送字符串末尾追加字符串“\r\n”,實現(xiàn)正常的指令下發(fā)。
套件支持Android手機與電腦串口通信,能夠?qū)ZZ1-2新型自動氣象站、WP3103區(qū)域自動氣象站、EWOS-1生態(tài)氣象自動觀測系統(tǒng)、PTB330氣壓傳感器、Belfort6000能見度儀等設(shè)備的串口輸出檢查,也可應(yīng)用于其他通用串口設(shè)備。利用轉(zhuǎn)換模塊連接DZZ1-2新型自動氣象站數(shù)據(jù)采集器和手機,在Android手機上運行APP軟件,勾選“指令”,向數(shù)據(jù)采集器發(fā)送“dmgd”即可調(diào)取分鐘觀測數(shù)據(jù),如圖5所示。
圖5 向DZZ1-2型數(shù)據(jù)采集器發(fā)送指令
利用套件可以對光電轉(zhuǎn)換器、串口服務(wù)器、通信電纜等通信傳輸設(shè)備做打環(huán)測試。將套件的RS232串口與光電轉(zhuǎn)換器RS232串口連接,用光纖回路器連接光電轉(zhuǎn)換器的光纖收發(fā)接口,在APP軟件發(fā)送測試信息,如光電轉(zhuǎn)換器工作正常,則軟件串口讀取顯示區(qū)將顯示發(fā)出的測試信息,如圖6所示。
圖6 打環(huán)測試界面
自動氣象站、氣壓傳感器、超聲風(fēng)傳感器、能見度儀、串口服務(wù)器、光電轉(zhuǎn)換器等多種設(shè)備均使用了串口通信,以往只能通過電腦串口來檢查設(shè)備串口狀態(tài)或設(shè)置設(shè)備參數(shù)。本研究利用PL2303HXD芯片開發(fā)了運行在Android手機的串口通信套件,實現(xiàn)Android手機與設(shè)備間的串口通信,為自動氣象觀測設(shè)備串口通信故障現(xiàn)場排查提供了一個方便、可靠、低成本的工具。由于Android手機廣泛普及,本套件的經(jīng)濟成本極低,也更加便攜,適合在自動氣象觀測維保一線推廣應(yīng)用。