1. 程式人生 > >MAX30100心率血氧模組(一)

MAX30100心率血氧模組(一)

組成

有兩個發光二極體,一個光檢測器,優化光學和低噪聲的模擬訊號處理,以檢測脈搏血氧飽和度和心臟速率訊號。

工作原理

只需要將手指頭緊貼在感測器上,就能估計 脈搏血氧飽和度(SpO2)及脈搏(相當於心跳)。
攜帶氧氣的紅血球能吸收較多紅外光(850-1000nm),未攜帶氧氣的紅血球則是吸收較多的紅光(600-750nm),
因此pulse oximeter就是一個迷你的分光計,利用不同紅血球之吸收光譜的原理,來分析血氧飽和度。
這種實時而快速的測量方式,也廣泛被運用在許多臨床的參考

如何使用

這個好像可以使用模擬IIC來讀取資料,那如何連線引腳

引腳定義

引腳連線

給了51的程式碼,但是用的是STM32,還是HAL庫,不能直接用的,還是得自己寫,不過可以知道引腳是怎麼連的
    // 1:VCC   --〉   1.8V-5.5V電源 
    // 2:SCL   --〉   P3.5
    // 3:SDA   --〉   P3.7
    // 4:INT   --〉   NC
    // 5:IRD   --〉   NC
    // 6:RD    --〉   NC              //NC指的是不連線,不用接地也不用去管,可能有內部連線
    // 7:GND   --〉   地

    對應的IIC介面
        //定義IIC介面
        sbit IIC_SCL    =P3^5;     //IIC的SCL
        sbit IIC_SDA    =P3^7;     //IIC的SDA
        bit  IIC_ACK;              //IIC的ACK
        int  rda;                  //IIC讀出
    這樣看用四根線就可以了,分別是VCC,GND和IIC用的SCL和SDA

IIC工作原理簡單介紹

序列匯流排
    一個數據線SDA
    一個時鐘線SCL
I2C匯流排通過上拉電阻接正電源
    匯流排空閒時,兩根線都是高電平
        當總線上的任一器件輸出的低電平,都將使匯流排的訊號變低,成線"與"關係

 I2C有三種狀態訊號:開始訊號、結束訊號和應答訊號

    開始訊號:SCL為高電平時,SDA由高電平轉變為低電平跳變,表示開始通訊。
    結束訊號:SCL為高電平時,SDA由低電平轉變為高電平跳變,結束結束通訊。
    應答訊號:接收資料的IC在接收到一個位元組資料後,向傳送資料的IC發出特定的低電平脈衝,表示已收到資料。
在資料傳輸過程中,SCL時鐘為主裝置控制,SCL為高的時候讀取資料SDA的資料,
    SCL為低的時候,主裝置改變SDA的資料準備傳輸下一位。
        資料從高位開始傳輸,當傳輸8位後,主裝置會釋放SDA匯流排。
            如果從裝置正確接收到資料,則從裝置會拉低SDA匯流排,則產生一個應答訊號。
            如果從裝置出錯,不拉低SDA匯流排,由於上拉電阻的作用,SDA的電平會變為高電平,即為非應答訊號。
資料傳輸總是以開始訊號開始傳輸,以結束訊號終止傳輸,中間可以傳輸多個位元組的資料。

IIC操作暫存器步驟

讀暫存器操作
    1) 傳送起始訊號
    2) 傳送 I2C 寫器件地址
    3) 等待應答
    4) 傳送 I2C 要讀的暫存器地址
    5) 等待應答
    6) 傳送起始訊號
    7) 傳送 I2C 讀器件地址
    8) 等待應答
    9) 接收返回資料
    10) 傳送結束訊號
讀暫存器操作程式碼實現
        IIC_Start();
        IIC_SendData(ADX345_ADDR);    //24C02дµØÖ·
        if(IIC_WaitAck())
        {
            return 0xFF;
        }
        IIC_SendData(0x32);           //·¢ËͶÁµØÖ·£¨XÖáÊ×µØÖ·£©
        if(IIC_WaitAck())
        {
            return 0xFF;
        }

        IIC_Start();
        IIC_SendData(ADX345_ADDR + 1); //24C02¶ÁµØÖ·
        if(IIC_WaitAck())
        {
            return 0xFF;       
        }

        /* ¶ÁÈ¡Áù¸ö×Ö½ÚÊý¾Ý */
        for(i=0; i<6; i++)
        {

            if(i == 5)        //½ÓÊÕ×îºóÒ»¸ö×Ö½Úʱ£¬·¢ËÍNACK
            {
                readValue[i] = IIC_ReceiveData(0);
            }
            else             //·¢ËͽÓÊÕºóÓ¦´ð
            {
                readValue[i] = IIC_ReceiveData(1); 
            }
        }
        IIC_Stop();
