目前本人已經不再寫代碼了,只是想把自己走過的彎路,踩過的坑分享出來,希望更多的小伙伴能看到,少走彎路,僅供參考哈!
這章重點給新手們提供一個能最大利用CPU性能的程序架構思路,具體程序就不再展示了。
前言
在學習51單片機或者用51單片機做項目時,由于51單片機的資源配置都是有限的,所以當外圍需要實現的功能較多時,就必須要從程序的架構上下功夫,如果使用“單一任務”的思維去寫程序,會直接影響效果甚至運行不起來。
架構思路
而在上一篇文章中,我們使用定時器的方式,避免了CPU空等待的情況,沒看過的小伙伴可以戳這里:
其實思路也是比較簡單的,如下圖1所示:
上圖中的任務體其實就是CPU在一定的時間內需要“光顧”的事件,比如想讓LED在1S的時間做亮滅的動作,那CPU就不用一直“盯著”LED,可以先去做其他“事件”,等1S時間到了之后再去控制LED就行。
舉個日常生活的例子:
假如水燒開需要8分鐘,那在這8分鐘里,我們可以不用一直在等著,我們可以利用這8分鐘去做其他事情,比如畫板子和寫代碼都是沒問題的,等8分鐘到了之后我們再回來把熱水壺關掉(現實中熱水壺開了會自動斷電,這里只是舉例說明)。
那在實際的項目中,比如LCD顯示屏的刷新和ADC的采集,都是不用CPU一直盯著的,特別是ADC采集轉化時是需要時間的,如果ADC轉換時間CPU一直在等,那將是致命的,LCD面對的對象是人眼,所以刷新的頻率并不需要太快。
還有按鍵的掃描,數碼管的顯示等等!
但需要注意的一點就是:CPU不會像人一樣,工作起來可以隨時停下來,CPU是需要借助“中斷”來把CPU“拉回來”,從而實現任務的切換。
如下圖1和圖2所示
圖1
圖2
圖1和圖2是兩種不同的方式,圖1中CPU在沒有任務需要執行的時候,都是在空閑任務里面循環運行,定時器中斷隔一段時間把CPU拉回來。不同的任務當滿足要求時,就可以獲得CPU的“關照”,關照完后就回到空閑任務重進行循環。
圖2中,中斷可以發生在任何時候,包括任務執行的時候,但是需要提前定義不同任務需要CPU啥時候回來“關照”。一般以200HZ或者100HZ作為“基準”時間,再加上“節拍計數器”讓不同的任務獲得CPU短暫的“關照”,任務而不至于被CPU“冷落”。
一般來說LCD刷新的頻率10HZ左右即可滿足,按鍵做到20HZ基本上不會出現丟鍵的情況,數碼管刷新率做到50HZ左右即可滿足人眼的需求。
我們以100HZ作為定時器中斷時間,也就是任務切換的基準時間,則:
LCD的節拍數:100HZ/10HZ=10
按鍵的節拍數:100HZ/20HZ=5
數碼管的節拍數:100HZ/50HZ=2
那任務切換代碼是如何實現的,其實很簡單,只需要在大循環里面用if做判斷即可,給每一個任務做條件判斷,滿足條件即可讓CPU執行相應的任務,如下:
while(1)
{
if(task_num[0]==0) task0(); //task0 節拍數到,CPU執行task0
if(task_num[1]==0) task1(); //task1 節拍數到,CPU執行task1
if(task_num[2]==0) task2(); //task2節拍數到,CPU執行task2
if(task_num[3]==0) task3(); //task3節拍數到,CPU執行task3
}
最后,我們看一下定時中斷服務函數里面該怎么寫?(省略TH0和TL0部分代碼)
void timer0(void) interrupt 1
{
if(task_num[0]) task_num[0]--;
if(task_num[1]) task_num[1]--;
if(task_num[2]) task_num[2]--;
if(task_num[3]) task_num[3]--;
}
這一類程序的架構思路,中心思想就是把“單一的CPU”劃分成“多個CPU”的效果,充分利用CPU的資源,使外圍電路較多的項目運行起來更為流暢。
好了,今天就先聊到這吧,以上純屬個人看法,僅供參考!