加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長期合作伙伴
立即加入
  • 正文
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

【CW32模塊使用】MS5611氣壓傳感器

11/15 08:45
787
閱讀需 27 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

模塊來源

資料下載鏈接:https://pan.baidu.com/s/1QOrpiggCE6mBpqabJXUufg

提取碼:c2pp

規(guī)格參數(shù)

工作電壓:1.8~3.6V

工作電流:0.25~23uA

溫度精度:0.8℃

溫度范圍:-40~85℃

氣壓范圍:10~1200 mbar

氣壓精度:1.5 mbar

輸出方式: IIC

管腳數(shù)量:3 Pin

以上信息見廠家資料文件

移植過程

我們的目標(biāo)是將例程移植至CW32F030C8T6開發(fā)板上【能夠測量環(huán)境氣壓】。首先要獲取資料,查看數(shù)據(jù)手冊(cè)應(yīng)如何實(shí)現(xiàn)讀取數(shù)據(jù),再移植至我們的工程。

3.1查看資料

當(dāng)PS引腳高電平時(shí),傳感器屬于IIC模式;當(dāng)PS引腳接低電平時(shí),傳感器屬于SPI模式;在原理圖上,PS引腳通過上拉電阻接了高電平,故默認(rèn)為IIC模式。

器件地址 = 0XEE

CSB的反補(bǔ)碼 即CSB引腳接高電平時(shí), 地址為 1110 110+(讀寫位)

CSB的反補(bǔ)碼 即CSB引腳接低電平時(shí), 地址為 1110 111+(讀寫位)

讀取氣壓與溫度的流程:開始-> 讀取出廠校準(zhǔn)值C1至C6 -> 讀取氣壓D1和溫度D2的原始數(shù)據(jù) -> 將D2和C1C6帶入公式求出dT和TEMP,其中TEMP為溫度數(shù)據(jù)-> 將dT和C1至C6帶入公式求出OFF、SENS和P,其中P為氣壓數(shù)據(jù)。

3.2引腳選擇

模塊接線圖

3.3移植至工程

移植步驟中的導(dǎo)入.c和.h文件與【CW32模塊使用】DHT11溫濕度傳感器相同,只是將.c和.h文件更改為bsp_ms5611.c與bsp_ms5611.h。這里不再過多講述,移植完成后面修改相關(guān)代碼。

在文件bsp_ms5611.c中,編寫如下代碼。

/* * Change Logs: * Date           Author       Notes * 2024-06-20     LCKFB-LP    first version */
#include "bsp_ms5611.h"#include "stdio.h"#include "board.h"
//出廠校準(zhǔn)值//Cal_C1_6[0]                                 = 廠家信息//Cal_C1_6[1] ~ Cal_C1_6[6] = 校準(zhǔn)值//Cal_C1_6[7]                                 = 校準(zhǔn)值的CRC校驗(yàn)uint16_t Cal_C1_6[8];

