新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > 由數(shù)碼管動態(tài)顯示淺談單片機程序

由數(shù)碼管動態(tài)顯示淺談單片機程序

作者: 時間:2016-11-30 來源:網(wǎng)絡 收藏
數(shù)碼管動態(tài)顯示原理:動態(tài)顯示的特點是將所有位數(shù)碼管的段選線并聯(lián)在一起,由位選線控制是哪一位數(shù)碼管有效。這樣一來,就沒有必要每一位數(shù)碼管接一組IO口,從而大大地節(jié)約了IO口。選亮數(shù)碼管采用動態(tài)掃描顯示。所謂動態(tài)掃描顯示即輪流向各位數(shù)碼管送出字形碼和相應的位選,利用發(fā)光管的余輝和人眼視覺暫留作用,使人的感覺好像各位數(shù)碼管同時都在顯示。 即實際上,每個數(shù)碼管是一個個的依次點亮。利用人眼視覺停留,快速掃描,一般每隔10ms以的下時間刷新一次數(shù)碼管顯示即可看到穩(wěn)定的顯示效果。本人親自試驗,最好刷新時間設定為5ms一下,高于5ms顯示會略微有些晃眼。

傳統(tǒng)的數(shù)碼管顯示程序為:

本文引用地址:http://butianyuan.cn/article/201611/323870.htm

#define DUAN P1

#define WEI P0

void delayms(uchar x)

{

uchar y=120;

while(x--)

while(y--);

}

WEI=0; //消影 共陽,共陰為 WEI=0xff

DUAN=code[value_duan1]; //送段選數(shù)據(jù)

WEI=value_wei1; //送位選數(shù)據(jù),確定第幾個數(shù)碼管點亮

Delayms(5); //延時5ms使其顯示穩(wěn)定

WEI=0; //消影 共陽,共陰為 WEI=0xff

DUAN=code[value_duan2]; //送段選數(shù)據(jù)

WEI= value_wei2; //送位選數(shù)據(jù),確定第幾個數(shù)碼管點亮

Delayms(5); //延時5ms使其顯示穩(wěn)定

當延時后依次再送下一個數(shù)據(jù),再延時······

這里我想再次說一下關于延時的問題。一般教科書或者說目前絕大多數(shù)能看到的數(shù)碼管處理程序資料大多都是按照上面的方式處理的。我想問一下,這里延時5ms的意義何在?可否不延時?答案是可以,但顯示結(jié)果就是最后一個被點亮的數(shù)碼管會比較亮,其余的都比較暗。至于原因很簡單,點亮最后一個數(shù)碼管后,單片機CPU還要跑其他程序,然后再次跑到數(shù)碼管顯示處理函數(shù)時再依次點亮第一第二個數(shù)碼管。顯然這樣最后一個被點亮的數(shù)碼管點亮的時間遠遠比其他的數(shù)碼管時間要長,自然這一個特別亮,其余的很暗淡。然而加上5ms延時的話呢?由于單片機速度還算比較快(一般一條指令1us),5ms相當于5000條指令。5000條指令什么概念呢?怎么說呢,若程序里不用“delay”這樣的空指令的話,一般一個大型項目就差不多了。一般而言,比如AD測溫、adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=17&is_app=0&jk=85d214d39ac24f75&k=%B5%E7%D7%D3%CA%B1%D6%D3&k0=%B5%E7%D7%D3%CA%B1%D6%D3&kdi0=0&luki=8&n=10&p=baidu&q=98059059_cpr&rb=0&rs=1&seller_id=1&sid=754fc29ad314d285&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1831118&u=http%3A%2F%2Fwww%2E51hei%2Ecom%2Fmcu%2F2120%2Ehtml&urlid=0" id="16_nwl" mpid="16" target="_blank">電子時鐘等這樣小項目實際有用的指令絕對不會達到好幾千的樣子。所以說5ms對于單片機來說是個相當長的時間。

再回到延時5ms后顯示較為穩(wěn)定的問題上。因為點亮最后一個數(shù)碼管延時5ms后單片機在跑其他的指令時相對要不了多久(前提是其余地方?jīng)]有“delay”空指令),所以最后一個數(shù)碼管比其他數(shù)碼管多亮的時間就不太明顯了,這樣自然顯示也會比較均勻一些。但是事實上,最后一個被點亮的數(shù)碼管還是稍微比別的數(shù)碼管亮一些。注意上面所說的是單片機跑其他指令用的時間不長的情況。如果,程序比較大,模塊很多,單片機要處理的事情很多呢?比方說一個float型數(shù)據(jù)的除法(不知道讀者有沒有在單片機上試過)所耗費的指令數(shù)可能你都想象不到(尤其是對于內(nèi)部不含硬件除法器單片機,其除法指令轉(zhuǎn)換成其他的運算)。我當時做AD測電阻時用的sonix芯片(沒有除法器),開始程序里面一個float型除法,整個程序當時有1.5k的樣子,數(shù)碼管顯示,老是一個亮,其余的暗淡,而且很不穩(wěn)定。后來查找原因,就是因為那條float型除法的問題,竟然占了大幾ms的時間。當刪除那條指令后,整個程序只有700多字節(jié),也就是說就這么一條指令就直接讓程序大小翻倍了!查看編譯器翻譯成的匯編指令占了相當大一部分,而且還有很多CALL指令。所以說,8位單片機 確實不適合做除法以及float運算。

