[活动专区] 【AT-START-F423测评】6.模拟I2C读取BMP280大气压和温度

[复制链接]
 楼主| yuyy1989 发表于 2023-10-28 22:30 | 显示全部楼层 |阅读模式
<
#申请原创# @21小跑堂  
BMP280是博世最推出的数字气压传感器,可以测量气压和温度,支持SPI和I2C通信接口,这里使用I2C来通讯
微信图片_20231028215222.jpg 微信图片_20231028215230.jpg
VCC:3.3V供电:
GND
SCL:时钟信号
SDA:I2C通信模式数据信号,SPI模式模块数据输入
CSB:通信模式选择,高电平I2C,低电平SPI,模块通过电阻上拉默认I2C模式
SDO:I2C通信模式下为传感器地址控制位,接GND的时候器件地址为0x76,接高电平为0x77,模块通过电阻下拉,SPI模式下为模块数据输出

I2C需要时钟线和数据线进行双向通讯,GPIO使用开漏模式
QQ截图20231028214927.png
定义GPIO操作中间层
  1. void yuyy_gpio_setlev(YUYY_GPIO_DEV_t *gpio_dev,YUYY_GPIO_LEV_TYPE lev)
  2. {
  3.     gpio_bits_write(gpio_dev->gpio,gpio_dev->pin,lev);
  4. }
  5. YUYY_GPIO_LEV_TYPE yuyy_gpio_getlev(YUYY_GPIO_DEV_t *gpio_dev)
  6. {
  7.      return gpio_input_data_bit_read(gpio_dev->gpio,gpio_dev->pin);
  8. }
  9. void yuyy_gpio_opod_out(YUYY_GPIO_DEV_t *gpio_dev)
  10. {
  11.    
  12. }
  13. void yuyy_gpio_opod_in(YUYY_GPIO_DEV_t *gpio_dev)
  14. {
  15.     gpio_bits_write(gpio_dev->gpio,gpio_dev->pin,YUYY_GPIO_LEV1);
  16. }
实现SCL和SDA操作方法
  1. void yuyy_soft_iic_sdain(YUYY_SOFT_IIC_DEV_t *iicx)
  2. {
  3.     yuyy_gpio_opod_in(&(iicx->sda));
  4. }
  5. void yuyy_soft_iic_sdaout(YUYY_SOFT_IIC_DEV_t *iicx)
  6. {
  7.     yuyy_gpio_opod_out(&(iicx->sda));
  8. }
  9. void yuyy_soft_iic_sdalev(YUYY_SOFT_IIC_DEV_t *iicx,YUYY_GPIO_LEV_TYPE lev)
  10. {
  11.     yuyy_gpio_setlev(&(iicx->sda),lev);
  12. }
  13. YUYY_GPIO_LEV_TYPE yuyy_soft_iic_sdaread(YUYY_SOFT_IIC_DEV_t *iicx)
  14. {
  15.     return yuyy_gpio_readlev(&(iicx->sda));
  16. }
  17. void yuyy_soft_iic_sclin(YUYY_SOFT_IIC_DEV_t *iicx)
  18. {
  19.     yuyy_gpio_opod_in(&(iicx->scl));
  20. }
  21. void yuyy_soft_iic_sclout(YUYY_SOFT_IIC_DEV_t *iicx)
  22. {
  23.     yuyy_gpio_opod_out(&(iicx->scl));
  24. }
  25. void yuyy_soft_iic_scllev(YUYY_SOFT_IIC_DEV_t *iicx,YUYY_GPIO_LEV_TYPE lev)
  26. {
  27.     yuyy_gpio_setlev(&(iicx->scl),lev);
  28. }
  29. YUYY_GPIO_LEV_TYPE yuyy_soft_iic_sclread(YUYY_SOFT_IIC_DEV_t *iicx)
  30. {
  31.     return yuyy_gpio_readlev(&(iicx->scl));
  32. }
