北京信息科技大學信控中心,北京 100192
輸液泵在臨床中常用于高危患者的治療,以達到降低醫療風險、改善患者的治療效果的目的[1-2]。而輸液泵屬于嵌入式系統的一種,其組成中負責控制功能的微處理器往往是8位或16位的單片機。此類設備運算能力和內部資源都有很大的局限性,如何保證利用有限的硬件實現系統的功能需求和實時性要求是設計人員的首要問題。
目前,很多輸液泵都采用了基于指令功能的軟件設計方法[3-4]。這種方法具有簡單、節省資源的特點,但往往實時性較差。
本文采用多任務型軟件架構,加入了任務的優先級調度機制,更加合理的利用了系統資源,同時使系統的實時性和可靠性得到的明顯提高。
嵌入式軟件的開發往往針對特定的系統,根據硬件平臺的不同,“因地制宜”地圍繞系統的具體需求而展開[5]。而不同的系統,其需求各不相同,因此嵌入式軟件千差萬別。
輸液泵系統是以單片機為控制核心,通過對電機等機械裝置的控制,實現藥液輸注的典型嵌入式系統。其軟件的體系結構與一般嵌入式系統相較而言,有相同之處。總體而言,可以將其劃分為如圖1所示的三層:底層、中間層和頂層。底層包括系統引導程序和監控程序;中間層包括操作系統、板級支持包(BSP)、處理器支持包(PSP);頂層包括設備驅動程序、用戶應用程序。在程序的設計過程中,頂層軟件是設計的重點。

設備驅動程序是上層應用程序與硬件設備交互的橋梁。MQX操作系統中已經提供了對于通用硬件的支持,如GPIO、ADC等。但輸液泵裝置中的存在大量的專用硬件,還需要根據各個硬件的功能需求開發專用的設備驅動程序。
用戶應用程序是完成輸液泵業務邏輯的主要程序,是開發的最主要部分。不同的輸液泵系統根據具體功能的不同,硬件結構的不同,實現方式的不同,其用戶應用程序也各不相同。但總體而言,可以將用戶應用程序劃分為兩大部分 :實時控制程序和安全保障程序。
實時控制程序:是完成輸液泵主要功能的主體程序,實現了圖形顯示、電機控制、響應系統輸入、數據處理等輸液泵的核心功能;
安全保障程序:是對輸液泵系統狀態進行檢測和保護的程序,可以在一定程度上保障了輸液泵安全、可靠的運行。主要實現了壓力檢測、電機狀態檢測、氣泡檢測、數據流控制等與安全相關的功能。
由于輸液泵系統屬于對實時性、可靠性要求較高的嵌入式系統,因此在設計軟件時需要特別考慮程序的運行效率。本設計采用功能模塊化的設計方法,利用嵌入式操作系統MQX對多個任務模塊進行管理的方式。這種設計方式可以極大地提高輸液泵系統中程序執行的并發性,從而保證了系統實時性的要求。
按照輸液泵系統的功能需求,將系統劃分為5個任務模塊,如圖2所示。

(1)主循環模塊:系統初始化、用戶事件響應;
(2)按鍵處理模塊:處理鍵盤輸入;
(3)顯示處理模塊:實時更新LCD上的系統信息;
(4)周期檢測任務模塊:根據系統狀態,周期檢測各個異常狀態;
(5)中斷檢測任務模塊:運行狀態下,檢測電機相關狀態。
每個任務的優先級及調用的任務函數各不相同,具體設置如表1所示。中斷任務與普通任務的設置方式略有不同,需要使用“_int_install_isr()”系統函數在MQX操作系統中注冊,在此不做具體說明。

表1 任務優先級及調用的函數說明
MQX系統的任務調度,采用優先級搶占CPU的方式實現。當前正在運行的任務,實際上并“不知道”系統中存在其他的任務,而是完全占用CPU資源獨立運行[6]。只有當前任務運行結束、調用任務阻塞函數或任務延時函數時,其他處于就緒狀態的任務根據優先級的高低,由優先級最高的任務搶占CPU,進入運行狀態。在本系統中,周期檢測任務在各個系統任務中的優先級最高,系統會首先檢查該任務是否就緒,就緒則立刻轉入并執行。如果未就緒,則會檢測下一優先級的任務“主循環任務”,以此類推的直到系統對所有任務都進行了一次遍歷。然后系統會重新檢查周期檢測任務是否就緒,開始下一次循環。具體調用流程如圖3所示。
其中,比較特殊的是中斷檢測任務,其調度方式與一般系統任務不同,具有更高的優先級。在MQX系統中,中斷任務一旦設置好觸發條件和任務函數,只要滿足了觸發條件,無論當前哪個任務正在運行,都會保存當前任務運行的位置,并立即轉入中斷任務。

