打印
[活动专区]

【AT-START-F423测评】6.模拟I2C读取BMP280大气压和温度

[复制链接]
1369|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
yuyy1989|  楼主 | 2023-10-28 22:30 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
#申请原创# @21小跑堂  
BMP280是博世最推出的数字气压传感器,可以测量气压和温度,支持SPI和I2C通信接口,这里使用I2C来通讯

VCC:3.3V供电:
GND
SCL:时钟信号
SDA:I2C通信模式数据信号,SPI模式模块数据输入
CSB:通信模式选择,高电平I2C,低电平SPI,模块通过电阻上拉默认I2C模式
SDO:I2C通信模式下为传感器地址控制位,接GND的时候器件地址为0x76,接高电平为0x77,模块通过电阻下拉,SPI模式下为模块数据输出

I2C需要时钟线和数据线进行双向通讯,GPIO使用开漏模式

定义GPIO操作中间层
void yuyy_gpio_setlev(YUYY_GPIO_DEV_t *gpio_dev,YUYY_GPIO_LEV_TYPE lev)
{
    gpio_bits_write(gpio_dev->gpio,gpio_dev->pin,lev);
}
YUYY_GPIO_LEV_TYPE yuyy_gpio_getlev(YUYY_GPIO_DEV_t *gpio_dev)
{
     return gpio_input_data_bit_read(gpio_dev->gpio,gpio_dev->pin);
}
void yuyy_gpio_opod_out(YUYY_GPIO_DEV_t *gpio_dev)
{
   
}
void yuyy_gpio_opod_in(YUYY_GPIO_DEV_t *gpio_dev)
{
    gpio_bits_write(gpio_dev->gpio,gpio_dev->pin,YUYY_GPIO_LEV1);
}
实现SCL和SDA操作方法
void yuyy_soft_iic_sdain(YUYY_SOFT_IIC_DEV_t *iicx)
{
    yuyy_gpio_opod_in(&(iicx->sda));
}
void yuyy_soft_iic_sdaout(YUYY_SOFT_IIC_DEV_t *iicx)
{
    yuyy_gpio_opod_out(&(iicx->sda));
}
void yuyy_soft_iic_sdalev(YUYY_SOFT_IIC_DEV_t *iicx,YUYY_GPIO_LEV_TYPE lev)
{
    yuyy_gpio_setlev(&(iicx->sda),lev);
}
YUYY_GPIO_LEV_TYPE yuyy_soft_iic_sdaread(YUYY_SOFT_IIC_DEV_t *iicx)
{
    return yuyy_gpio_readlev(&(iicx->sda));
}
void yuyy_soft_iic_sclin(YUYY_SOFT_IIC_DEV_t *iicx)
{
    yuyy_gpio_opod_in(&(iicx->scl));
}
void yuyy_soft_iic_sclout(YUYY_SOFT_IIC_DEV_t *iicx)
{
    yuyy_gpio_opod_out(&(iicx->scl));
}
void yuyy_soft_iic_scllev(YUYY_SOFT_IIC_DEV_t *iicx,YUYY_GPIO_LEV_TYPE lev)
{
    yuyy_gpio_setlev(&(iicx->scl),lev);
}
YUYY_GPIO_LEV_TYPE yuyy_soft_iic_sclread(YUYY_SOFT_IIC_DEV_t *iicx)
{
    return yuyy_gpio_readlev(&(iicx->scl));
}
之后按照I2C通讯逻辑实现I2C读写
uint8_t yuyy_soft_iic_start(YUYY_SOFT_IIC_DEV_t *iicx)
{
    yuyy_soft_iic_sdaout(iicx);
    yuyy_soft_iic_sclout(iicx);
    yuyy_soft_iic_sdalev(iicx,YUYY_GPIO_LEV1);
    yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV1);
    yuyy_soft_iic_sclin(iicx);
    if(yuyy_soft_iic_waitscl_timeout(iicx,YUYY_GPIO_LEV1))
        return 1;

    yuyy_soft_iic_sclout(iicx);
    yuyy_soft_iic_delay();
    yuyy_soft_iic_sdalev(iicx,YUYY_GPIO_LEV0);
    yuyy_soft_iic_delay();
    yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV0);
    yuyy_soft_iic_delay();
    return YUYY_SOFT_IIC_OK;
}