/****************************************************************** * 函 數(shù) 名 稱:MS5611_GPIO_Init * 函 數(shù) 說 明:MS5611的引腳初始化 * 函 數(shù) 形 參:無 * 函 數(shù) 返 回:無 * 作       者:LC * 備       注:無******************************************************************/void MS5611_GPIO_Init(void){    GPIO_InitTypeDef GPIO_InitStruct; // GPIO初始化結(jié)構(gòu)體
    RCC_MS5611_ENBALE();        // 使能GPIO時(shí)鐘
    GPIO_InitStruct.Pins = GPIO_SDA|GPIO_SCL;   // GPIO引腳    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; // 開漏輸出    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;    // 輸出速度高    GPIO_Init(PORT_MS5611, &GPIO_InitStruct);   // 初始化}

/****************************************************************** * 函 數(shù) 名 稱:IIC_Start * 函 數(shù) 說 明:IIC起始時(shí)序 * 函 數(shù) 形 參:無 * 函 數(shù) 返 回:無 * 作       者:LC * 備       注:無******************************************************************/void IIC_Start(void){        SDA_OUT();
        SDA(1);        delay_us(5);        SCL(1);        delay_us(5);
        SDA(0);        delay_us(5);        SCL(0);        delay_us(5);
}/****************************************************************** * 函 數(shù) 名 稱:IIC_Stop * 函 數(shù) 說 明:IIC停止信號(hào) * 函 數(shù) 形 參:無 * 函 數(shù) 返 回:無 * 作       者:LC * 備       注:無******************************************************************/void IIC_Stop(void){        SDA_OUT();        SCL(0);        SDA(0);
        SCL(1);        delay_us(5);        SDA(1);        delay_us(5);
}
/****************************************************************** * 函 數(shù) 名 稱:IIC_Send_Ack * 函 數(shù) 說 明:主機(jī)發(fā)送應(yīng)答或者非應(yīng)答信號(hào) * 函 數(shù) 形 參:0發(fā)送應(yīng)答  1發(fā)送非應(yīng)答 * 函 數(shù) 返 回:無 * 作       者:LC * 備       注:無******************************************************************/void IIC_Send_Ack(unsigned char ack){        SDA_OUT();        SCL(0);        SDA(0);        delay_us(5);        if(!ack) SDA(0);        else         SDA(1);        SCL(1);        delay_us(5);        SCL(0);        SDA(1);}

/****************************************************************** * 函 數(shù) 名 稱:I2C_WaitAck * 函 數(shù) 說 明:等待從機(jī)應(yīng)答 * 函 數(shù) 形 參:無 * 函 數(shù) 返 回:0有應(yīng)答  1超時(shí)無應(yīng)答 * 作       者:LC * 備       注:無******************************************************************/unsigned char I2C_WaitAck(void){
        char ack = 0;        unsigned char ack_flag = 10;        SCL(0);        SDA(1);        SDA_IN();        delay_us(5);        SCL(1);        delay_us(5);
        while( (SDA_GET()==1) && ( ack_flag ) )        {                ack_flag--;                delay_us(5);        }
        if( ack_flag <= 0 )        {                IIC_Stop();                return 1;        }        else        {                SCL(0);                SDA_OUT();        }        return ack;}
/****************************************************************** * 函 數(shù) 名 稱:Send_Byte * 函 數(shù) 說 明:寫入一個(gè)字節(jié) * 函 數(shù) 形 參:dat要寫人的數(shù)據(jù) * 函 數(shù) 返 回:無 * 作       者:LC * 備       注:無******************************************************************/void Send_Byte(uint8_t dat){        int i = 0;        SDA_OUT();        SCL(0);//拉低時(shí)鐘開始數(shù)據(jù)傳輸
        for( i = 0; i < 8; i++ )        {                SDA( (dat & 0x80) >> 7 );                delay_us(1);                SCL(1);                delay_us(5);                SCL(0);                delay_us(5);                dat<<=1;        }}
/****************************************************************** * 函 數(shù) 名 稱:Read_Byte * 函 數(shù) 說 明:IIC讀時(shí)序 * 函 數(shù) 形 參:無 * 函 數(shù) 返 回:讀到的數(shù)據(jù) * 作       者:LC * 備       注:無******************************************************************/unsigned char Read_Byte(void){        unsigned char i,receive=0;        SDA_IN();//SDA設(shè)置為輸入        for(i=0;i<8;i++ )        {                SCL(0);                delay_us(5);                SCL(1);                delay_us(5);                receive<<=1;                if( SDA_GET() )                {                        receive|=1;                }                delay_us(5);        }        SCL(0);        return receive;}


/********************************************************** * 函 數(shù) 名 稱:MS5611_Reset * 函 數(shù) 功 能:MS5611的復(fù)位 * 傳 入 參 數(shù):無 * 函 數(shù) 返 回:0=復(fù)位成功  1=器件地址錯(cuò)誤  2=命令無應(yīng)答 * 作       者:LC * 備       注:無**********************************************************/char MS5611_Reset(void){        IIC_Start();//起始信號(hào)        Send_Byte(0xee|0); //器件地址+寫        if( I2C_WaitAck() == 1 )return 1;        Send_Byte(0x1e); //復(fù)位命令        if( I2C_WaitAck() == 1 )return 2;        IIC_Stop();        return 0;}

//C1-C6 16位  6個(gè)地址  每一個(gè)地址16位/********************************************************** * 函 數(shù) 名 稱:MS5611_Read_PROM * 函 數(shù) 功 能:讀取出廠校準(zhǔn)值 * 傳 入 參 數(shù):無 * 函 數(shù) 返 回:無 * 作       者:LC * 備       注:無**********************************************************/void MS5611_Read_PROM(void){        uint8_t data_H=0,data_L=0;        uint8_t i = 0;
        for( i = 0; i < 8; i++ )        {                IIC_Start();//起始信號(hào)                Send_Byte(0xee|0); //器件地址+寫                I2C_WaitAck();                Send_Byte( 0xA0 + i * 2 ); //寄存器地址                I2C_WaitAck();                IIC_Stop();
                delay_us(200);
                IIC_Start();//起始信號(hào)                Send_Byte(0xee|1); //器件地址+讀                I2C_WaitAck();
                data_H = Read_Byte();//讀取的數(shù)據(jù)高8位                IIC_Send_Ack(0);                data_L = Read_Byte();//讀取的數(shù)據(jù)低8位                IIC_Send_Ack(1);
                IIC_Stop();                //保存出廠校準(zhǔn)數(shù)據(jù)                Cal_C1_6[i] = (data_H<<8) | data_L;        }}

/********************************************************** * 函 數(shù) 名 稱:MS5611_Read_D1_D2 * 函 數(shù) 功 能:讀取氣壓D1和溫度D2的初始數(shù)據(jù) * 傳 入 參 數(shù):regaddr=0x48或0x58 * 函 數(shù) 返 回:返回讀取后整合為24位的數(shù)據(jù) * 作       者:LC * 備       注: *                                 regaddr= 0x48         讀取D1數(shù)據(jù)(OSR=4096) *                                 regaddr= 0x58         讀取D2數(shù)據(jù)(OSR=4096)**********************************************************/uint32_t MS5611_Read_D1_D2(uint8_t regaddr){        uint32_t dat = 0;        uint8_t buff[3] ={0};        IIC_Start();//起始信號(hào)        Send_Byte(0xee|0); //器件地址+寫        if( I2C_WaitAck() == 1 )printf("D1 NACK -1rn");        Send_Byte(regaddr); //OSR = 4096        if( I2C_WaitAck() == 1 )printf("D1 NACK -2rn");        IIC_Stop();
        delay_ms(10);
        IIC_Start();//起始信號(hào)        Send_Byte(0xee|0); //器件地址+寫        if( I2C_WaitAck() == 1 )printf("D1 NACK -3rn");        Send_Byte(0X00);        if( I2C_WaitAck() == 1 )printf("D1 NACK -4rn");        IIC_Stop();
        delay_ms(10);
        IIC_Start();//起始信號(hào)        Send_Byte(0xee|1); //器件地址+讀        if( I2C_WaitAck() == 1 )printf("D1 NACK -5rn");
        buff[0] = Read_Byte();        IIC_Send_Ack(0);        buff[1] = Read_Byte();        IIC_Send_Ack(0);        buff[2] = Read_Byte();        IIC_Send_Ack(1);        IIC_Stop();
        dat = (((buff[0]<<16) | ( buff[1]<<8)) | buff[2]);        return dat;}
uint32_t D1 = 0, D2 = 0, dT = 0;/********************************************************** * 函 數(shù) 名 稱:Get_TEMP * 函 數(shù) 功 能:換算溫度 * 傳 入 參 數(shù):無 * 函 數(shù) 返 回:沒有小數(shù)點(diǎn)后的溫度數(shù)據(jù) * 作       者:LC * 備       注:無**********************************************************/float Get_TEMP(void){        float dat = 0;        long long TEMP = 0;
        D1 = MS5611_Read_D1_D2(0x48);        delay_ms(10);        D2 = MS5611_Read_D1_D2(0x58);        delay_ms(10);
        dT = D2 - (Cal_C1_6[5] * 256.0);
        TEMP = 2000 + (((float)dT * Cal_C1_6[6]) / 8388608.0);
//        printf("temp = %lld%lld.%lld%lldrn",TEMP/1000, TEMP/100%10,TEMP/10%10,TEMP%10);
        //沒有小數(shù)的溫度        dat = (((TEMP/1000)*10) + (TEMP/100%10)) ;
        return dat;}
/********************************************************** * 函 數(shù) 名 稱:Get_pressure * 函 數(shù) 功 能:換算氣壓數(shù)據(jù) * 傳 入 參 數(shù):無 * 函 數(shù) 返 回:返回氣壓,單位(HPa) * 作       者:LC * 備       注:無**********************************************************/float Get_pressure(void){        long long SENS = 0;        long long P =0;        long long OFF = 0;
        Get_TEMP();
        OFF = Cal_C1_6[2] * 65536.0 + Cal_C1_6[4] * dT / 128;        SENS = (Cal_C1_6[1] * 32768.0) + ((Cal_C1_6[3] * dT ) / 256.0);
        P = (D1 * SENS / 2097152.0 - OFF) / 32768.0;
        return (P/100.0);}

在文件bsp_sht10.h中,編寫如下代碼。

/* * Change Logs: * Date           Author       Notes * 2024-06-20     LCKFB-LP    first version */
#ifndef _BSP_MS5611_H_#define _BSP_MS5611_H_
#include "board.h"

//端口移植#define RCC_MS5611_ENBALE()        __RCC_GPIOB_CLK_ENABLE()#define PORT_MS5611                CW_GPIOB

#define GPIO_SDA                   GPIO_PIN_9#define GPIO_SCL                   GPIO_PIN_8
//設(shè)置SDA輸出模式#define SDA_OUT()   {                                GPIO_InitTypeDef GPIO_InitStruct;                                        GPIO_InitStruct.Pins = GPIO_SDA;                                         GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;                              GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;                                 GPIO_Init(PORT_MS5611, &GPIO_InitStruct);                            }//設(shè)置SDA輸入模式#define SDA_IN()    {                                GPIO_InitTypeDef GPIO_InitStruct;                                        GPIO_InitStruct.Pins = GPIO_SDA;                                         GPIO_InitStruct.Mode = GPIO_MODE_INPUT;                                 GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;                                 GPIO_Init(PORT_MS5611, &GPIO_InitStruct);                           }//獲取SDA引腳的電平變化#define SDA_GET()       GPIO_ReadPin(PORT_MS5611, GPIO_SDA)//SDA與SCL輸出#define SDA(x)          GPIO_WritePin(PORT_MS5611, GPIO_SDA, (x?GPIO_Pin_SET:GPIO_Pin_RESET) )#define SCL(x)          GPIO_WritePin(PORT_MS5611, GPIO_SCL, (x?GPIO_Pin_SET:GPIO_Pin_RESET) )

void MS5611_GPIO_Init(void);char MS5611_Reset(void);void MS5611_Read_PROM(void);float Get_TEMP(void);float Get_pressure(void);
#endif

移植驗(yàn)證

在自己工程中的main主函數(shù)中,編寫如下。

/* * Change Logs: * Date           Author       Notes * 2024-06-20     LCKFB-LP    first version */#include "board.h"#include "stdio.h"#include "bsp_uart.h"#include "bsp_ms5611.h"
int32_t main(void){    board_init();        // 開發(fā)板初始化
    uart1_init(115200);        // 串口1波特率115200
    MS5611_GPIO_Init();
    MS5611_Reset();//器件復(fù)位
    delay_ms(300);//等待初始化完成;
    MS5611_Read_PROM();//讀取出廠校準(zhǔn)值    printf("startrn");    while(1)    {        //輸出溫度        printf("溫度 = %.0f℃rn",Get_TEMP() );        //輸出氣壓        printf("氣壓 = %.2fHParn",Get_pressure() );
        printf("n");        delay_ms(1000);
    }}

移植現(xiàn)象:每隔一秒左右測量一次溫度和氣壓。

模塊移植成功案例代碼:

鏈接:https://pan.baidu.com/s/1unyWALyDcHWy02K_Y77blQ?pwd=LCKF

提取碼:LCKF

相關(guān)推薦

電子產(chǎn)業(yè)圖譜

以開放、共享、互助為理念,致力于構(gòu)建武漢芯源半導(dǎo)體CW32系列MCU生態(tài)社區(qū)。無論是嵌入式MCU小自還是想要攻破技術(shù)難題的工程師,亦或是需求解決方案的產(chǎn)品經(jīng)理都可在CW32生態(tài)社區(qū)汲取營養(yǎng)、共同成長。

B站