由于采用多任務搶占的設計模式,各個任務對數據進行處理后,不僅需要任務之間數據的通信,還需要進行任務間同步,保證數據的一致性。本設計采用了三種方式,全局變量、互斥量、輕量級消息隊列。
全局變量“SysCore”是自定義的結構體變量,為了方便任務之間的通信,將與輸液泵系統相關的幾乎所有參數都包含在內,如系統狀態、當前界面、返回界面、運行參數、硬件驅動接口。
互斥量主要設置在電機、LED等硬件驅動的模塊中。由于驅動模塊可能會被多個任務調用,當一個任務調用硬件驅動時,使用鎖定互斥量獨占資源,避免發生意外錯誤。
輕量級消息隊列用于實現任務間的數據交換。實現方式是:由某一任務發送數據給輕量級消息隊列,再由其他任務從消息隊列中讀取。
主循環任務是系統初始化完成后自動進入的第一個任務模塊。在開始主循環之前,系統需要對硬件設備進行初始化,并利用MQX的任務列表和“_task_create()”函數創建各個任務。因此,主循環模塊又分為了三個子模塊:硬件初始化模塊、任務初始化模塊、循環響應模塊。模塊流程圖如圖4所示。
硬件初始化模塊:主要功能是對各個設備的控制、檢測端口進行初始化,主要包括LCD、電源、FLASH、鍵盤、蜂鳴器、LED、電機等。通過調用與各個硬件相對應的驅動函數,對硬件的初始狀態進行設置,并初始化負責控制各個硬件的驅動結構體。
任務初始化模塊:主要功能是創建除“main_task”以外的其他任務。由于系統初始化和任務初始化只有在系統啟動時執行一次,如果失敗的初始化或錯誤的初始化沒能被系統識別,則可能對后續的程序運行帶來無法預知的后果。因此,需要通過檢查返回值的方式對任務創建的結果進行檢查,即檢查“_task_create()”函數的返回值是否為對應任務的“task_id”。一旦檢查結果異常,則立即阻塞當前任務,系統進入異常狀態,無法通過按鍵等進行操作。
循環響應模塊:負責讀取由按鍵處理任務傳遞的按鍵狀態,并通過判斷系統當前的狀態調用對應的函數響應用戶的輸入。由于采用模塊化的設計方法,系統的參數設置、輸液模式選擇、啟停等控制函數都相互獨立并存放于“ObjectOperationPool[]”數組中。該數組的類型為自定義的結構體“OBJECT_OP_STRUCT”,即數組的每個元素都是一個結構體。結構體包含的元素為“UP”、“DOWN”、“LEFT”、“RIGHT”、“OK”、“START”等按鍵響應的函數。再根據循環響應模塊讀取的系統狀態和按鍵狀態值,調用數組中哪個元素的哪個函數。

按鍵處理模塊的主要功能是正確無誤的讀取用戶向系統輸入的控制指令,并將指令通過輕量級消息隊列發送給相應的任務模塊。從硬件角度看,外部輸入鍵盤共有10個按鍵,分別為:“OK”、“Start”、“Stop”、“Mode”、“↑”、“↓”、“→”、“←”、“Bolus”、“Clear”。按鍵處理模塊實現的具體功能為:
(1)鍵盤任務模塊通過鍵盤驅動模塊提供的“dev_kb_read()”函數讀取鍵盤按鍵值,查詢各個按鍵按下狀態,即獲取按下的是哪個按鍵的信息;
(2)根據按鍵狀態判斷用戶的輸入意圖,并將用戶輸入的有效按鍵信息讀入,如讀入按鍵的初次按下狀態、短按下狀態、持續按下狀態;
(3)將按鍵信息(鍵值和狀態)通過輕量級消息隊列的方式發送給主循環任務和顯示處理任務。
按鍵處理模塊的流程圖如圖5所示。首先進行初始化設置,對該任務所需要的變量和消息隊列進行初始化,并讀入系統數據,進入循環。然后,執行讀取和發送按鍵信息的處理。利用鍵盤驅動模塊提供的讀取函數,將鍵盤對應的硬件狀態值賦值到變量VALUE_CUR中。再將判斷后的按鍵狀態發送到消息隊列中,完成一次循環。

顯示處理模塊的主要功能是讀取系統信息,并利用LCD顯示驅動控制LCD顯示屏顯示并實時更新提示信息。顯示處理模塊在系統啟動后需要持續更新顯示信息,因此需要使用while(1)循環,每執行完一次循環調用_time_delay()函數,等待下一次調用。在循環體內部,根據功能需求可以分為三個子功能模塊:圖形建立、報警界面切換、數據更新。顯示處理模塊的具體流程如圖6所示。
圖形建立模塊的功能是根據系統狀態,在LCD屏幕上創建一些提示性圖標,如低溫、電池電量等;
報警界面切換模塊在每次調用時,會首先檢查系統狀態字信息,如果處于異?;蚬收蠣顟B,則會根據狀態字調用相應的界面創建函數,進行界面報警處理;
數據更新模塊負責調用信息顯示歷程,以遍歷的方式逐條調用各個顯示信息的更新函數,對系統各個顯示信息進行更新。

