<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 嵌入式系統 > 設計應用 > 單片機分時(shí)思想

單片機分時(shí)思想

作者: 時(shí)間:2016-11-17 來(lái)源:網(wǎng)絡(luò ) 收藏
下面說(shuō)的單片機應用也主要是家電控制方面,也就是現在的工作。其它應用不在討論范圍。才識有限,也敬請前輩們勘誤,指教。

本文引用地址:http://dyxdggzs.com/article/201611/315477.htm

先用一個(gè)小例子引出今天的主題,想象一下,一個(gè)基本的家電控制板,肯定或多或少的會(huì )包含 : LED 或者 數碼管顯示, 按鍵, 繼電器或者可控硅的輸出 這3部分。數碼管需要 10ms到20ms的動(dòng)態(tài)掃描,按鍵也需要 20ms左右的延時(shí)消抖,有沒(méi)有意識到,其實(shí)這些時(shí)間是同時(shí)在進(jìn)行的?;叵胍幌略蹅兊慕炭茣?shū)怎么教 按鍵 的延時(shí)消抖的?沒(méi)錯,死循環(huán),絕對是原地踏步死循環(huán),用指令來(lái)計時(shí)。這樣很自然的引發(fā)一個(gè)問(wèn)題,單片機在原地踏步死循環(huán)的話(huà),那么其它的工作怎么辦?如數碼管的動(dòng)態(tài)掃描怎么辦?唯有等按鍵掃描之后再進(jìn)行了,這樣出來(lái)的效果,數碼管肯定會(huì )閃爍的,掃描時(shí)間過(guò)長(cháng)了,縮短按鍵消抖時(shí)間也不是解決辦法,想象如果咱們還有其它很多工作也是同時(shí)做的呢?解決辦法之一,就是今天的主題,分時(shí)掃描的思想。當然不會(huì )是唯一的辦法,只不過(guò)俺一直在用,覺(jué)得這個(gè)是非常不錯的思想,可以解決很多實(shí)際問(wèn)題。大膽妄言一下,分時(shí)掃描的思想也是單片機編程最核心的思想了,信不信就由你自己判斷了。

程序的執行環(huán)境

用的是純匯編,因為用習慣的匯編,以致于整個(gè)腦袋都是匯編的思想,某種程度上說(shuō),C的廢碼確實(shí)是多了一點(diǎn),對于實(shí)際工業(yè)用的單片機ROM和RAM都不是很充足的情況下,代碼還是要求盡量精簡(jiǎn)的。所以俺一直都在匯編的苦海中沉浮著(zhù)……說(shuō)明一點(diǎn),俺用的是EMC的單片機(Elan公司的),傳聞中最爛的單片機,所以代碼不值的去學(xué),也正是這個(gè)原因,但愿我想表達的思想能表達清楚, 阿門(mén)!

核心思想的實(shí)現

其實(shí)是幾個(gè)步驟,

第一, 用TCC中斷來(lái)計時(shí),TCC的中斷時(shí)間斷一點(diǎn),我習慣是 125us ,為了解紅外遙控的碼,這個(gè)時(shí)間是需要的。TCC計時(shí)是相當準的,盡量利用。

第二, 在TCC的中斷服務(wù)程序里面放3個(gè)(數量自定)記時(shí)器(說(shuō)白了就是計數器),我的習慣是 2ms 5ms 500ms 這3個(gè)是作為基準時(shí)間,提供給整個(gè)系統來(lái)調用的,所以必須準確一點(diǎn),實(shí)際用示波器調一下就OK了,不難。

第三, 在主程序的循環(huán)里面放一個(gè)專(zhuān)門(mén)處理時(shí)間的子程序。(注:?jiǎn)纹瑱C是不會(huì )停的,永遠在不斷循環(huán)的跑,這個(gè)跟學(xué)校學(xué)的貌似有點(diǎn)不同,俺面試的時(shí)候被問(wèn)過(guò)這個(gè)問(wèn)題 ….) 將所有的時(shí)間處理都放在時(shí)間處理子程序里面做,這樣是非常方便的,一個(gè)單片機系統最起碼需要處理 10~20個(gè)不同的時(shí)間,也需要10~20個(gè)計時(shí)器了,而且相當多要求同時(shí)不同步工作的,如果每個(gè)都單獨的話(huà)是相當的麻煩。

第四, “程序是跑著(zhù)來(lái)等,而不是站著(zhù)來(lái)等”,這話(huà)看來(lái)有點(diǎn)玄,一個(gè)跟俺一起進(jìn)去公司的工程師討論的時(shí)候提到的這個(gè)問(wèn)題,俺覺(jué)得這個(gè)也是分時(shí)系統的一個(gè)比較重要的思想,所以也這樣叫,下面有細說(shuō)。

第五, 下面用程序來(lái)說(shuō)話(huà),注釋盡量詳細,可以不用看代碼,直接看注釋就可以了。

