<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > 代碼的移植性問題

          代碼的移植性問題

          作者: 時間:2016-11-17 來源:網絡 收藏
          代碼移植性是對編程人員的一大考驗,這個問題應該時刻考慮。甚至從你策劃項目的一瞬間開始,就應該考慮到代碼可能會被多次修改,或者功能模塊的刪減等。項目的外圍硬件很多時候都會根據需求改變,到底怎么樣的編寫技巧能使修改量降至最小,而又能很好的完成項目呢?這就是今天研究的話題。這里先說一些小的例子,以及實際怎樣運用。

          (1)用宏定義代替直接IO操作

          本文引用地址:http://www.ex-cimer.com/article/201611/315480.htm

          我覺得最典型的例子就是蜂鳴器,4KHZ驅動的交流蜂鳴器,如果蜂鳴器接在 P50 口,那么驅動的代碼就應該是:

          mov a,@0x01

          xor 0x05,a

          代碼很簡單,0x01 和 P5口異或出來的結果,就是 P50 口取反,不斷的取反那么得到的是 P50 口輸出方波,用C語言來描述就是:

          PORT5 ^= 0x01

          好了,這個代碼的移植性超級差,如果我的蜂鳴器現在需要修改到 P62口,那么代碼也必須相應的修改為:

          mov a,@0x04

          xor 0x06,a

          當然了,我們這里只需要一處,還不見得麻煩,如果你的代碼中有50處,乃至100處需要修改,我想你肯定要抓狂。所以這種不可移植的代碼必須扔掉。

          修改版1:

          通過定義蜂鳴器的IO口來處理

          buz_port EQU 0x05

          mov a,@0x01

          xor buz_port,a

          這里用 buz_port 這個名字代替了蜂鳴器的輸出端口,那么現在移植性有了提高,如果修改了端口的話,我們只需要重新定義 buz_port 這個宏,就完成了對代碼的所有的修改。

          按照上面的描述,能解決了端口的問題,但是我們發(fā)現,問題還沒有完全解決,mov a,@0x01 我們還得手工計算蜂鳴器在哪個引腳上面,而且還得在一個一個的修改,所以還需要改進。

          修改版2:

          buz_port EQU 0x05

          buz_pin EQU 0

          mov a,@1<

          xor buz_port,a

          這個代碼就真正實現了所謂的移植性。用C語言來解釋一下

          buz_port ^= 1<

          如果C語言過關的同學應該對這個表達式很熟悉了。1<

          例如

          1<<0 得到的結果是 1 (00000001b)

          1<<3 得到的結果是 8 (00001000b)

          道理是這樣,但是使用起來一點也不負責,可以說是很好用??梢灾苯雍虸O的名字對應起來,例如前面說的 P62 的話,那么定義就應該為:

          buz_port EQU 0x06

          buz_pin EQU 2

          只需要修改一下定義,程序當中所有使用了這個IO口的部分都不需要修改,這樣移植性就非常好了。這個技巧雖然簡單,但是是必須學會的。

          (2)動態(tài)綁定IO口

          思考一種情況,我們使用 3個IO口分別發(fā)不同占空比的PWM,驅動3個不同顏色的LED發(fā)光,形成彩燈效果。要求就是3個IO口獨立控制,那么很自然的想法就是,3段程序,每一段程序都生成PWM,也就是說將1路的情況擴展到3路,分別控制。但是寄存器的消耗和ROM的消耗也相對應的變成了3倍,這是很好理解的。但是3段程序驚人的類似,很可能只是IO口輸出部分修改了一下,我們思考,時候可以合在一起寫呢?也就是說,用1個PWM程序生成PWM,分別輸出到3個不同的IO口,我建議,在看下去之前先自己思考一下,敲一下程序,就能很深刻的理解到這個問題的難點。

          類似的情況也不少見,例如RC測溫,如果測1路的話很好辦,但是如果測很多路呢?你不會真的需要將每一路都一份對應的程序吧?那絕對不可能,處理的辦法類似,也就是說,用一個程序處理多個IO的輸入數據,切換。這有點類似數字電路里面的數據選擇器。

          答案是:動態(tài)綁定IO口輸入輸出,途徑是R0和R4配合的間接尋址。怎么實現?其實很簡單,因為間接尋址本身能訪問地址 0x05 和 0x06 ,也就是能直接訪問 PORT5 和 PORT6 ,這樣就很容易聯想到,例如 PORT6 口輸出狀態(tài),然后 PORT6 的輸出狀態(tài)修改為 0X0F (P60~P63高電平,P64~P67低電平)一般的做法是:

          mov a,@0x0f

          mov PORT6,a

          如果通過間接尋址的辦法,那么就是

          mov a,@0x06

          mov R4,a

          mov a,@0x0f

          mov R0,a

          首先將要訪問的寄存器地址 0x06放到地址寄存器 R4,然后將數據 0x0f 送到 R0中,那么實際的效果就是將 0xf 送到 PORT6 當中,用仿真器跑一下就OK了,很簡單的。

          懂了這個原理之后,那么所謂的“動態(tài)綁定”就很容易理解了,將原來用 PORT5 PORT6訪問IO口的指令,變成用 R0 R4 間接尋址來訪問,這樣程序就可以變得很靈活。

          例如有用回之前的那個蜂鳴器的例子

          系統(tǒng)有兩個蜂鳴器,P50和P62,那么下面看看怎么通過動態(tài)綁定將方波分別輸出到這兩個蜂鳴器當中。

          分配兩個寄存器,分別保存當前需要操作的端口信息。

          REG_PORT == 0x10

          REG_PIN == 0x11

          假如當前需要對 P50輸出

          Mov a,@0x05

          Mov REG_PORT,a

          Mov a,@1<<0

          Mov REG_PIN,a

          那么蜂鳴器的驅動函數就應該做相應的修改,前面說了,原來是直接對PORT口操作,現在變成間接尋址

          Mov a,REG_PORT

          Mov R4,a

          Mov a,REG_PIN

          Xor R0,a

          可以理解么?其實很簡單,首先確定當前需要操作的端口,前面設定了REG_PORT的值為0x05,也就是說操作 PORT5,然后將需要操作的腳 1<<0 也就是 0x01 和 R0(現在指向PORT5)異或,得出來的效果就是 P50 改變電平,多次調用就變成輸出方波了。

          如果現在需要對 P62輸出,那么事情就變得很簡單,只需要:

          Mov a,@0x06

          Mov REG_PORT,a

          Mov a,@1<<2

          Mov REG_PIN,a

          那么中間的方波生成部分就通用了,我們需要操作哪個端口,直接送值就OK。

          看到沒有?這里就是所謂的動態(tài)綁定。如果考慮移植性,也就是說以后可能會修改端口的話,那集合第一點當中所說的,定義一個宏就OK了,反正這東西需要自己靈活的運用。

          結束語:

          很簡單的兩個東西,我用了大篇幅來描述就是為了說明問題而已,如果理解的話真的很簡單,甚至是不足掛齒。但是,怎么說呢,程序就是這類小技巧一點一點的積累起來的。希望今天說的2個小技巧能對你有益。



          關鍵詞: 代碼移

          評論


          技術專區(qū)

          關閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();