uint8_t yuyy_soft_iic_stop(YUYY_SOFT_IIC_DEV_t *iicx)
{
    yuyy_soft_iic_sdaout(iicx);
    yuyy_soft_iic_sclout(iicx);
    yuyy_soft_iic_sdalev(iicx,YUYY_GPIO_LEV0);
    yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV1);
    yuyy_soft_iic_sclin(iicx);
    if(yuyy_soft_iic_waitscl_timeout(iicx,YUYY_GPIO_LEV1))
        return 1;

    yuyy_soft_iic_sclout(iicx);
    yuyy_soft_iic_delay();
    yuyy_soft_iic_sdalev(iicx,YUYY_GPIO_LEV1);
    return YUYY_SOFT_IIC_OK;
}

uint8_t yuyy_soft_iic_readack(YUYY_SOFT_IIC_DEV_t *iicx)
{
    uint8_t i=0,ack=YUYY_SOFT_IIC_ACK;
    yuyy_soft_iic_sdain(iicx);
    yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV1);
    yuyy_soft_iic_sclin(iicx);
    if(yuyy_soft_iic_waitscl_timeout(iicx,YUYY_GPIO_LEV1))
        return 1;
   
    yuyy_soft_iic_sclout(iicx);
    yuyy_soft_iic_delay();
    while(yuyy_soft_iic_sdaread(iicx)!=YUYY_GPIO_LEV0 && i<10)
    {
        yuyy_soft_iic_delay();
        i += 1;
    }
    if(i>8)
        ack = YUYY_SOFT_IIC_NACK;
    yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV0);
    yuyy_soft_iic_delay();
    return ack;
}

uint8_t yuyy_soft_iic_sendack(YUYY_SOFT_IIC_DEV_t *iicx,uint8_t ack)
{
    yuyy_soft_iic_sdaout(iicx);
    if(ack == YUYY_SOFT_IIC_ACK)
        yuyy_soft_iic_sdalev(iicx,YUYY_GPIO_LEV0);
    else
        yuyy_soft_iic_sdalev(iicx,YUYY_GPIO_LEV1);
    yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV1);
    yuyy_soft_iic_sclin(iicx);
    if(yuyy_soft_iic_waitscl_timeout(iicx,YUYY_GPIO_LEV1))
        return 1;
   
    yuyy_soft_iic_sclout(iicx);
    yuyy_soft_iic_delay();
    yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV0);
    yuyy_soft_iic_delay();
    return YUYY_SOFT_IIC_OK;
}

uint8_t yuyy_soft_iic_sendbyte(YUYY_SOFT_IIC_DEV_t *iicx,uint8_t dat)
{
    uint8_t i = 0;
    yuyy_soft_iic_sdaout(iicx);
    while(i<8)
    {
        if(dat & 0x80)
            yuyy_soft_iic_sdalev(iicx,YUYY_GPIO_LEV1);
        else
            yuyy_soft_iic_sdalev(iicx,YUYY_GPIO_LEV0);
        yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV1);
        yuyy_soft_iic_sclin(iicx);
        if(yuyy_soft_iic_waitscl_timeout(iicx,YUYY_GPIO_LEV1))
            return 1;
        
        yuyy_soft_iic_sclout(iicx);
        yuyy_soft_iic_delay();
        yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV0);
        yuyy_soft_iic_delay();
        dat = dat << 1;
        i += 1;
    }
    return YUYY_SOFT_IIC_OK;
}