(一)先中斷服務(wù)程序部分:

每 125us 中斷一次

;-------------------產(chǎn)生幾個(gè)基準時(shí)間---------------------------

int_2ms:

djz ref_2ms (1)

jmp int_5ms

mov a,@16 ; 恢復原始數據

mov ref_2ms,a

bs flag_time,flag_2ms (2)

int_5ms:

djz ref_5ms

jmp ref_time_end

mov a,@40 125us×40=5ms

mov ref_5ms,a

bs flag_time,flag_5ms

int_500ms:

djz ref_500ms

jmp ref_time_end

mov a,@100

mov ref_500ms,a

bs flag_time,flag_500ms

ref_time_end:

nop

(1) ef_2ms寄存器不斷的減1,每次中斷減1,一共減 16次,所以這里經(jīng)過(guò)的時(shí)間是 125us × 16 = 2ms,這個(gè)就是所謂的計時(shí)/計數器 了。這樣就可以靠一個(gè)系統的TCC中斷,來(lái)實(shí)現我們需要的很多個(gè)定時(shí)時(shí)間。

(2)置 2ms 計時(shí)結束標志,這個(gè)是提供給時(shí)間處理程序用的,這是一個(gè)計時(shí)器的框架,下面的5ms計時(shí)完全相同。

這里解釋一下:bs flag_time,flag_2ms,其中bs是將某一位置1的指令,該指令的意思是,將 flag_timg寄存器里面第flag_2ms位置1,設立一個(gè)溢出標志,后面的程序可以通過(guò)讀這個(gè)標志,就知道 2ms 是否已經(jīng)計時(shí)到了

這程序還用了一個(gè)塊的框架,比較方便的,不過(guò)跟今天的主題無(wú)關(guān),以后郁悶的時(shí)候再上來(lái)寫(xiě)寫(xiě)這個(gè)。上面的程序就是中斷服務(wù)程序里面的計時(shí)器,分別定時(shí) 2ms 5ms 500ms,計時(shí)完畢溢出是flag_time 標志來(lái)記錄的,程序通過(guò)讀這個(gè)標志就可以知道定時(shí)的時(shí)間是否已經(jīng)到了。

(二)下面看那個(gè)統一的時(shí)間服務(wù)子程序

;-------------------時(shí)間處理子程序-----------------------------

time_proc:

jbs flag_time,flag_5ms 判斷5ms是否到

jmp time_500ms_proc 沒(méi)有的話(huà)判斷500ms

time_5ms_proc:

bc flag_time,flag_5ms 5ms已經(jīng)到了,進(jìn)入服務(wù)程序,先清掉那個(gè)標志,這樣下次再過(guò)5ms才允許進(jìn)來(lái)這里。

;------------------ 按鍵延時(shí)部分--------------------- ;這里用這個(gè)做例子

key_delay_proc:

jbs flag_delay,key_start ; 按鍵延時(shí)開(kāi)始標志,這個(gè)用來(lái)控制是否進(jìn)入計時(shí),允許計時(shí)標志

jmp key_delay_end

djz reg_key ; 預先設置的延時(shí)時(shí)間,每5秒減一次,這里預設的值是4,也就是說(shuō) 5ms * 4 = 20ms

jmp key_delay_end 有減到0的話(huà)直接跳出

bs flag_delay,key_flow 時(shí)間到,置需要用的標志

mov a,@4 ; 重新置數據下次用。

mov reg_key,a

key_delay_end:

nop

;---------------------500ms處理部分------------------------

time_500ms_proc:

jbs flag_time,flag_500ms

ret

bc flag_time,flag_500ms

這里放需要的計時(shí)器

Ret

上面用了按鍵20ms消抖的計時(shí)器作為例子,如果理解之后就可以發(fā)現,我們可以完全模仿那個(gè)計時(shí)器而在下面放很多很多的計時(shí)器,則每5ms 進(jìn)來(lái)一下,每個(gè)計時(shí)器都同時(shí)在計數了,誰(shuí)先計算完畢就先關(guān)掉自己,置相應的標志給其它程序調用,而對其它計時(shí)器完全沒(méi)有影響!這樣,我們可以在這里放很多個(gè)計時(shí)器了,一般來(lái)說(shuō),十來(lái)二十個(gè)是沒(méi)有問(wèn)題的,完全滿(mǎn)足一個(gè)單片機系統對多個(gè)時(shí)間的需求了。

單個(gè)計時(shí)器的結構很簡(jiǎn)單,先判斷允許計時(shí)標志是否進(jìn)入計時(shí),然后一個(gè)專(zhuān)用的寄存器在加1或者減1,加/減購相應的數值之后也就是相應的時(shí)間到了,關(guān)掉計時(shí)器,置相應需要用到的標志。

