陳飆,鄒遠文
(四川大學,四川成都 610065)
隨著人們對于自身生理健康的日漸重視,在日常生活中能夠方便、實時地進行生理信號的監測變得愈加重要。
人體的心電(ECG)和脈搏波含有豐富的生理信息,具有醫療和健康指導意義。利用心電波形可以進行異常心跳的檢測與分類[1],而利用脈搏波特別是光電容積描記脈搏波(PPG)可以進行多種心血管疾病的診斷[2],甚至可以結合ECG 和PPG 進行血壓的預測[3]。因此,本文基于STM32 設計了一種生理信號監測方案,可以實時同步監測清晰穩定的ECG 和PPG 波形。
方案總體上由信號的采集、處理和顯示3 個部分構成。其中采集部分由STM32 的模擬/數字轉換(ADC)部分對心電模塊和脈搏波傳感器采集的模擬信號進行采樣從而轉化成數字信號,而處理部分則是由STM32對采樣的數字信號進行濾波并實時提取信號波形的特征計算一些生理參數,顯示部分是STM32 將處理后的信號和特征參數通過LCD 屏和LabVIEW 上位機進行實時顯示。
方案選用的器件包括用于采集模擬生理信號的AD8232 心電模塊、脈搏波傳感器,用作主控芯片的STM32F103C8T6,用于顯示的LCD 屏和運行LabVIEW上位機的個人電腦(PC)。
STM32F103C8T6 的信號采集部分工作流程如圖1所示,包括STM32 對ECG 和PPG 模擬信號的ADC采樣及采樣后數字信號的DMA(Direct Memory Access,直接存儲器訪問)傳輸。

圖1 STM32 的模擬信號采集流程
由于需要同步采集ECG 和PPG,所以使用STM32的雙ADC 同步規則模式,即ADC1(主ADC)的外部觸發同時給ADC2(從ADC)提供觸發,這樣ADC1和ADC2 的2 個通道就能同時進行ADC 采樣。主ADC的外部觸發源配置為通用定時器TIM3 的TRGO 觸發輸出信號,同時將定時器的TRGO 信號配置為定時器的更新事件,這里是定時器的計數器在向上計數模式下從0 計數到自動重裝載值產生溢出時的更新事件。因此ADC 的采樣頻率實際上由計數器的時鐘頻率和自動重裝載值決定,可由以下公式計算:
式中:fADC為ADC 的采樣頻率的數值,也是計數器計數溢出的更新頻率的數值;RARR為自動重裝載寄存器的數值;fCNT為計數器的時鐘頻率的數值;fPSC為定時器的時鐘頻率,由APB1 總線的時鐘頻率結合APB1的預分頻系數獲得,此處為72 MHz。
這里將PSC 預分頻值設置為71,ARR 自動重裝載值設置為1 000,從而得到1 kHz 的ADC 采樣頻率。
在完成一次ADC 采樣后,ADC1 和ADC2 同時轉換的2 個12 位ADC 值分別存儲在32 位的ADC1 數據寄存器的低16 位和高16 位中,為了避免連續轉換時數據被覆蓋丟失,需要及時讀取。另外,為了避免CPU(中央處理器)頻繁響應中斷,選擇DMA 來進行外設ADC 到內部存儲器的高速數據傳輸。STM32 的DMA1 通道1 在內部直接與ADC1 相連,除了基本的數據傳輸方向(從外設讀)、外設數據寬度(32 位)等配置,還需要注意在內存中預先分配一個數組作為緩沖區,緩沖區的大小也是DMA 通道的CNDTR 傳輸數量寄存器的值,進一步將DMA 通道配置為循環模式,存儲器地址執行增量操作,這樣DMA 就能自動搬運數據填滿數組緩沖區,并且下一次自動從數組基地址重頭開始向內存搬運數據。
為了避免緩沖區數據被覆蓋,需要及時讀取數據并進行處理,但同時不應影響DMA 的高速連續傳輸,因此需要采用類似乒乓緩存的雙緩沖區[4],并且使能DMA 的HT 傳輸過半中斷和TC 傳輸完成中斷。每當DMA 傳輸50%的數據后,CPU 通過HT 中斷將緩沖區數組的前50%數據讀出處理(此時DMA 仍在繼續向后50%填充數據),并且關閉HT 中斷;當DMA 傳輸完成時,再通過TC 中斷將緩沖區的后50%讀出處理,再開啟HT 中斷。如此交錯反復,實現ADC 的連續采樣和周期性及時處理。中斷處理的時間間隔取決于緩沖區的大小,這里緩沖區數組長度設置為200,這樣DMA 每傳輸100 個數據也就是每隔100 ms 觸發一次中斷,進行數據讀取與信號處理。
原始的ECG 和PPG 信號最主要的噪聲是隨機噪聲,需要采用平均濾波來平滑曲線。這里采用滑動窗口數組來進行平均濾波,即每次接收1 個新的信號點,就將數組的首項數據去除,數組整體數據左移1 位,將新數據放入到數組的尾項,然后對這個窗口數組里的所有數據求平均值。這樣在不損失采樣點數量或采樣頻率的情況下很好地消除尖銳噪聲,提取了一定區間內的波形變化趨勢。
另外,滑動窗口越大,平均濾波后的曲線越平滑,但波形的特征越容易丟失,因此需要平衡好噪聲與波形特征的取舍,選擇合適的數組大小。EGG 和PPG 的原始含噪聲波形和濾波后波形如圖2 所示。