之后按照I2C通讯逻辑实现I2C读写
  1. uint8_t yuyy_soft_iic_start(YUYY_SOFT_IIC_DEV_t *iicx)
  2. {
  3.     yuyy_soft_iic_sdaout(iicx);
  4.     yuyy_soft_iic_sclout(iicx);
  5.     yuyy_soft_iic_sdalev(iicx,YUYY_GPIO_LEV1);
  6.     yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV1);
  7.     yuyy_soft_iic_sclin(iicx);
  8.     if(yuyy_soft_iic_waitscl_timeout(iicx,YUYY_GPIO_LEV1))
  9.         return 1;

  10.     yuyy_soft_iic_sclout(iicx);
  11.     yuyy_soft_iic_delay();
  12.     yuyy_soft_iic_sdalev(iicx,YUYY_GPIO_LEV0);
  13.     yuyy_soft_iic_delay();
  14.     yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV0);
  15.     yuyy_soft_iic_delay();
  16.     return YUYY_SOFT_IIC_OK;
  17. }

  18. uint8_t yuyy_soft_iic_stop(YUYY_SOFT_IIC_DEV_t *iicx)
  19. {
  20.     yuyy_soft_iic_sdaout(iicx);
  21.     yuyy_soft_iic_sclout(iicx);
  22.     yuyy_soft_iic_sdalev(iicx,YUYY_GPIO_LEV0);
  23.     yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV1);
  24.     yuyy_soft_iic_sclin(iicx);
  25.     if(yuyy_soft_iic_waitscl_timeout(iicx,YUYY_GPIO_LEV1))
  26.         return 1;

  27.     yuyy_soft_iic_sclout(iicx);
  28.     yuyy_soft_iic_delay();
  29.     yuyy_soft_iic_sdalev(iicx,YUYY_GPIO_LEV1);
  30.     return YUYY_SOFT_IIC_OK;
  31. }

  32. uint8_t yuyy_soft_iic_readack(YUYY_SOFT_IIC_DEV_t *iicx)
  33. {
  34.     uint8_t i=0,ack=YUYY_SOFT_IIC_ACK;
  35.     yuyy_soft_iic_sdain(iicx);
  36.     yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV1);
  37.     yuyy_soft_iic_sclin(iicx);
  38.     if(yuyy_soft_iic_waitscl_timeout(iicx,YUYY_GPIO_LEV1))
  39.         return 1;
  40.    
  41.     yuyy_soft_iic_sclout(iicx);
  42.     yuyy_soft_iic_delay();
  43.     while(yuyy_soft_iic_sdaread(iicx)!=YUYY_GPIO_LEV0 && i<10)
  44.     {
  45.         yuyy_soft_iic_delay();
  46.         i += 1;
  47.     }
  48.     if(i>8)
  49.         ack = YUYY_SOFT_IIC_NACK;
  50.     yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV0);
  51.     yuyy_soft_iic_delay();
  52.     return ack;
  53. }

  54. uint8_t yuyy_soft_iic_sendack(YUYY_SOFT_IIC_DEV_t *iicx,uint8_t ack)
  55. {
  56.     yuyy_soft_iic_sdaout(iicx);
  57.     if(ack == YUYY_SOFT_IIC_ACK)
  58.         yuyy_soft_iic_sdalev(iicx,YUYY_GPIO_LEV0);
  59.     else
  60.         yuyy_soft_iic_sdalev(iicx,YUYY_GPIO_LEV1);
  61.     yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV1);
  62.     yuyy_soft_iic_sclin(iicx);
  63.     if(yuyy_soft_iic_waitscl_timeout(iicx,YUYY_GPIO_LEV1))
  64.         return 1;
  65.    
  66.     yuyy_soft_iic_sclout(iicx);
  67.     yuyy_soft_iic_delay();
  68.     yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV0);
  69.     yuyy_soft_iic_delay();
  70.     return YUYY_SOFT_IIC_OK;
  71. }

  72. uint8_t yuyy_soft_iic_sendbyte(YUYY_SOFT_IIC_DEV_t *iicx,uint8_t dat)
  73. {
  74.     uint8_t i = 0;
  75.     yuyy_soft_iic_sdaout(iicx);
  76.     while(i<8)
  77.     {
  78.         if(dat & 0x80)
  79.             yuyy_soft_iic_sdalev(iicx,YUYY_GPIO_LEV1);
  80.         else
  81.             yuyy_soft_iic_sdalev(iicx,YUYY_GPIO_LEV0);
  82.         yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV1);
  83.         yuyy_soft_iic_sclin(iicx);
  84.         if(yuyy_soft_iic_waitscl_timeout(iicx,YUYY_GPIO_LEV1))
  85.             return 1;
  86.         
  87.         yuyy_soft_iic_sclout(iicx);
  88.         yuyy_soft_iic_delay();
  89.         yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV0);
  90.         yuyy_soft_iic_delay();
  91.         dat = dat << 1;
  92.         i += 1;
  93.     }
  94.     return YUYY_SOFT_IIC_OK;
  95. }

  96. uint8_t yuyy_soft_iic_readbyte(YUYY_SOFT_IIC_DEV_t *iicx,uint8_t *dat)
  97. {
  98.     uint8_t i = 0;
  99.     *dat = 0;
  100.     yuyy_soft_iic_sdain(iicx);
  101.     while(i<8)
  102.     {
  103.         yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV1);
  104.         yuyy_soft_iic_sclin(iicx);
  105.         if(yuyy_soft_iic_waitscl_timeout(iicx,YUYY_GPIO_LEV1))
  106.             return 1;
  107.         
  108.         yuyy_soft_iic_sclout(iicx);
  109.         yuyy_soft_iic_delay();
  110.         *dat = *dat << 1;
  111.         if(yuyy_soft_iic_sdaread(iicx) == YUYY_GPIO_LEV1)
  112.             *dat |= 0x01;
  113.         yuyy_soft_iic_scllev(iicx,YUYY_GPIO_LEV0);
  114.         yuyy_soft_iic_delay();
  115.         i += 1;
  116.     }
  117.     return YUYY_SOFT_IIC_OK;
  118. }