到這里差不多了,俺們需要的時(shí)間都可以出來(lái)了,這樣做是不是非常方便?咱們再來(lái)看看在這段時(shí)間里面單片機在做了什么東西?只有中斷計時(shí)夠 5ms 或者 500ms ,那個(gè)溢出標志才有效,才能進(jìn)入上面的計時(shí)程序,其它時(shí)間都是在做其它事情。而且進(jìn)入上面的計時(shí)器的時(shí)候,可以看出,并不是在那里死循環(huán),只是單純的加減一下寄存器就退出了,整個(gè)過(guò)程耗時(shí)極其短,看代碼不同吧,5us到 20us左右吧,對主程序的執行沒(méi)有什么影響。

(三)下面看看具體怎么調用

最開(kāi)始談過(guò)的按鍵的消抖時(shí)間處理問(wèn)題,現在就用上面介紹的辦法來(lái)看具體怎么解決問(wèn)題。按鍵的處理也是重要的基礎學(xué)問(wèn),不過(guò)不在本次的討論范圍,所以只是單單的討論怎么解決時(shí)間問(wèn)題,而對于按鍵的一些問(wèn)題,下次有機會(huì )繼續討論吧,hoho~~~

scan_key:

jbc flag_key,first_on ; 用來(lái)控制跳轉的

jmp have_key

jbs port6,1 假設P61高電平是有鍵

jmp key_end

;-------------------------------------

bs flag_key,first_on 第一次按鍵的標志

bs flag_delay,key_start 啟動(dòng)計時(shí)器開(kāi)始定時(shí)20ms消抖

have_key:

jbs flag_delay,key_flow 等待定時(shí)結束溢出

jmp key_end

大概是這樣的:判斷時(shí)候有健,沒(méi)有的話(huà)跳出,有的話(huà)開(kāi)始延時(shí)消抖的計時(shí),第二次進(jìn)來(lái)的時(shí)候直接由標志位控制過(guò)去判斷時(shí)間時(shí)候夠。

同樣是等待,這里就是最后一點(diǎn)所說(shuō)的,咱這是跑著(zhù)來(lái)等,不是站著(zhù)來(lái)等。跟死循環(huán)定時(shí)比較,在沒(méi)有定時(shí)到20ms 的這段時(shí)間里面單片機在做什么? 死循環(huán)的話(huà),肯定就是在原地等,什么都不做,而看看上面的程序,他只是判斷是否定時(shí)夠,具體的定時(shí)在統一的時(shí)間子程序里面做,判斷沒(méi)有到時(shí)間的話(huà)就跳出了,繼續跑其它的程序,直到當時(shí)間到了,單片機判斷出flag_delay,key_flow 符合條件,開(kāi)始進(jìn)入按鍵處理程序了,在這個(gè)期間,單片機都在做其它事情,只是一個(gè)主循環(huán)跑回來(lái)判斷一次,所以單片機完全有空跑其它的程序,而沒(méi)有將時(shí)間都耗在消抖上面。

(四)看看我的主程序循環(huán)體

start:

call clear_all_ram 清空RAM

call initialize 初始化

loop:

eni 開(kāi)中斷

wdtc 清看門(mén)狗

call scan_proc 調用掃描LED和按鍵程序

call ir_data_proc 調用紅外處理程序

call time_proc 調用時(shí)間統一處理程序

call output_proc 調用輸出處理程序

jmp loop

這個(gè)就是我用的循環(huán)體了,所有功能都做成子程序形式了,需要就掛上去就可以了,比較方便,這樣一個(gè)總的循環(huán)體,單片機就是在不斷的執行這個(gè)循環(huán)體,如果整個(gè)程序都采用上面說(shuō)的分時(shí)掃的思想的話(huà),一周循環(huán)回來(lái)的時(shí)間是相當短的,其實(shí)是不是跟電腦的思想有點(diǎn)像呢?電腦再快也并不是同時(shí)處理多個(gè)任務(wù),而且每次處理一個(gè),然后非??斓乃俣葋?lái)循環(huán)處理,讓我們感覺(jué)上他是在同時(shí)處理多個(gè)程序那樣,我想,我最終想表達的思想也就是這個(gè)而已。

啰啰唆唆的說(shuō)了一堆,也不知道是否能看懂,或者是否去看。不知道我對分時(shí)掃描這個(gè)概念是否理解錯了呢?在我看來(lái),有這個(gè)思想支撐下,單片機的程序變得比較容易上手了,剩下的只是集中精力去用程序來(lái)實(shí)現我們的思想而已,當然,這里只是說(shuō)一種可行的辦法而已,不是說(shuō)只有這種辦法,如果大家有好的思想也分享一下哦,編寫(xiě)程序是一門(mén)藝術(shù),寫(xiě)出來(lái)很容易,但是寫(xiě)得好,寫(xiě)得精巧,那就很難了。



關(guān)鍵詞: 單片機分時(shí)思

評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>