圖2 ECG 和PPG 波形的滑動平均濾波
ECG 和PPG 的波形特征蘊含著豐富的生理信息,這里考慮心率和血壓這2 種常見的生理參數。首先,ECG 的R 波間隔或者PPG 的波峰間隔都可以作為一個心跳周期,從而得到每分鐘的心跳次數即心率。其次,目前一種有潛力的無袖式血壓測量方法是通過脈搏波在人體動脈中的傳播速度來關聯預測血壓,這種速度可以體現為脈搏波從動脈近端到遠端的傳輸時間,一般通過ECG 的R 波與PPG 的某些特征點的時間差來計算,這里常用的特征點包括PPG 的峰值、足部、最大斜率/導數處等。
特征檢測算法需要對每個新的濾波后信號點進行實時判斷,從而及時地跟蹤并記錄波形變化。首先設定波形的峰值、谷值、周期及閾值初值,并且在連續判斷信號點的過程中不斷更新。具體來說,在更新過程中,閾值被不斷調整為波形峰值和谷值的平均值,因此每當出現大于閾值的信號點,就意味著波形此時正處于上升階段即將到達波峰,也標志著新的心跳節拍的開始;當出現小于閾值的點時,則說明處于波峰的下降階段,標志著當前一拍的結束。需要注意避免ECG 的T 波和PPG 的重搏波干擾,即判斷時不僅僅依賴于信號點的數值大小,還要注意信號點的時間距離上一拍的時間間隔是否大于1/2~3/5 個心跳周期。因此,ECG 的R 波和PPG 的波峰都可以通過一拍結束后更新的最大值來確定。PPG 的足部也就是波峰的山腳,則應在舊的一拍結束后新的一拍開始前這個時間段對信號點時間進行更新。當信號點首次出現超過5%~10%閾值(具體數值根據總體信號幅度確定)的上升幅度后,就停止更新,表示剛好從底部平緩的變化轉為向波峰快速爬升,表明已經找到了足部。而在檢測到峰值之前,出現最大上升幅度的點則被認為是最大斜率處。對本方案中某次實時采集的波形和特征數據保存后進行離線處理,繪制的圖像如圖3 所示。可以看到波形非常穩定而且細節十分清晰,并且各個特征都被清晰地用虛線標注了出來,不僅說明提取算法有效,也體現了波形質量良好。

圖3 ECG 和PPG 的波形及特征
STM32 需要與外部設備建立通信,再將濾波后的信號點和生理特征等數據傳輸給外接設備進行顯示。首先考慮小巧便攜的顯示方案,這里選用了分辨率為240×240 的1.3 英寸TFT-LCD 顯示模塊,其內核是一塊單片機控制和驅動芯片ST7789V3,支持8 位/9 位的并行輸入控制。
STM32 選擇串行外設接口SPI 進行與LCD 的通信,有助于節省I/O(輸入輸出接口)資源,同時可以通過軟件模擬SPI的方式來自由地使用任意I/O進行通信。因為只需顯示,所以只用向屏幕寫入數據,4 線制SPI 寫時序如圖4 所示。

圖4 LCD 的SPI 寫時序圖
每次寫入時需要將CS 片選引腳拉低,然后將數據引腳SDA 設置為要發送的字節的每位的高低電平,然后將時鐘引腳SCL 時鐘先設為低電平再設為高電平,這樣SDA 就會在SCL 時鐘的上升沿被采樣從而將該位電平發送出去,依次發送8 位就剛好完成1 個字節的發送。另外,在發送字節時還需要設置D/CX 引腳的高低電平,因為芯片會在SCL 的第8 個上升沿對D/CX引腳電平進行采樣,從而確定寫入的是數據還是命令。
由于LCD 的屏幕尺寸較小,所以也考慮了引入大尺寸的屏幕來同時進行ECG 和PPG 波形的監測,而且也便于觀察波形細節。這里采用LabVIEW 設計了一款PC 端上位機軟件,可以實時接收STM32 從串口發送來的數據包并進行解析與顯示。這里選用STM32 的通用同步異步收發器USART1 作為串口,其波特率可以通過波特比率寄存器BRR 進行配置,而通過配置控制寄存器CR1 的PCE 檢驗控制使能位和M 字長位以及CR2 的停止位,可將USART1 設置為無校驗、8 位數據位、1 位停止位,然后使能USART1。另外,需要使能發送和接收。發送一幀數據(一個字節)時,需要向數據寄存器DR 寫入數據,在硬件上實際是數據被送到發送數據寄存器TDR 或者直接送到移位寄存器,當1 幀數據發送完成后狀態寄存器SR 的TC 傳輸完成標志位被置1,通過讀一次SR 寄存器和寫一次DR 寄存器來清除TC 位并同時寫入下一幀。當一個字符被接收時,SR 寄存器的讀數據寄存器非空RXNE 位被硬件置1,通過使能RXNE 中斷來及時讀取數據。
在LCD 或上位機進行顯示的時候涉及CPU 對LCD 的頻繁寫操作或者向串口連續收發數據的操作,為了避免還未讀取處理的數據被后續DMA 中斷送來的新數據覆蓋,同樣也需要設置緩沖區。這里通過緩沖數組和讀、寫雙指針的交替移動來實現先進先出環形緩沖區FIFO 的設計[5-6],如圖5 所示。讀、寫指針一開始都是緩沖數組的基地址,DMA 每次中斷處理時就進行寫指針的自增,并根據指針地址進行緩沖數組新數據的填充,如果指針超過數組大小就回到數組開頭的基地址,如此循環反復,構成了一個環形緩沖區。讀指針也是如此,當LCD 和上位機每次取數據時,讀指針根據讀取數據的數量進行移動。因此,緩沖區中讀指針和寫指針之間的數據就是待讀取的新數據,而2 個指針重合則表明暫時沒有有效的數據可讀取,等待DMA 中斷填充新的有效數據。

