C語言-簡易的分時多工概念

1.關於分時多工

MCU在任何情況底下,基本上我們自己寫入的邏輯,透過MCU程式只能逐一執行,並無法同時在一個時間單位內處理多個命令,然而因為MCU速度夠快,對於人來說就好像可以在同一個時間以內做很多事情,但終歸來說,CPU同一個時間內還是只能做一件事情,而有時候我們再處理MCU程式的時候,經常會有等待的情況,這些等待有可能是內部硬體資源的等待,有可能是外部硬體的等待,例如:AD轉換的等待時間,這些時間就足以造成我們等待。

然而為什麼要分時多工?如果把需要等待的時候,把MCU浪費在等待上面就會顯的非常沒有效率,一般來說MCU可能同時需要處理很多周邊的事情,有可能要控制I/O又要量測AD,又要通訊等等,此時如果程式中有一個while(); for();之類的東西佔用太多時間,則就會影響到其他程式的工作時間,而整體反應時間就會被拖慢。

以電腦的角度觀之,我們可以同時開啟數個程式同時執行,然而對於CPU來說也並不是同一時間進行處理,也是透過將時間分割的方式,執行緒分配給不同的程式使用,所以簡單說作業系統(OS)的作用就是在於任務管理。

在MCU裡面也有許多所謂的RTOS即時式作業系統,但是是否所有應用都適合使用RTOS?這邊我不表示意見。

但在不使用RTOS的情況底下,我認為寫MCU還是需要保有時間的概念,要如何自己有效的控管MCU的執行時間就顯的相當重要。

2.MCU處理的時間

以前用組合語言學PIC的時候可以透過命令的行數與MCU的system clock來計算副程式時間,所以執行的時間可以掌控到相當精準,但是換到C語言,因為每個編譯器的不同所產生的命令也不同,所以也很懶得去預估這些時間,但很難去預估並不是代表就不需要去預估,還是有其他方式可以進行程式運作時間的評估,我比較常用的方法有兩種

較準確的方式,採用GPIO,作法就是在副程式開始前改變GPIO狀態,離開時再改變一次GPIO狀態,再用示波器看變化時間,就是程式處理時間,這個方法的缺點是需要有一支空的IO腳跟示波器才能夠觀察,優點則是比較準確預估。

誤差較大的方式是使用內部Timer interrupt count一個變數,在進入副程式之前清除或設定一個值,離開副程式的時候檢查該變數的變化量在這個變化量計算時間即可,這個缺點就是誤差比較大,因為為了要count時間,所以timer可能必須要很即時的進入interrupt,但是一旦有進入interrupt的時候也就會產生時間的消耗,故會造成誤差,但是優點是不太需要其他外部工具也能進行粗略的預估,至少得到的結果可以判定為說該副程式執行時間一定小於得到的結果。

3.如何製造多工?

如果用RTOS的時候,RTOS就會提供任務管理的功能,但是不使用RTOS的時候要怎麼製造多工?我認為只有一個原則,就是所有要等的地方,都不要浪費時間等,就能夠提高程式的運作效率。例如一個應用範例是,透過外部硬體切換N個通道並獲取這些通道所輸入的頻率,而頻率量測的方式採用1秒count計算,當量測完所有通道時換算頻率,則從條件上看來要量完N個通道就需要花上N秒,不可能讓MCU量完這N秒之後才去做其他是情,所以我們可以用類似以下這樣的架構。

switch (handlerToken)
	{
	case GET_NEXT_CH:
		chSwitchFunc();
		handlerToken = GET_CNT;
		break;
	case GET_CNT:
		if (status == COMPLETE)
			{
			cntSave[ptr] = getCountFunc();
			if (ptr > CH_NUM)
				{
				ptr++;
				handlerToken = GET_NEXT_CH;
				}
			else
				{
				ptr = 0;
				handlerToken = GET_RESULT;
				}
			}
		break;
	case GET_RESULT:
		resultCalc();
		handlerToken = GET_NEXT_CH;
		break;
	}

從上面的架構來看我把測量Count這件事情拆成三件事情來做

a.切換通道 b.取得count c.計算結果

用白話文來說,第一次進來這個副程式的時候,會先切換通道然後改變handlerToken為下一個任務取得count,之後離開,當第二次進來的時候,會檢查是否完成count的捕獲?如果還沒則離開,如果完成了就檢查是否完成所有通道選擇?如果還沒就設定下一個要切換的通道,並將handlerToken切換回通道切換的任務,然後離開,之後在進來的時候就會重複剛剛的動作直到所有通道量測完畢,就將任務指向結果轉換,當結果轉換完成後再切回通道切換任務進行下一次的開始。

如此一來,就可以減少等待的時間,讓MCU有其他時間可以去做其他事情。

task

 

其他參照 PSoC Creator UART buffer in Super Loop

發表迴響