占用式和非占用式程序結構分析
void refresh7()
{
static unsigned char r=0;
static unsigned char flagrgb=0; //當前需要點(diǎn)亮的顏色,0-R,1-G,2-B
static unsigned char num=0;
num++;
if(num==32)
{
num=0;
flagrgb++;
if(flagrgb==3) //說(shuō)明三種顏色都掃描完了
{
flagrgb=0; //從紅色開(kāi)始掃描
r++; //開(kāi)始掃描下一行
if(r==8) //如果發(fā)現行都掃描結束則從第行開(kāi)始掃描
r=0;
}
}
if(num
{
switch(flagrgb)
{
case 0: //掃描紅色
DPw = ~(0x01
DPr = ~vm7r[r];//送入R燈IO接口顯示
break;
case 1: //掃描綠色
DPw = ~(0x01
DPg = ~vm7g[r];
break;
case 2: //掃描藍色
DPw = ~(0x01
DPb = ~vm7b[r];
break;
}
}
else //說(shuō)明不需要點(diǎn)亮
{
DPw=0xff;
DPr=0xff;
DPg=0xff;
DPb=0xff;
}
}
現在,這個(gè)函數中沒(méi)有任何延時(shí)和循環(huán),執行所消耗的時(shí)間是非常少的,可以很快地響應響應其它任務(wù)。
四、改造的本質(zhì)
上面我們對DYS388的掃描程序進(jìn)行了“三大改造”,分別是:1、各個(gè)行掃描的分離;2、各個(gè)顏色掃描的分離;3、延時(shí)函數的消除。
這些改造的本質(zhì)都是對原程序的分割,把一大坨程序分成多個(gè)步驟分別執行,以減小耗時(shí),提高對外部的響應速度。
但就整個(gè)進(jìn)程的執行來(lái)看,有效代碼的比例是降低的,包括上面“三大改造”的第三點(diǎn) 延時(shí)函數的消除,看上去是消除了延時(shí)函數,提高了執行效率,但從“掃描一次整屏”這個(gè)任務(wù)來(lái)看,其執行的代碼量反而是增加的。(但并不是所有的改造都一定會(huì )使效率降低,有些改造確實(shí)可以達到“消除延時(shí)函數”的目的)
那為什么還要對其進(jìn)行改造呢,見(jiàn)下節分析。
五、非占用式程序結構的優(yōu)勢
1、非占用式程序相比于占用式程序,增加了一定的代碼,雖然會(huì )使整體效率降低,但是提高了各個(gè)任務(wù)之間的切換速度,可以對各個(gè)任務(wù)都能很快地響應。這點(diǎn)類(lèi)似于操作系統,雖然降低了效率,但是各個(gè)任務(wù)間的快速切換可以達到各個(gè)任務(wù)“并行處理”的效果,光是這點(diǎn)的好處就已經(jīng)很大了。
2、非占用式程序結構可以放進(jìn)定時(shí)器
之前寫(xiě)過(guò)一片《單片機用定時(shí)器分配任務(wù)程序結構總結》已經(jīng)發(fā)現用定時(shí)器分配任務(wù)的好處,有些簡(jiǎn)短的代碼可以直接放進(jìn)定時(shí)器里。
在改造之前的掃描程序是不適合放在定時(shí)器中斷處理程序里執行的,因為太長(cháng),可能還沒(méi)執行完就來(lái)了下一個(gè)中斷。就算勉強執行完了,留給主進(jìn)程處理其它事情的時(shí)間也不多了。
而改為非占用式之后,可以在中斷處理程序里直接調用掃描程序,它會(huì )很快地執行完,然后有充足的時(shí)間留給其他任務(wù)。
3、非占用式程序并不是一定會(huì )降低效率。
先拿“三大改造”的第三點(diǎn)說(shuō)明,它雖然形式上消除了延時(shí)函數,但是每次調用此函數時(shí)對num變量的處理,以及有其產(chǎn)生的相關(guān)判斷語(yǔ)句,總的代碼量比原來(lái)的要多。
但是,這真的就僅僅是這樣了嗎?改造之前的函數,執行玩退出之后所有的led全是熄滅的,只有在此函數執行過(guò)程中(延時(shí)階段)才會(huì )點(diǎn)亮(傳統數碼管掃描亦是如此)。
而改造之后的函數,它的功能就是指定一下每個(gè)燈的亮滅,然后立馬退出,在執行其它任務(wù)的過(guò)程中該點(diǎn)亮的燈是在點(diǎn)亮的狀態(tài)。這樣就提高了整體的亮度,在執行其他任務(wù)的過(guò)程中,從某種意義上說(shuō)也是在執行當前任務(wù)。
這可能還不能太清楚地說(shuō)明問(wèn)題,下面我要再舉一例,傳統的按鍵掃描一般是這樣:
if(key==0) //key是某個(gè)引腳
{
delay5(1);
if(key==0) //確認按鍵已按下
{
//do something
}
}
這段代碼也是很浪費時(shí)間的,中間有個(gè)5ms延時(shí)拜拜浪費。
通過(guò)對它改造之后,結合定時(shí)器,可以幾乎完全地把這5ms時(shí)間省出來(lái):
static unsigned char keylast; //保存上次的按鍵值
if(key==0 keylast==1) //檢測到一個(gè)下降沿
{
//do something
}
keylast=key;
結合定時(shí)器進(jìn)行改造,是真的可以把占用式函數的延時(shí)時(shí)間節省出來(lái)的。
六、非占用式程序的一般結構
非占用式程序將占用式程序分割執行,需要用到靜態(tài)變量對當前步驟進(jìn)行記憶,其一般結構如下:

邏輯變量計算就是根據任務(wù)功能構建出一個(gè)合理的邏輯結構。
對邏輯變量的響應就是對構建好的邏輯結構的結果的響應和執行。
七、結論
最近開(kāi)發(fā) DYS388 寫(xiě)了不少程序,以前在寫(xiě)程序的過(guò)程中就隱約發(fā)現了所謂占用式和非占用式程序結構的區別,程序寫(xiě)多了肯定能發(fā)現問(wèn)題,但是如果不停下來(lái)總結,而是一味的開(kāi)發(fā),那是不會(huì )有進(jìn)步的。
組織龐大的程序需要正確的理論指導,學(xué)習很多的知識也需要進(jìn)行總結。知識點(diǎn)太多不可能學(xué)完,只有將他們提升到理論層次,將這種思維方式刻在腦子里才能靈活地運用,并從容地接受新的知識。
評論