圖5 緩沖數組模擬環形緩沖區讀寫示意圖
ECG 或PPG 波形數據在LCD 顯示的時候需要進行刷新作畫,這里選擇波形從右往左的滾動刷新方式。由于軟件模擬SPI 的速率不是太高,為了保證刷新的流暢性,在DMA 中斷里除了滑動平均濾波外,還進行了簡單的平均濾波,即將100 個新的信號點每隔10 個點求平均值,這樣在濾除噪聲且基本保留波形變化趨勢的情況下,LCD 每次需要刷新的點數就降低到了10 個。每次刷新前類似于滑動窗口的思想,存放屏幕波形數據的舊數組(大小等于屏幕分辨率240)會集體左移10 個位置,新的10 個數據被放到數組最后面產生新的波形數組。刷新時會從左到右逐點擦除舊的波形點連線,同時每擦除一條連線就在同樣位置畫新數組2 個信號點的連線,這種方式有利于顯示幀的平滑過渡,即使在刷新幀數較低時人眼也不會感覺到波形平移的明顯卡頓。LCD 波形監測界面如圖6 所示。

圖6 LCD 波形監測界面
LabVIEW 上位機的前面板如圖7 所示,程序流程如圖8 所示。程序主體是個狀態機,本質上是包含在while 循環結構內的條件結構,通過枚舉類型條件和移位寄存器進行各個狀態的跳轉。程序運行時,首先在“init”分支里對一些變量進行初始化,然后進入最主要的“wait”分支,通過事件結構進行各類事件的檢測,比如檢測到串口操作按鈕開啟時就打開相應的串口,并且將數據位、停止位、奇偶校驗進行與STM32 的串口同樣的配置,通過下拉列表選擇相對應的波特率。另外還有保存圖像、退出程序等事件。當“wait”分支沒有檢測到事件時就會跳轉“send”分支,如果“開始采集”按鈕開啟即上位機處于采集狀態且布爾型變量“處理完成標志位”為真表明當前數據已處理顯示完畢,此時會向STM32 發送一個特定命令字節,表示準備好接收下一批數據,STM32 的串口中斷檢測到命令后就會讀取環形緩沖區中的有效數據并發送給上位機;如果不滿足條件,程序就會跳回“wait”分支繼續進行事件檢測。

圖7 LabVIEW 上位機波形監測界面

圖8 LabVIEW 上位機程序流程圖
在成功向STM32 串口發送了讀取命令后程序就會跳轉到“getdata”分支,對串口接收的字節數進行判斷,如果數量達到規定的數據包字節數就表示接收完畢,進入下個分支“deal”進行數據處理顯示,否則回到“wait”分支繼續進行等待。在“deal”分支中,首先是根據協議對接收的數據包進行字節的拆分與合并,從而提取波形采樣值、心率及其生理參數;其次將這些信息保存為CSV 文件,同時利用波形圖表進行ECG 和PPG 的波形滾動顯示,另外在前面板里還顯示了心率(BPM)和心跳周期(IBI)。
人們對日常健康的監測需求愈加強烈,而類似STM32 這樣低成本、低功耗的MCU(微控制單元)芯片非常適合用在可穿戴設備或其它醫療電子設備,能夠使人們隨時隨地監測自己的生理狀態。本文提出了一種基于STM32 的ECG 和PPG 監測方案,能夠方便實時地監測ECG 或PPG 波形,另外除了LCD 式的便攜監測方案外,還演示了使用PC 等大屏設備進行多個波形及波形細節與生理特征的監視,為類似醫院的心電圖機、血氧儀等設備提供了一種簡便的替代思路。最后,本文對方案的整體流程及具體算法都進行了詳細討論,為此類裝置從理論向實踐的轉化提供了一個較好的示例。