西門子S7-300PLC的V存儲區(qū)的探索與發(fā)現(xiàn)

發(fā)布時間:2024-03-13
西門子s7-300plc有v存儲區(qū)嗎?聽到這個問題,絕大多數(shù)人都會笑起來,v存儲區(qū)不就是s7-200的變量存儲區(qū)嗎?s7-300哪里有什么v區(qū)?有沒有搞錯?最近有個網(wǎng)友在網(wǎng)上詢問這個問題:“我的疑問也是這個v區(qū),被一堆人鄙視的說是200的吧。另外我有個疑問沒見有誰用這個區(qū)域編程,麻煩有類似的例子給露露臉啊”,顯出了幾分急切和無奈。
我也曾經(jīng)被這個問題困擾過,下面向大家介紹我尋找答案的過程。
首先在step 7的幫助中搜索“v區(qū)”,在參數(shù)類型any和pointer的幫助中有個存儲區(qū)編碼表,其中就有v區(qū),其代碼為16#87,對v區(qū)的描述為“先前的本地數(shù)據(jù)”。這幾個字像天書一樣,可能很難有人能看懂。
為了確認翻譯的準確性,我將step 7切換到英語,“先前的本地數(shù)據(jù)”的英文為“previous local data”。local data一般翻譯為“局部數(shù)據(jù)”,看來翻譯沒有問題。德國人的英語水平很高,德國大學圖書館的書籍和雜志大多數(shù)都是英語的,不用懷疑德語翻譯為英語時失真。
v區(qū)與參數(shù)類型any和pointer有關,打開step 7的幫助目錄中的附錄,選中其中的“\數(shù)據(jù)類型和參數(shù)類型\參數(shù)類型\參數(shù)類型pointer的格式”,可以看到參數(shù)類型由6個字節(jié)組成,0號和1號字節(jié)是db塊的編號,不是數(shù)據(jù)塊內(nèi)的地址時為0。2~5號字節(jié)的格式與寄存器間接尋址的格式相同。下面是寄存器間接尋址的32位指針格式:
x000 0rrr 0000 0bbb bbbb bbbb bbbb bxxx
其中第0~2位(xxx,最低位為第0位)為被尋址地址中位的編號(0~7),第3~18位(16個b)為被尋址地址的字節(jié)的編號。第24~26位(rrr)為被尋址地址的區(qū)域標識號,指針的最高位x 為0時,為區(qū)域內(nèi)的間接尋址,最高位x 為1時,為區(qū)域間(交叉區(qū)域)間接尋址。
參數(shù)類型any可以用來傳遞一片連續(xù)的地址區(qū),由10個字節(jié)組成。any和pointer用于在塊調(diào)用時傳遞輸入、輸出參數(shù)。為了揭開v區(qū)之謎,編寫了fc1,將地址區(qū)中相鄰的若干個字累加。地址區(qū)的起始地址由參數(shù)類型為pointer的輸入?yún)?shù)start_addr提供。p# db2.dbx0.0也可以改寫為db2.dbx0.0。在ob1中調(diào)用fc1:
call fc 1
start_addr:=p#db2.dbx0.0 //數(shù)據(jù)區(qū)起始地址
number :=5 //需要累加的字數(shù)
result :=db2.dbd10 //保存運算結果的雙整數(shù)
圖1是運行時監(jiān)控fc1的結果,累加器1(standard)中的數(shù)據(jù)為十六進制顯示格式,ar1是地址寄存器1。終于看到了ar1中的v區(qū)地址了!
800)this.width=800>
圖1中第一條指令的p#表示指針,第2個#號表示局部變量。p##start_addr就是調(diào)用fc1時,用輸入?yún)?shù)start_addr傳送給fc1的指針p#db2.dbx0.0(16#0002 8400 0000)存放的地址。p##start_addr(16#8700 00a8)最低字節(jié)16#a8對應的二進制數(shù)為2#10101000,其字節(jié)部分為2#10101,即十進制數(shù)21,最高字節(jié)16#87(2#1000 0111)表示存儲區(qū)為v區(qū)。
第一條指令將p##start_addr送給累加器1,第二條指令將累加器1中的數(shù)據(jù)傳送到ar1,傳送后ar1中的地址為v21.0(即16#8700 00a8)。
那么v區(qū)到底是什么呢?根據(jù)幫助中的解釋“先前的本地數(shù)據(jù)”(previous local data),猜想與局部數(shù)據(jù)堆棧有關。執(zhí)行每個塊時,它都有自己的臨時局部數(shù)據(jù)。在ob1調(diào)用fc1時,ob1的臨時局部數(shù)據(jù)被保存到局部數(shù)據(jù)堆棧,fc1則使用它自己的臨時局部數(shù)據(jù)區(qū),ob1的局部數(shù)據(jù)成為“previous local data”(以前的局部變量)。根據(jù)上述分析,v區(qū)很有可能是調(diào)用fc1的ob1的局部數(shù)據(jù)區(qū)。
怎樣才能證實這個猜想呢?最好能看到ar1中的地址為v21.0時,ob1的局部數(shù)據(jù)。好在step 7的監(jiān)控功能可以查看塊調(diào)用時保存在堆棧中的數(shù)據(jù)。為了能看到某條指令執(zhí)行后ob1的局部數(shù)據(jù),在fc1的第2條指令處設置一個斷點。執(zhí)行完第2條指令后,cpu進入hold模式,此時打開cpu模塊信息對話框的“堆?!边x項卡,選中b堆棧中的ob1,點擊“l(fā)堆?!卑粹o,打開l堆棧對話框,ob1的局部數(shù)據(jù)堆棧如圖2所示。
800)this.width=800> 
由圖1可知,因為指針常數(shù)p#v21.0(16#8700 00a8)被送給ar1,監(jiān)控區(qū)中的ar1列顯示v21.0。此時ob1調(diào)用fc1的pointer格式的實參p#db2.dbx0.0(16#0002 8400 0000),存放在從ob1的局部變量lb21開始的6個字節(jié)中(見圖2)。因此ar1中的p#v21.0表示指針常數(shù)p#db2.dbx0.0的值存放在ob1的局部變量區(qū)中的地址,換句話說,v區(qū)就是調(diào)用fc1時ob1的局部數(shù)據(jù)區(qū)。
難怪“沒見有誰用這個區(qū)域編程”,v區(qū)用于監(jiān)控,在編程時沒有使用它。
最后我們來總結一下塊調(diào)用時的參數(shù)傳遞過程。如果輸入?yún)?shù)為簡單數(shù)據(jù)類型,例如字節(jié)、字、整數(shù)和雙整數(shù),可以通過32位(4個字節(jié))的累加器1直接傳遞參數(shù)。而any和pointer分別為10個和6個字節(jié),不能用累加器1直接傳遞。因此將這些參數(shù)的實參(例如16#0002 8400 0000)暫時保存在ob1從v21.0開始的局部變量中。在被調(diào)用的fc1中, p##start_addr提供了保存參數(shù)start_addr的實參的地址v21.0,在fc1中用寄存器間接尋址指令“l(fā) w [ar1,p#0.0]”來讀取pointer實參的第一個字(數(shù)據(jù)塊編號),用指令“l(fā) d [ar1,p#2.0]”來讀取pointer實參的2~5號字節(jié)(數(shù)據(jù)塊內(nèi)的變量地址p# dbx0.0)。間接尋址的操作數(shù)地址等于方括號中ar1的地址值加上逗號后面的地址偏移量。
說到這里,我們可以看到傳遞pointer參數(shù)類型的思路是非常清晰的,“previous local data”用詞是準確的,只不過所用的筆墨太少,背后的復雜過程需要我們猜想和驗證。
解決了這個問題后,有一些感觸:
1.由于語言和思維方式的差異,老外寫的用戶手冊有的地方很難理解,這并不奇怪。奇怪的是網(wǎng)上有一些高手的“用戶手冊萬能論”。用戶手冊肯定不是萬能的,不可能回答所有的問題,有的問題還需要我們設法去探索和發(fā)現(xiàn),包括用程序來驗證我們的假設。
2.這個問題的解決使我驚嘆step 7強大的功能,如果沒有斷點和監(jiān)控堆棧的功能,是不可能搞清楚這個問題的。還有別的plc有這些功能嗎?
上一個:緊身胸衣
下一個:八心八箭鉆石的寓意是什么?

9月國內(nèi)自駕游路線推薦
聯(lián)想筆記本電源鍵亮屏幕不亮(聯(lián)想筆記本電源鍵亮但黑屏鼠標光標可以動)
如何區(qū)分霍山黃芽的等級
五月份花事
傷殘賠償金什么時候能拿到
域名有多少尾綴 哪些域名尾綴是常見的
機動車尾氣排放污染
一臺云服務器主機多少錢
庭院植物搭配的奇思妙想
國服csgo變成英文(csgo界面改成英文)
十八禁 网站在线观看免费视频_2020av天堂网_一 级 黄 色 片免费网站_绝顶高潮合集Videos