uint8_t yuyy_soft_iic_readbyte(YUYY_SOFT_IIC_DEV_t *iicx,uint8_t *dat)
{
    uint8_t i = 0;
    *dat = 0;
    yuyy_soft_iic_sdain(iicx);
    while(i<8)
    {
        yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV1);
        yuyy_soft_iic_sclin(iicx);
        if(yuyy_soft_iic_waitscl_timeout(iicx,YUYY_GPIO_LEV1))
            return 1;
        
        yuyy_soft_iic_sclout(iicx);
        yuyy_soft_iic_delay();
        *dat = *dat << 1;
        if(yuyy_soft_iic_sdaread(iicx) == YUYY_GPIO_LEV1)
            *dat |= 0x01;
        yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV0);
        yuyy_soft_iic_delay();
        i += 1;
    }
    return YUYY_SOFT_IIC_OK;
}
BMP280手册提供的 参考代码

代码实现
uint8_t yuyy_bmp280_writereg(YUYY_BMP280_DEV_t *bmp280_dev,uint8_t reg,uint8_t dat)
{
    uint8_t result = 0;
    if(bmp280_dev->wiretype == YUYY_BMP280_WIRE_IIC)
        result = bmp280_dev->iic_senddatas_func(bmp280_dev->iicx,BMP280_IIC_ADDR+bmp280_dev->addrlastbit,reg,1,&dat,1);
    return result;
}

uint8_t yuyy_bmp280_readdatas(YUYY_BMP280_DEV_t *bmp280_dev,uint8_t reg,uint8_t *datas,uint8_t len)
{
    uint8_t result = 0;
    if(bmp280_dev->wiretype == YUYY_BMP280_WIRE_IIC)
        result = bmp280_dev->iic_readdatas_func(bmp280_dev->iicx,BMP280_IIC_ADDR,reg,1,datas,len);

    return result;
}

uint8_t yuyy_bmp280_read1byte(YUYY_BMP280_DEV_t *bmp280_dev,uint8_t reg)
{
    uint8_t dat;
    yuyy_bmp280_readdatas(bmp280_dev,reg,&dat,1);
    return dat;
}

uint16_t yuyy_bmp280_read2byte(YUYY_BMP280_DEV_t *bmp280_dev,uint8_t reg,uint8_t le)
{
    uint8_t datas[2];
    yuyy_bmp280_readdatas(bmp280_dev,reg,datas,2);
    if(le > 0)
        return (datas[1]<<8)|datas[0];
    return (datas[0]<<8)|datas[1];
}

void yuyy_bmp280_readCoefficients(YUYY_BMP280_DEV_t *bmp280_dev)
{
    bmp280_calib.dig_T1 = yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_T1,1);
    bmp280_calib.dig_T2 = (int16_t)yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_T2,1);
    bmp280_calib.dig_T3 = (int16_t)yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_T3,1);

    bmp280_calib.dig_P1 = yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_P1,1);
    bmp280_calib.dig_P2 = (int16_t)yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_P2,1);
    bmp280_calib.dig_P3 = (int16_t)yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_P3,1);
    bmp280_calib.dig_P4 = (int16_t)yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_P4,1);
    bmp280_calib.dig_P5 = (int16_t)yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_P5,1);
    bmp280_calib.dig_P6 = (int16_t)yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_P6,1);
    bmp280_calib.dig_P7 = (int16_t)yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_P7,1);
    bmp280_calib.dig_P8 = (int16_t)yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_P8,1);
    bmp280_calib.dig_P9 = (int16_t)yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_P9,1);
}