BMP280手册提供的 参考代码
QQ截图20231028222354.png
代码实现
  1. uint8_t yuyy_bmp280_writereg(YUYY_BMP280_DEV_t *bmp280_dev,uint8_t reg,uint8_t dat)
  2. {
  3.     uint8_t result = 0;
  4.     if(bmp280_dev->wiretype == YUYY_BMP280_WIRE_IIC)
  5.         result = bmp280_dev->iic_senddatas_func(bmp280_dev->iicx,BMP280_IIC_ADDR+bmp280_dev->addrlastbit,reg,1,&dat,1);
  6.     return result;
  7. }

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

  13.     return result;
  14. }

  15. uint8_t yuyy_bmp280_read1byte(YUYY_BMP280_DEV_t *bmp280_dev,uint8_t reg)
  16. {
  17.     uint8_t dat;
  18.     yuyy_bmp280_readdatas(bmp280_dev,reg,&dat,1);
  19.     return dat;
  20. }

  21. uint16_t yuyy_bmp280_read2byte(YUYY_BMP280_DEV_t *bmp280_dev,uint8_t reg,uint8_t le)
  22. {
  23.     uint8_t datas[2];
  24.     yuyy_bmp280_readdatas(bmp280_dev,reg,datas,2);
  25.     if(le > 0)
  26.         return (datas[1]<<8)|datas[0];
  27.     return (datas[0]<<8)|datas[1];
  28. }

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

  34.     bmp280_calib.dig_P1 = yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_P1,1);
  35.     bmp280_calib.dig_P2 = (int16_t)yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_P2,1);
  36.     bmp280_calib.dig_P3 = (int16_t)yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_P3,1);
  37.     bmp280_calib.dig_P4 = (int16_t)yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_P4,1);
  38.     bmp280_calib.dig_P5 = (int16_t)yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_P5,1);
  39.     bmp280_calib.dig_P6 = (int16_t)yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_P6,1);
  40.     bmp280_calib.dig_P7 = (int16_t)yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_P7,1);
  41.     bmp280_calib.dig_P8 = (int16_t)yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_P8,1);
  42.     bmp280_calib.dig_P9 = (int16_t)yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_DIG_P9,1);
  43. }

  44. float yuyy_bmp280_readtemp(YUYY_BMP280_DEV_t *bmp280_dev)
  45. {
  46.     int32_t var1, var2;
  47.     float T;
  48.     int32_t adc_T = yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_TEMPDATA,0);
  49.     adc_T <<= 8;
  50.     adc_T |= yuyy_bmp280_read1byte(bmp280_dev,BMP280_REGISTER_TEMPDATA+2);
  51.     adc_T >>= 4;

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

  53.     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;

  54.     t_fine = var1 + var2;

  55.     T  = (t_fine * 5 + 128) >> 8;
  56.     return T/100;
  57. }
  58. float yuyy_bmp280_readpress(YUYY_BMP280_DEV_t *bmp280_dev)
  59. {
  60.     int64_t var1, var2, p;
  61.     int32_t adc_P = yuyy_bmp280_read2byte(bmp280_dev,BMP280_REGISTER_PRESSUREDATA,0);
  62.     adc_P <<= 8;
  63.     adc_P |= yuyy_bmp280_read1byte(bmp280_dev,BMP280_REGISTER_PRESSUREDATA+2);
  64.     adc_P >>= 4;

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

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

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

初始化代码,将读到的气压和温度通过printf打印
  1. YUYY_SOFT_IIC_DEV_t siic_dev;
  2. YUYY_BMP280_DEV_t bmp280_dev;
  3. void bmp280_init()
  4. {
  5.     siic_dev.scl.gpio = SIIC_SCL_GPIO_PORT;
  6.     siic_dev.scl.pin = SIIC_SCL_PIN;
  7.     siic_dev.sda.gpio = SIIC_SDA_GPIO_PORT;
  8.     siic_dev.sda.pin = SIIC_SDA_PIN;
  9.     yuyy_soft_iic_init(&siic_dev);
  10.     bmp280_dev.iicx = &siic_dev;
  11.     bmp280_dev.wiretype = YUYY_BMP280_WIRE_IIC;
  12.     bmp280_dev.iic_readdatas_func = (yuyy_iic_readdatas_func_t)yuyy_soft_iic_readdatas;
  13.     bmp280_dev.iic_senddatas_func = (yuyy_iic_senddatas_func_t)yuyy_soft_iic_senddatas;
  14.     yuyy_bmp280_init(&bmp280_dev);
  15.     yuyy_bmp280_setctrlmeas(&bmp280_dev,0x3F);
  16. }

  17. void bmp280_readpress()
  18. {
  19.     float temp,press;
  20.     temp = yuyy_bmp280_readtemp(&bmp280_dev);
  21.     press = yuyy_bmp280_readpress(&bmp280_dev);
  22.     printf("BMP280 读取温度:%.1f℃ 压力:%.1fpa",temp,press);
  23. }
运行效果
QQ截图20231028214100.png



单片小菜 发表于 2023-11-1 10:10 | 显示全部楼层
这个小模块,在哪里买的?
 楼主| yuyy1989 发表于 2023-11-1 10:57 | 显示全部楼层
单片小菜 发表于 2023-11-1 10:10
这个小模块,在哪里买的?

淘宝
lajfda003 发表于 2023-11-1 11:14 | 显示全部楼层
这个小模块多少钱?
 楼主| yuyy1989 发表于 2023-11-1 11:23 | 显示全部楼层
lajfda003 发表于 2023-11-1 11:14
这个小模块多少钱?

淘宝上3块多
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:同飞软件研发工程师
简介:制冷系统单片机软件开发,使用PID控制温度

161

主题

815

帖子

10

粉丝
快速回复 在线客服 返回列表 返回顶部
认证:同飞软件研发工程师
简介:制冷系统单片机软件开发,使用PID控制温度

161

主题

815

帖子

10

粉丝
快速回复 在线客服 返回列表 返回顶部