扯遠了,回到數(shù)碼管問題。綜上面所述,delayms(5)的方式是不可靠的。而且最為關鍵的時delay指令是毫無意義的,就是讓單片機啥也不做,在那里死等。試想一下,單片機還要處理其他事情,光在這里死等豈不是太浪費了嗎?就好比人一樣我可以在吃飯的同時聽音樂,而不是先吃飯,飯吃完了再專門聽音樂。單片機也是一樣,要的是效率,而不是在那里死等。

那么這種方式不好,該怎么辦呢?要不要延時?延時肯定是需要的,不然顯示不均勻,但不是這種方式。正確的方式是定時器定時5ms,5ms到后刷新一次數(shù)碼管,這樣一來單片機不會在這里死等,二來數(shù)碼管顯示時間絕對均勻。對于定時器,一般的單片機至少有一個,而且它作為單片機的獨立模塊,根本不影響cpu工作。以3個數(shù)碼管為例,其程序代碼如下

#define DUAN P1 //宏定義段選

#define WEI P0 //宏定義位選

void timer(); //定時器處理函數(shù),用定時器定時5ms

{

if(定時標志位置一)

{

定時標志清零;

If(T_5ms) //若T_5ms大于0,每5ms減1

T_5ms--;

}

}

if(T_5ms==2)

{

WEI=0; //消影 共陽,共陰為 WEI=0xff

DUAN=code[value_duan1];

WEI= value_wei1;

}

if(T_5ms==1)

{

WEI=0;

DUAN=code[value_duan1];

WEI= value_wei2;

}

if(T_5ms==0)

{

T_5ms=3; //計時寄存器重新賦值

WEI=0;

DUAN=code[value1];

WEI=value2;

}

這樣CPU不用在這里死等,每次程序跑到這里時,只需做個判斷就好了,5ms到后就進去點亮數(shù)碼管,否則就不進去,顯示效果絕對均勻。同理,諸如鍵盤掃描程序,延時消抖,都可以采用這種方式,而不用delay。

也許讀者可能發(fā)現(xiàn)了問題,對,還是有點問題。假若程序在其他地方耗費時間大于5ms的話,那么這里的定時5ms就失去了作用。確實是這樣的。實際上對于好程序來說,主循環(huán)絕對控制在1ms一下(CPU跑1Mhz,即1條指令1us)。也許你會問,有些模塊不可能1ms以內(nèi)就完成啊。是的,有些時候某些模塊確實需要很久才能完成。這就涉及到程序分時分段處理的問題。好比人做事情一樣,我這件事今天做不完,但可以明天再做,而且同時今天我也要吃飯、睡覺做其他的事情,而不是說這件事沒做完,別的什么也不干了。單片機也是如此。不管在大的程序,都是分時分段處理的,不然CPU會崩潰的,CPU不可能同時把所有的都一起處理了,而是這段時間處理一點,下段時間再處理一點。這樣在總的時間上是一樣的,CPU完成的事情卻翻倍了。說道這里程序主循環(huán)控制在1ms絕對不成問題了。在試想一下,在程序里面到處delay是不是很可怕?比如按鍵,消抖可以delay 10ms,如果是長按鍵呢?難道要delay 3s或更長?所以說不管從功能上還是程序結(jié)構(gòu)上,delay是絕對不可取的。對于delay,幾個us(相當于幾個nop指令)還是允許的。

說到這里,程序分時分段思想已經(jīng)很明白了。雖然說一個大型項目,包括很多模塊,比如按鍵、AD采樣、數(shù)碼管顯示(或lcd顯示)、PWM輸出、UART、IIC通訊等等,但是并不是說每個模塊都在同一時間完成。比如按鍵按一下大概幾百毫秒的樣子,長按好幾秒的樣子,主程序不是一直在這里等,而是一遍又一遍的循環(huán)掃描,當掃描的按鍵鍵值變化而且連續(xù)在100ms以內(nèi)沒有變化,那么確認此次為短按鍵按下。每次在掃描鍵盤時大概耗費幾十us,然后接著以同樣的方式掃描其他模塊。這樣主循環(huán)把所有的模塊都掃一遍頂多也就幾百us的樣子。這樣說來,一次按鍵按下事件,程序已經(jīng)把它分成了大概幾百次來完成,即為分時處理。而不是以delay的方式死等這一次事件完成。其他模塊都遵循這個道理。

告別delay,主循環(huán)while(1)周期做到小于1ms,那么就告別了學校教育從而進入實際應用!為什么學校所教的不是這種思想呢?因為在學校和實踐嚴重脫節(jié),沒有考慮過真正的項目。所學的都是一些獨立子程序模塊。由于子程序結(jié)構(gòu)簡單,程序較小,delay無所謂。而把各個模塊都加在一起,可能就會出毛病。實際情況要考慮的還多的很,比如功耗、成本等等。在學校只管能搞出結(jié)果就不錯了,哪管這個芯片多少錢,這個電容多少錢?對于真正的項目應用,實現(xiàn)功能只算很小很小的一部分。由于學校所學和實際脫節(jié),所以這也是當今大學生難找工作的原因之一,這也是當今中國教育的缺陷!當然成為單片機高手,還有很多路要走,了解這些只是一個門檻而已。



評論


技術專區(qū)

關閉