摘 要:隨著自動(dòng)測(cè)試的發(fā)展,對(duì)儀器的可編程性提出了挑戰(zhàn),在這個(gè)前提下,SCPI(Standard Commands for Programmable Instruments)協(xié)議的出現(xiàn),帶動(dòng)了標(biāo)準(zhǔn)編程語(yǔ)言的發(fā)展,最后被工業(yè)界所接受。本文就是以SCPI為基準(zhǔn)完成的下位機(jī)的編程。
關(guān)鍵詞:自動(dòng) SCPI 標(biāo)準(zhǔn)編程語(yǔ)言
[b][align=center]The Development of the Bottom Machine in the Direct Current
Electric Resistance Instrument
Teng Da-zhu ,Cheng Ming[/align][/b]
Abstract: Along with the development of the automatic test, put forward the challenge to the programmable of the instrument, under this premise, the appear of the negotiate SCPI(Standard Commands for Programmable Instruments), arousing the development of the standard programable language, and finally were accept by the industry field. This thesis is design for the bottom machine base on the SCPI.
Keywords: automation SCPI programmable language
1、引言
在以往的儀器控制中,復(fù)雜的指令結(jié)構(gòu),繁瑣的編寫(xiě)語(yǔ)言使儀表的可編程性很差,久而久之,人們渴望得到一個(gè)統(tǒng)一的編程標(biāo)準(zhǔn),美國(guó)HP公司為了迎接這個(gè)挑戰(zhàn),首先在公司的內(nèi)部實(shí)現(xiàn)了統(tǒng)一的標(biāo)準(zhǔn)化編程語(yǔ)言TMSL(Test and Measuremens System Language),經(jīng)過(guò)一段時(shí)間的試驗(yàn)和改進(jìn),它被工業(yè)界所接受,定義為儀表界的標(biāo)準(zhǔn),并將它重新命名為SCPI(Standard Commands for Programmable Instruments)。
SCPI應(yīng)用的很普遍,但是在中國(guó),可程控儀器和自動(dòng)測(cè)試系統(tǒng)正處于發(fā)展階段,所以個(gè)人認(rèn)為,我們應(yīng)盡量跳過(guò)程控命令非標(biāo)準(zhǔn)化階段。大力推廣SCPI,以跟上程控命令標(biāo)準(zhǔn)化的世界潮流。
在本文中,主要通過(guò)構(gòu)建一個(gè)子系統(tǒng)來(lái)說(shuō)明SCPI是如何實(shí)現(xiàn)的,上位機(jī)通過(guò)RS232串口發(fā)送指令,下位機(jī)接受后進(jìn)行循環(huán)解析,得出命令所希望實(shí)現(xiàn)的功能,執(zhí)行相應(yīng)的函數(shù)后返回?cái)?shù)據(jù)。下位機(jī)通過(guò)返回相應(yīng)的數(shù)據(jù)來(lái)驗(yàn)證上位機(jī)的指令是否得到了解析,如果是正確的,則返回相應(yīng)的數(shù)據(jù),如果是錯(cuò)誤的,則返回錯(cuò)誤信息。
2、設(shè)計(jì)概述
2.1 SCPI命令樹(shù)結(jié)構(gòu)
對(duì)SCPI命令采用樹(shù)狀結(jié)構(gòu)的,可向下三級(jí),在這里最高級(jí)稱為子系統(tǒng)命令。只有選擇了子系統(tǒng)命令,該其下級(jí)命令才有效,SCPI使用冒號(hào)(:)來(lái)分隔高級(jí)命令和低級(jí)命令。
2.2串口通信
通常PC機(jī)和單片機(jī)之間的通信都是通過(guò)串行總線RS-232實(shí)現(xiàn)的。因此采用一種以RS232為核心的通信接口電路。該接口電路適用于由一臺(tái)PC機(jī)與多個(gè)單片機(jī)串行通信的設(shè)計(jì),其原理框圖見(jiàn)圖1:
該框圖中,起著重要作用的是RS-232C通信接口電路。它是上位機(jī)和下位機(jī)之間信息傳遞的樞紐,一切數(shù)據(jù)的傳輸必需由它完成,上位機(jī)通過(guò)直接利用它的RS-232串行口來(lái)發(fā)送指令和接受返回值。
[align=center]
圖1單片機(jī)與PC機(jī)通信原理框圖[/align]
3、SCPI在直流低阻表中的實(shí)現(xiàn)
3.1直流低阻表的功能
直流低電阻主要用于計(jì)算機(jī)等高端機(jī)器,由于是直流電阻,所以電阻發(fā)熱是不可避免的,而采用低阻值的電阻則可以減少發(fā)熱量,不但可以節(jié)省電能,而且還大大提高儀器的使用壽命。直流低阻表的功能就是在流水線上檢測(cè)電阻的質(zhì)量,確保電阻阻值在允許的誤差范圍內(nèi)。這樣不但可以全天實(shí)時(shí)監(jiān)控,更可以記錄下阻值變化曲線圖,給工程師檢測(cè)儀器是否正常工作帶來(lái)方便。
3.2直流低阻表的模塊
可程控儀器的標(biāo)準(zhǔn)指令集同樣可以在直流低阻表里實(shí)現(xiàn),一般的直流低阻表都包含: FUNCtion子系統(tǒng)和COMParator子系統(tǒng)。
3.3命令解析
3.3.1 庫(kù)函數(shù)介紹
在構(gòu)建模塊化的時(shí)候,調(diào)用庫(kù)函數(shù)完成相應(yīng)的功能是很方便的,在這個(gè)SCPI解析協(xié)議中提供了以下的庫(kù)函數(shù):
CheckFloat.c 它的作用是檢查是否為浮點(diǎn)數(shù);
CheckInteger.c 它的作用是檢查是否為整數(shù);
CommandEntry.c 這個(gè)庫(kù)函數(shù)很重要,它是程序的入口,計(jì)算機(jī)通過(guò)RS232串口發(fā)送數(shù)據(jù)到單片機(jī),就是通過(guò)這個(gè)入口程序來(lái)接受指令的;
NewToken.c 它的作用是對(duì)指針指向的字符或符號(hào)或數(shù)字轉(zhuǎn)換成標(biāo)識(shí)符,如將“set”轉(zhuǎn)換“TOKEN_FLAG_COMMAND”,將“50”轉(zhuǎn)換成“TOKEN_FLAG_NUMMBER”;
RS232_Close.c 它的作用是關(guān)閉RS232串口;
RS232ErrChr.c 它的作用是顯示字符錯(cuò)誤;
RS232ErrStr.c 它的作用是顯示字符串錯(cuò)誤;
RS232_Open.c 它的作用是打開(kāi)RS232串口;
RS232Print.c 它的作用是輸出;
RS232PrintChar.c 它的作用是輸出單個(gè)字符;
RS232PrintError.c 它的作用是輸出錯(cuò)誤;
RS232PrintLine.c 它的作用是輸出字符串;
RS232Send.c 它是RS232發(fā)送指令;
SeekParameter.c 它的作用是尋找參數(shù);
SubsystemError.c 這里面包括了ERR子系統(tǒng)的函數(shù);
Translate.c 這個(gè)庫(kù)函數(shù)是下面要講到的循環(huán)調(diào)用解析函數(shù)。
3.3.2命令解析函數(shù)
解析函數(shù)是整個(gè)SCPI協(xié)議的靈魂,SCPI協(xié)議的解析正是通過(guò)這樣的一個(gè)循環(huán)調(diào)用函數(shù)來(lái)實(shí)現(xiàn)對(duì)命令的解析,然后再對(duì)解析出來(lái)的命令再加以解析,直到最后一層,最后調(diào)用其他的函數(shù)。
在循環(huán)解析中,它起了一個(gè)分割命令的作用,并對(duì)分割出來(lái)的命令再加以解析和分割直到最后一層,在這個(gè)函數(shù)中首先用到了NewToken()這個(gè)函數(shù),這個(gè)函數(shù)的作用是對(duì)當(dāng)前指針m_pInBuffer所指的對(duì)象進(jìn)行判斷,并返回相應(yīng)的類型,若指向“:”,則返回“:”;如若指向“set”,則返回“TOKEN_FLAG_COMMAND”;若指向“;”,則返回“ ;”,若指向“50”,則返回“TOKEN_FLAG_NUMMBER”,解析具體過(guò)程如下:
1.若是“TOKEN_FLAG_COMMAND”,則和自己所定義的命令進(jìn)行比較,若不相同,則返回錯(cuò)誤信息“BAD COMMAND”,若比較結(jié)果相同的話,賦bFound為true,并跳出while()循環(huán),執(zhí)行if操作,這里將出現(xiàn)兩種情況:
?。?) 如果沒(méi)有下級(jí)執(zhí)行函數(shù),則比較m_pInBuffer是否為“:”,若是,則執(zhí)行“++”操作,取出下一個(gè)符號(hào),這里執(zhí)行if操作,如果沒(méi)有下級(jí)命令,則返回錯(cuò)誤信息“BAD COMMAND”,如果有下級(jí)命令,就把這個(gè)命令賦給pToken,并置bNeedCommand為true;如果m_pInBuffer不是“:”,則返回錯(cuò)誤信息“INVALID SEPARATOR”,返回主函數(shù)。執(zhí)行完這段程序后跳出循環(huán),等待下次循環(huán)的到來(lái)。
?。?) 如果有下級(jí)執(zhí)行函數(shù),則將下級(jí)命令賦給pToken,并執(zhí)行下級(jí)執(zhí)行函數(shù),函數(shù)執(zhí)行完后會(huì)返回一個(gè)標(biāo)識(shí)符,在這里又一次對(duì)標(biāo)識(shí)符進(jìn)行一次判斷:
?、?如果是“:”,這時(shí)再看命令是否有下級(jí),如果沒(méi)有,則返回錯(cuò)誤信息“INVALID AEPARATOR”,如果有則將true賦給bNeedCommand后跳出。
?、?如果是“;”,則看m_bCommon是否為true,若為true的話,則將其置false,并將bNeedCommand置為false后跳出。
?、?如果是“TOKEN_FLAG_RESTART”,則將m_bCommon置為false,返回到根命令,返回true。
?、?如果是“TOKEN_FLAG_COMMON”,則看m_bCommon是否為false如果是則將其置為true,將pToken的值賦給m_pTokenSave,返回true。
?、?如果是“END”,則返回fslse。
?、?如果以上什么都不是,則返回錯(cuò)誤信息,并返回false。
2.如果是“*”,則其代表的是公共命令,將m_bCommon置為true。
3.如果是“:”,則跳出。
4.如果是“ ”,此時(shí)看bNeedCommand是否為真,如果是,則返回錯(cuò)誤信息“SYNTAX ERROR”,返回主函數(shù)。
5.如果是“TOEN_FLAG_NUMBER”,返回錯(cuò)誤信息“BAD COMMAND”。
6.如果是“TOKEN_FLAG_END”,返回主循環(huán)。
7.如果都不是,則返回錯(cuò)誤信息“INVALID SEPARATOR”,并返回主循環(huán)。
為了便于理解,下面我來(lái)舉個(gè)例子:
在計(jì)算機(jī)里輸入“set:red 50;:set:yel?”這個(gè)指令,這個(gè)指令的作用是設(shè)置紅燈的時(shí)間為“50”,并查詢當(dāng)前黃燈的時(shí)間。首先主程序的指針指向“set”,并通過(guò)“NewToken()”這個(gè)函數(shù)來(lái)返回一個(gè)標(biāo)識(shí)符,把它賦給“cToken”,此時(shí)對(duì)“cToken”進(jìn)行判斷,因?yàn)椤皊et”是命令標(biāo)識(shí)符,所以“NewToken()”返回的是“TOKEN_FLAG_COMMAND”,執(zhí)行里面的操作,比較自定義的命令,結(jié)果在命令縮寫(xiě)形式里找到相同的命令,跳出“if”操作,程序指針“++”,由于我們定義“set”有下級(jí)指令“M_tSetup”,所以執(zhí)行“else”操作,判斷主程序的指針為“:”,后面有下級(jí)命令“red”,把它賦給“pToken”后跳出,此時(shí)的指針指向的是“red”,通過(guò)判斷標(biāo)識(shí)符的類型為“TOKEN_FLAG_COMMAND”,繼續(xù)執(zhí)行里面的操作,比較自定義命令,結(jié)果找到相同的命令,程序指針“++”,我們定義的“red”指令沒(méi)有下級(jí)命令而有下級(jí)執(zhí)行函數(shù),所以這里執(zhí)行“if”操作,這里調(diào)用“SetRed()”這個(gè)函數(shù),向里面寫(xiě)入時(shí)間“50”,此時(shí)程序指針執(zhí)行“++”指向“;:”,它是一個(gè)“TOKEN_FLAG_RESTART”類型的數(shù)據(jù),執(zhí)行命令樹(shù)的重起操作,等待主函數(shù)的下次調(diào)用“CommandEntry()”,調(diào)用后繼續(xù)執(zhí)行命令,同樣指針指向“set”,由于返回的類型是“TOKEN_FLAG_COMMAND”,所以執(zhí)行里面的操作,比較自定義的命令,結(jié)果在命令縮寫(xiě)形式里找到相同的命令,跳出“if”操作,程序指針“++”,由于我們定義“set”有下級(jí)指令“M_tSetup”,所以執(zhí)行“else”操作,判斷主程序的指針為“:”,后面有下級(jí)命令“yel?”,把它賦給“pToken”后跳出,此時(shí)的指針指向的是“yel?”,通過(guò)判斷標(biāo)識(shí)符的類型為“TOKEN_FLAG_COMMAND”,繼續(xù)執(zhí)行里面的操作,比較自定義命令,結(jié)果找到相同的命令,程序指針“++”,我們定義的“yel?”指令沒(méi)有下級(jí)命令而有下級(jí)執(zhí)行函數(shù),所以這里執(zhí)行“if”操作,這里調(diào)用“SetYellowQuery()”這個(gè)函數(shù),執(zhí)行查詢操作。指令到此結(jié)束。
3.4延時(shí)定時(shí)器的使用
設(shè)計(jì)中,我遇到了這樣的一個(gè)問(wèn)題:一開(kāi)始我用一片單片機(jī)做實(shí)驗(yàn),成功后,換仿真器做實(shí)驗(yàn),結(jié)果數(shù)碼管的速度變慢了,原來(lái)的一秒變長(zhǎng)了,經(jīng)過(guò)思考,我認(rèn)為是單片機(jī)的時(shí)鐘頻率和仿真器不同造成的,比較一看,單片機(jī)的時(shí)鐘頻率是20M,而我的仿真器的頻率是12M,發(fā)現(xiàn)了問(wèn)題的所在,我就開(kāi)始改寫(xiě)時(shí)種定義函數(shù)。
首先找到定義延時(shí)定時(shí)器的文件define.h,在里面找到:
#define RELOAD_H_10MS 0x7d
#define RELOAD_L_10MS 0xcb
這里的時(shí)間定義是以20M為準(zhǔn)的,時(shí)間計(jì)算的公式如下:
x=65536-T/t,再將x轉(zhuǎn)化成十六進(jìn)制,分別賦給RELOAD_H_10MS和RELOAD_L_10MS,其中T是延時(shí)時(shí)間,t是一周期的時(shí)間。像:
12MHz@12CLK: t=1us/circle
12MHz@6CLK: t=500ns/circle
40MHz@12CLK: t=300ns/circle
像:x = 65536 –T/t 1ms = 65536–1000=64536 轉(zhuǎn)化為十六進(jìn)制為0xFC18
50ms = 65536–50000=15536轉(zhuǎn)化為十六進(jìn)制為0x3CB0
在本設(shè)計(jì)中,用的是12M@12CLK的芯片,延時(shí)定時(shí)器用的是10ms的,所以修改定義RELOAD_H_10MS和RELOAD_L_10MS的值就可以了,x=65536-10ms/1us=55536,修改后為: #define RELOAD_H_10MS 0Xd8
#define RELOAD_L_10MS 0Xf0
修改后運(yùn)行成功,時(shí)間也正確了。
3.5測(cè)試結(jié)果
在設(shè)計(jì)里,你可以通過(guò)兩種方法來(lái)設(shè)置紅綠等亮的時(shí)間,一種是通過(guò)按鍵,直接在模板上進(jìn)行操作,是通過(guò)“KeyEntry()”來(lái)完成的;一種是通過(guò)計(jì)算機(jī)串口和模板進(jìn)行通信,在計(jì)算機(jī)里輸入命令來(lái)設(shè)置紅綠燈的時(shí)間,是通過(guò)“CommandEntry()”來(lái)完成的,這兩種方法在模板上都得到了實(shí)現(xiàn),通過(guò)按鍵來(lái)來(lái)設(shè)置的功能要少一點(diǎn),只能對(duì)時(shí)間進(jìn)行設(shè)置和實(shí)現(xiàn)暫停功能,通過(guò)串口通信來(lái)設(shè)置的功能包括了查詢,設(shè)置時(shí)間,重新啟動(dòng)。在電腦里通過(guò)上位機(jī)所編的界面,來(lái)與模板通信,輸入“set:red 50”,返回“50”,同時(shí)紅燈的設(shè)置時(shí)間變?yōu)椤?0”,輸入“set:gree?”,返回“30”說(shuō)明綠燈的設(shè)置時(shí)間為“30”,輸入“rst”,返回“waiting for 3s……”,3s后重新啟動(dòng),通過(guò)測(cè)試,說(shuō)明我所用的SCPI的思想在里面得到了實(shí)現(xiàn)。
4、結(jié)束語(yǔ)
控制中出現(xiàn)的功能不足,可以通過(guò)增加指令來(lái)滿足,這是SCPI的優(yōu)點(diǎn)。標(biāo)準(zhǔn)的指令格式實(shí)現(xiàn)了助記符的一致性、參數(shù)格式的統(tǒng)一性以及執(zhí)行方式和功能擴(kuò)展戰(zhàn)略的一致性,減少了測(cè)試軟件開(kāi)發(fā)時(shí)間,使儀器的互換更容易。用SCPI編寫(xiě)的程序不僅更可讀,而且更加直觀人們可以花費(fèi)較少的時(shí)間來(lái)學(xué)習(xí)所使用的儀器,從而可花費(fèi)較多的時(shí)間來(lái)解決實(shí)際應(yīng)用問(wèn)題。而且SCPI還是可擴(kuò)展的,這就使它能隨著儀器能力的增加而擴(kuò)大,這樣在將來(lái)人們可以購(gòu)買一臺(tái)比目前所用儀器功能更多的多用表,其基本功能完全可像目前使用的舊儀器一樣程控。
因而,在本次設(shè)計(jì)中,我們就是以SCPI協(xié)議為指導(dǎo)思想,采用SCPI的指令助記符,分層結(jié)構(gòu)及多重命令結(jié)構(gòu),來(lái)實(shí)現(xiàn)控制儀器模板的目的。在計(jì)算機(jī)通過(guò)RS232串口發(fā)送控制指令到模板時(shí),模板接受了指令,并且做出了相應(yīng)的回應(yīng),返回的數(shù)據(jù)與實(shí)際的數(shù)據(jù)相符,成功地把SCPI的思想應(yīng)用于下位機(jī)的編程中,收到了很好的效果。
本文的創(chuàng)新點(diǎn): SCPI協(xié)議已經(jīng)編寫(xiě)成功,計(jì)算機(jī)發(fā)送的指令已經(jīng)被單片機(jī)接受,并解析正確,執(zhí)行了相應(yīng)的函數(shù)。由此可見(jiàn),在直流低阻表中,SCPI也能得到實(shí)現(xiàn)。
參考文獻(xiàn)
[1] 李毓輝,郭群山,周雄偉.一種自動(dòng)測(cè)試系統(tǒng)軟件平臺(tái)的設(shè)計(jì)[J].微計(jì)算機(jī)信息 2005年第五期.
[2] 歐陽(yáng)光,何光明.Keil_c程序設(shè)計(jì)教程[M].北京:人民大學(xué)出版社,2004.23-39.
[3] 王小龍,雷河靜.可編程儀器的前景[J].微型儀器與應(yīng)用,2001,(6):16-18.
[4] H.A.Wheeler.SCPI:The Next Step in the Evolution of ATE Systems.Electronics Test[M].New York:Industry Publisher,August 1990:12-15.
[5] J.W.Duncan,and V.P.Minerva.SCPI Instruments Will Ease ATE Development[J]. Instrument,October l991:4-6.