float yuyy_bmp280_readtemp(YUYY_BMP280_DEV_t *bmp280_dev)
{
    int32_t var1, var2;
    float T;
    int32_t adc_T = yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_TEMPDATA,0);
    adc_T <<= 8;
    adc_T |= yuyy_bmp280_read1byte(bmp280_dev,BMP280_REGISTER_TEMPDATA+2);
    adc_T >>= 4;

    var1  = ((((adc_T>>3) - ((int32_t)bmp280_calib.dig_T1 <<1))) * ((int32_t)bmp280_calib.dig_T2)) >> 11;

    var2  = (((((adc_T>>4) - ((int32_t)bmp280_calib.dig_T1)) * ((adc_T>>4) - ((int32_t)bmp280_calib.dig_T1))) >> 12) * ((int32_t)bmp280_calib.dig_T3)) >> 14;

    t_fine = var1 + var2;

    T  = (t_fine * 5 + 128) >> 8;
    return T/100;
}
float yuyy_bmp280_readpress(YUYY_BMP280_DEV_t *bmp280_dev)
{
    int64_t var1, var2, p;
    int32_t adc_P = yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_PRESSUREDATA,0);
    adc_P <<= 8;
    adc_P |= yuyy_bmp280_read1byte(bmp280_dev,BMP280_REGISTER_PRESSUREDATA+2);
    adc_P >>= 4;

    var1 = ((int64_t)t_fine) - 128000;
    var2 = var1 * var1 * (int64_t)bmp280_calib.dig_P6;
    var2 = var2 + ((var1*(int64_t)bmp280_calib.dig_P5)<<17);
    var2 = var2 + (((int64_t)bmp280_calib.dig_P4)<<35);
    var1 = ((var1 * var1 * (int64_t)bmp280_calib.dig_P3)>>8) + ((var1 * (int64_t)bmp280_calib.dig_P2)<<12);
    var1 = (((((int64_t)1)<<47)+var1))*((int64_t)bmp280_calib.dig_P1)>>33;

    if (var1 == 0) {
        return 0;  // avoid exception caused by division by zero
    }
    p = 1048576 - adc_P;
    p = (((p<<31) - var2)*3125) / var1;
    var1 = (((int64_t)bmp280_calib.dig_P9) * (p>>13) * (p>>13)) >> 25;
    var2 = (((int64_t)bmp280_calib.dig_P8) * p) >> 19;

    p = ((p + var1 + var2) >> 8) + (((int64_t)bmp280_calib.dig_P7)<<4);
    return (float)p/256;
}

初始化代码,将读到的气压和温度通过printf打印
YUYY_SOFT_IIC_DEV_t siic_dev;
YUYY_BMP280_DEV_t bmp280_dev;
void bmp280_init()
{
    siic_dev.scl.gpio = SIIC_SCL_GPIO_PORT;
    siic_dev.scl.pin = SIIC_SCL_PIN;
    siic_dev.sda.gpio = SIIC_SDA_GPIO_PORT;
    siic_dev.sda.pin = SIIC_SDA_PIN;
    yuyy_soft_iic_init(&siic_dev);
    bmp280_dev.iicx = &siic_dev;
    bmp280_dev.wiretype = YUYY_BMP280_WIRE_IIC;
    bmp280_dev.iic_readdatas_func = (yuyy_iic_readdatas_func_t)yuyy_soft_iic_readdatas;
    bmp280_dev.iic_senddatas_func = (yuyy_iic_senddatas_func_t)yuyy_soft_iic_senddatas;
    yuyy_bmp280_init(&bmp280_dev);
    yuyy_bmp280_setctrlmeas(&bmp280_dev,0x3F);
}

void bmp280_readpress()
{
    float temp,press;
    temp = yuyy_bmp280_readtemp(&bmp280_dev);
    press = yuyy_bmp280_readpress(&bmp280_dev);
    printf("BMP280 读取温度:%.1f℃ 压力:%.1fpa",temp,press);
}
运行效果




使用特权

评论回复
沙发
单片小菜| | 2023-11-1 10:10 | 只看该作者
这个小模块,在哪里买的?

使用特权

评论回复
板凳
yuyy1989|  楼主 | 2023-11-1 10:57 | 只看该作者
单片小菜 发表于 2023-11-1 10:10
这个小模块,在哪里买的?

淘宝

使用特权

评论回复
地板
lajfda003| | 2023-11-1 11:14 | 只看该作者
这个小模块多少钱?

使用特权

评论回复
5
yuyy1989|  楼主 | 2023-11-1 11:23 | 只看该作者
lajfda003 发表于 2023-11-1 11:14
这个小模块多少钱?

淘宝上3块多

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

143

主题

688

帖子

6

粉丝