周期檢測任務模塊的主要功能是在系統啟動后,根據系統的當前運行狀態,讀取不同的傳感器信號,用以檢測系統當前狀態是否正常。一旦檢測函數發現系統處于異?;蚬收系臓顟B,則會根據系統的狀態觸發不同類型、級別的報警并調用相關處理函數。由于需要在輸液泵系統使用期間持續的對各類異常狀態進行檢測,因此需要使用while(1)循環,并在循環結束后調用_time_delay()函數,交出CPU占用權,等待下一次搶占。周期檢測任務模塊在循環體內部,按照功能的不同,劃分為三個子模塊,分別為:報警恢復檢測、傳感器信息讀取、系統狀態檢測處理。周期檢測任務模塊的具體流程如圖7所示。

報警恢復檢測模塊:主要起到一個計時器的作用。輸液泵在使用時可能會出現一些需要用戶處理的特定情況,如:待機超時、輸液接近完成、電池電量過低。在出現這類不影響用戶正常使用的情況時,需要發出可消除的報警信號,提醒用戶進行處理。報警恢復檢測模塊的主要功能就是檢測這些特定情況是否被工作人員及時處理。如果檢測到在指定時間內,仍未解除特定情況,則會再次觸發報警。
傳感器信息讀取模塊:主要功能是正確的讀取輸液泵系統中傳感器的狀態信息。輸液泵系統中共包括6種不同功能的傳感器,分別實現泵門開啟檢測、輸液管路氣泡檢測、輸液管路壓力檢測、溫度檢測、電源狀態檢測、電機狀態檢測。設計時,考慮到電機相關狀態的優先級較高,將其設置成中斷形式的檢測外,其他傳感器信號的讀取都在本模塊中實現。傳感器信號的讀取需要考慮到傳感器失效的情況。以負責氣泡檢測的超聲波傳感器為例,通過比對使能時的傳感器數值和禁用后的傳感器數值,可以判斷傳感器本身是否處于故障狀態,進而判斷讀取信息的正確性。
系統狀態檢測處理模塊:主要是根據讀取的傳感器信息,對系統狀態進行邏輯上的判斷。輸液泵系統狀態的檢測分為系統故障狀態的檢測和系統異常狀態的檢測。系統故障狀態的檢測主要是對與安全性高度相關的硬件設備的檢查,如電機狀態、氣泡傳感器、壓力傳感器,目的在于及時發現硬件的失效,并及時觸發相應的報警。系統異常狀態的檢測主要是是根據各類傳感器的數值,判斷輸液泵是否出現了異常狀態。系統狀態檢測處理的流程是:根據系統當前的運行狀態,選擇性地執行系統故障檢測和系統異常檢測中的某些函數,以判定當前系統是否正常運行。如果判定系統出現故障或異常,則啟動聲、光報警,停止電機運轉并將系統狀態置為當前的故障或異常的狀態。輸液泵運行狀態與調用檢測函數的詳細情況如表2所示。

表2 輸液泵運行狀態與調用檢測函數的詳細情況表
中斷檢測任務模塊主要是負責電機運行狀態相關的檢測,例如轉動方向、轉動速度。輸液泵電機采用步進角為1.8°的兩相步進電機,并使用16細分控制。電機每轉一圈的脈沖數由公式(1)計算得3200??刂贫嗣看伟l出脈沖信號為一次中斷,電機中斷函數為電機反饋計數器加一,作為反饋中斷函數的判斷依據。

其中,N—脈沖數;
ρ—電機旋轉的角度;
ω—電機的步進角;
d—控制電機步進的細分數。
圖8為輸液泵電機狀態監測的示意圖,運行過程中電機每轉一圈,圖8中的兩個光電開關分別被電機軸上的擋光片遮擋一次。以光電開關1的信號變化作為中斷條件,調用反饋中斷函數。
反饋中斷函數流程圖如圖9所示,該函數讀取兩個光電開關的信號,進而由遮擋情況判斷電機的轉向,并判斷計數器的值。如果計數值超過或低于允許的誤差范圍(±5%),則認為電機故障。反饋中斷函數還會重置電機中斷函數中的電機反饋計數器。


由于輸液泵在實際使用中,精度受到輸液器影響較大。因此,首先需要對輸液器進行性能測試。選取市場上較為常見的三種輸液器,在同樣的設定流速下進行精度測試。測試結果如表2所示。可以看出在持續運行24小時后,輸液器精度均有所下降,但哈娜好輸液器的精度下降最少,適合作為測試用輸液器。

表2 輸液器精度下降測試結果
選擇哈娜好輸液器,分別采用不同的流速運行4小時,對輸液泵進行精度測試。測試結果如表3所示。

表3 輸液泵精度測試結果
實驗結果表明除1ml/h和5ml/h兩種極低流速情況外,但是在常規的流速狀況下,輸液泵可以滿足5%的精度要求。
本文設計了應用于輸液泵系統的多任務嵌入軟件,給出了軟件的體系結構、任務模塊的劃分、任務間通信以及任務模塊的實現方法。這種設計方法,在一定程度上減少了系統資源的浪費,并且易于改進和擴充。系統功能模塊化,在后期維護中具有很好的可讀性和可理解性。