在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            代碼的移植性問題

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

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

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

            我覺得最典型的例子就是蜂鳴器,4KHZ驅(qū)動(dòng)的交流蜂鳴器,如果蜂鳴器接在 P50 口,那么驅(qū)動(dòng)的代碼就應(yīng)該是:

            mov a,@0x01

            xor 0x05,a

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

            PORT5 ^= 0x01

            好了,這個(gè)代碼的移植性超級差,如果我的蜂鳴器現(xiàn)在需要修改到 P62口,那么代碼也必須相應(yīng)的修改為:

            mov a,@0x04

            xor 0x06,a

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

            修改版1:

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

            buz_port EQU 0x05

            mov a,@0x01

            xor buz_port,a

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

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

            修改版2:

            buz_port EQU 0x05

            buz_pin EQU 0

            mov a,@1<

            xor buz_port,a

            這個(gè)代碼就真正實(shí)現(xiàn)了所謂的移植性。用C語言來解釋一下

            buz_port ^= 1<

            如果C語言過關(guān)的同學(xué)應(yīng)該對這個(gè)表達(dá)式很熟悉了。1<

            例如

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

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

            道理是這樣,但是使用起來一點(diǎn)也不負(fù)責(zé),可以說是很好用。可以直接和IO的名字對應(yīng)起來,例如前面說的 P62 的話,那么定義就應(yīng)該為:

            buz_port EQU 0x06

            buz_pin EQU 2

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

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

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

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

            答案是:動(dòng)態(tài)綁定IO口輸入輸出,途徑是R0和R4配合的間接尋址。怎么實(shí)現(xiàn)?其實(shí)很簡單,因?yàn)殚g接尋址本身能訪問地址 0x05 和 0x06 ,也就是能直接訪問 PORT5 和 PORT6 ,這樣就很容易聯(lián)想到,例如 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,然后將數(shù)據(jù) 0x0f 送到 R0中,那么實(shí)際的效果就是將 0xf 送到 PORT6 當(dāng)中,用仿真器跑一下就OK了,很簡單的。

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

            例如有用回之前的那個(gè)蜂鳴器的例子

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

            分配兩個(gè)寄存器,分別保存當(dāng)前需要操作的端口信息。

            REG_PORT == 0x10

            REG_PIN == 0x11

            假如當(dāng)前需要對 P50輸出

            Mov a,@0x05

            Mov REG_PORT,a

            Mov a,@1<<0

            Mov REG_PIN,a

            那么蜂鳴器的驅(qū)動(dòng)函數(shù)就應(yīng)該做相應(yīng)的修改,前面說了,原來是直接對PORT口操作,現(xiàn)在變成間接尋址

            Mov a,REG_PORT

            Mov R4,a

            Mov a,REG_PIN

            Xor R0,a

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

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

            Mov a,@0x06

            Mov REG_PORT,a

            Mov a,@1<<2

            Mov REG_PIN,a

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

            看到?jīng)]有?這里就是所謂的動(dòng)態(tài)綁定。如果考慮移植性,也就是說以后可能會(huì)修改端口的話,那集合第一點(diǎn)當(dāng)中所說的,定義一個(gè)宏就OK了,反正這東西需要自己靈活的運(yùn)用。

            結(jié)束語:

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



            關(guān)鍵詞: 代碼移

            評論


            技術(shù)專區(qū)

            關(guān)閉