詳細解釋
    IIC_WaitAck()        等待應答函式
        其實就是控制IIC上SDA和SCL兩條線上高低電平的變化
            那麼如何控制?
                #define IIC_SDA_SET {GPIOB->BSRR = 1 << 11;}
                #define IIC_SDA_CLR {GPIOB->BRR = 1 << 11;}
                #define IIC_SCL_SET {GPIOB->BSRR = 1 << 10;}
                #define IIC_SCL_CLR {GPIOB->BRR = 1 << 10;}
    IIC_ReceiveData       IIC接收一個8位資料,但是有引數,那引數是什麼意思呢?
        引數為0,不應答
        引數為1,應答
        那怎麼應答呢?
            應答函式
                static void IIC_SendAck(void)
                {   
                    IIC_SCL_CLR;
                    IIC_SDA_OUT();

                    IIC_SDA_CLR;
                        HAL_Delay(2/1000);
                    //IIC_DelayUs(2);
                    IIC_SCL_SET;
                        HAL_Delay(2/1000);
                    //IIC_DelayUs(2);
                    IIC_SCL_CLR;        
                }
            不應答函式
                static void IIC_NoAck(void)
                {   
                    IIC_SCL_CLR;
                    IIC_SDA_OUT();

                    IIC_SDA_SET;
                        HAL_Delay(2/1000);
                    //IIC_DelayUs(2);
                    IIC_SCL_SET;
                        HAL_Delay(2/1000);
                    //IIC_DelayUs(2);
                    IIC_SCL_CLR;        
                }
            兩個函式的區別就在於在IIC_SDA_OUT();之後,應答要IIC_SDA_CLR;,不應答要IIC_SDA_SET;

寫暫存器操作
    1) 傳送起始訊號
    2) 傳送 I2C 寫器件地址
    3) 等待應答
    4) 傳送要寫入的暫存器地址
    5) 等待應答
    6) 傳送要寫入的資料
    7) 等待應答
    8) 傳送結束訊號
好像就是使用了傳送輸出函式和在初始化函式中涉及到了IIC操作

基本流程是使用IIC來讀出資料,好像MAX30100採集到的不同資料放到了不同的暫存器裡面,得知道哪個暫存器放了什麼?

這樣就可以根據暫存器中的資料進行計算了,因為給出的51樣例只給出了一個放溫度的暫存器的地址

那麼怎麼知道其他有用的資料放到哪個暫存器呢?怎麼使用這些資料得出心率和血氧呢?

先看看資料手冊吧,下面是晶片邏輯圖

細節描述是這樣說的:

The MAX30100 is fully configurable through software registers, and the digital output data is stored in a 16-deep FIFO within the device. The FIFO allows the MAX30100 to be connected to a microcontroller or microprocessor on a shared bus, where the data is not being read continuously from the device’s registers.

數字輸出資料放到了一個16個深度(表示可以放16個血氧飽和度通道資料樣品)的先進先出佇列裡,這個先進先出的方式允許了MAX30100在總線上和MCU連線,而且資料不會被從暫存器連續讀取(這個結合IIC的操作暫存器的方式可以理解)

一般示例程式碼中都是把溫度讀了出來,那麼這個溫度有什麼用呢?

The SpO2 algorithm is relatively insensitive to the wavelength of the IR LED, but the red LED’s wavelength is critical to correct interpretation of the data. The temperature sensor data can be used to compensate the SpO2 error with ambient temperature changes

血氧飽和度演算法對 IR LED不敏感,但是red LED對正確獲取資料很關鍵,溫度感測器資料可以用來矯正由於環境溫度變化產生的誤差。

那怎麼知道那個暫存器中放著什麼資料呢?

給出的MAX301002的讀取溫度的示例 temp_num = max30102_Bus_Read(0x1f); 暫存器地址是0x1f,檢視MAX301002的資料手冊,其實有一個表記錄了每個暫存器的作用和地址,如下圖

紅色方框中就是儲存溫度的暫存器,其地址為0x1F

這樣的話,對於MAX30100,那麼其溫度暫存器的地址也可以確定了

現在的問題就是從暫存器裡面讀出資料然後計算了

建立工程實現讀取暫存器資料計算心率血氧

主要檔案是模擬IIC,使用IIC讀取特定暫存器中的資料進行處理就可以獲得心率血氧。
先寫模擬IIC的檔案,能實現IIC初始化,開始結束,讀取和寫入以及傳送應答訊號的功能。
使用STM32CUBEMX配置IIC是需要配置clock speed,有兩種模式,最快的模式為400KHZ,但在實際使用中需要自己寫模擬IIC檔案,也用不到這個IIC,所以可以不用配置

上面是使用軟體模擬IIC,但是HAL庫本身就是提供了IIC操作函式的,而且是硬體IIC,可以使用HAL庫的IIC方法,操作應該會更簡單。

【注意】

SCL和SDA加上拉電阻的問題
    逛論壇的時候說SCL和SDA要加4.7k的上拉電阻,datasheet上也說要加,看了看原理圖,SCL和SDA都加了一個472貼片電阻,這個472指的是47*10^2,正好是4.7k的電阻,所以不用擔心燒壞了。