基于STM32平台的BMP180测试(模拟IIC)

2023-05-16

1.测试描述:

使用模拟IIC,从BMP180中获取ID号、温度值、气压值以及计算海拔高度。

2.测试准备:

硬件平台:原子战舰V3开发板
测试工具:逻辑分析仪、串口调试工具


3.数据手册解读:

(1) 首先是多个字节的读取时序图,从这里也可以看出BMP180芯片的地址+写信号是0xEE,地址+读信号为0xEF,当然手册前面也有提到过,有兴趣的可以自己去查看一下手册。

这里写图片描述

(2) 然后本人测试时默认使用的是下图画横线部分的部分,也就是气压这块使用的是低功耗模式。OSS的值要注意,因为后期的计算需要这个,并且读取UT值时也要做对应的处理。

这里写图片描述

(3) 下图就是手册里给出的利用BMP180里的参数计算气压和温度的流程图。特别注意流程里的OSS,由于本测试使用的OSS = 0,所以在实际代码中省去了这一部分。

这里写图片描述

4.测试代码:

由于本工程是直接使用原子战舰的标准例程-库函数版本\实验23 IIC实验源码改过来的,所以模拟IIC部分使用的原子这块的代码。BMP180部分由本人编写。
(1) 首先是BMP180.C的代码片

#include "bmp180.h"
#include "delay.h"
#include "math.h"

//存储BMP180数据的结构
_bmp180 bmp180;

//BMP180初始化
//对使用的IIC端口进行初始化
void BMP_Init(void)
{
    IIC_Init();
}

//写一个数据到BMP180
void BMP_WriteOneByte(uint8_t WriteAddr,uint8_t DataToWrite)
{
    IIC_Start();

    IIC_Send_Byte(0xEE);
    IIC_Wait_Ack();

    IIC_Send_Byte(WriteAddr);
    IIC_Wait_Ack();

    IIC_Send_Byte(DataToWrite);
    IIC_Wait_Ack();
    IIC_Stop();
}

//从BMP180读一个字节数据
uint8_t BMP_ReadOneByte(uint8_t ReadAddr)
{
    uint8_t data = 0;

    IIC_Start();

    IIC_Send_Byte(0xEE);
    IIC_Wait_Ack();

    IIC_Send_Byte(ReadAddr);
    IIC_Wait_Ack();

    IIC_Start();

    IIC_Send_Byte(0xEF);
    IIC_Wait_Ack();

    data = IIC_Read_Byte(1);
    IIC_Stop();

    return data;
}

//从BMP180读一个16位的数据
short BMP_ReadTwoByte(uint8_t ReadAddr)
{
    short data;
    uint8_t msb,lsb;

    IIC_Start();

    IIC_Send_Byte(0xEE);
    IIC_Wait_Ack();

    IIC_Send_Byte(ReadAddr);
    IIC_Wait_Ack();

    IIC_Start();

    IIC_Send_Byte(0xEF);
    IIC_Wait_Ack();

    msb = IIC_Read_Byte(1);
    lsb = IIC_Read_Byte(0);

    IIC_Stop();

    data = msb*256 + lsb;

    return data;
}

//从BMP180的获取计算参数
void BMP_ReadCalibrationData(void)
{
    bmp180.AC1 = BMP_ReadTwoByte(0xAA);
    bmp180.AC2 = BMP_ReadTwoByte(0xAC);
    bmp180.AC3 = BMP_ReadTwoByte(0xAE);
    bmp180.AC4 = BMP_ReadTwoByte(0xB0);
    bmp180.AC5 = BMP_ReadTwoByte(0xB2);
    bmp180.AC6 = BMP_ReadTwoByte(0xB4);
    bmp180.B1  = BMP_ReadTwoByte(0xB6);
    bmp180.B2  = BMP_ReadTwoByte(0xB8);
    bmp180.MB  = BMP_ReadTwoByte(0xBA);
    bmp180.MC  = BMP_ReadTwoByte(0xBC);
    bmp180.MD  = BMP_ReadTwoByte(0xBE);
}

//从BMP180读取未修正的温度
long BMP_Read_UT(void)
{
    long temp = 0;
    BMP_WriteOneByte(0xF4,0x2E);

    delay_ms(5);
    temp = (long)BMP_ReadTwoByte(0xF6);
    return temp;
}

//从BMP180读取未修正的大气压
long BMP_Read_UP(void)
{
    long pressure = 0;

    BMP_WriteOneByte(0xF4,0x34);
    delay_ms(5);

    pressure = (long)BMP_ReadTwoByte(0xF6);
    //pressure = pressure + BMP_ReadOneByte(0xf8);
    pressure &= 0x0000FFFF;

    return pressure;
}

//用获取的参数对温度和大气压进行修正,并计算海拔
void BMP_UncompemstatedToTrue(void)
{
    bmp180.UT = BMP_Read_UT();//第一次读取错误
    bmp180.UT = BMP_Read_UT();//进行第二次读取修正参数
    bmp180.UP = BMP_Read_UP();

    bmp180.X1 = ((bmp180.UT - bmp180.AC6) * bmp180.AC5) >> 15;
    bmp180.X2 = (((long)bmp180.MC) << 11) / (bmp180.X1 + bmp180.MD);
    bmp180.B5 = bmp180.X1 + bmp180.X2;
    bmp180.Temp  = (bmp180.B5 + 8) >> 4;

    bmp180.B6 = bmp180.B5 - 4000;
    bmp180.X1 = ((long)bmp180.B2 * (bmp180.B6 * bmp180.B6 >> 12)) >> 11;
    bmp180.X2 = ((long)bmp180.AC2) * bmp180.B6 >> 11;
    bmp180.X3 = bmp180.X1 + bmp180.X2;

    bmp180.B3 = ((((long)bmp180.AC1) * 4 + bmp180.X3) + 2) /4;
    bmp180.X1 = ((long)bmp180.AC3) * bmp180.B6 >> 13;
    bmp180.X2 = (((long)bmp180.B1) *(bmp180.B6*bmp180.B6 >> 12)) >>16;
    bmp180.X3 = ((bmp180.X1 + bmp180.X2) + 2) >> 2;
    bmp180.B4 = ((long)bmp180.AC4) * (unsigned long)(bmp180.X3 + 32768) >> 15;
    bmp180.B7 = ((unsigned long)bmp180.UP - bmp180.B3) * 50000;

    if(bmp180.B7 < 0x80000000)
    {
        bmp180.p = (bmp180.B7 * 2) / bmp180.B4;     
    }
    else
    {
        bmp180.p = (bmp180.B7 / bmp180.B4) * 2;
    }

    bmp180.X1 = (bmp180.p >> 8) * (bmp180.p >>8);
    bmp180.X1 = (((long)bmp180.X1) * 3038) >> 16;
    bmp180.X2 = (-7357 * bmp180.p) >> 16;

    bmp180.p = bmp180.p + ((bmp180.X1 + bmp180.X2 + 3791) >> 4);

    bmp180.altitude = 44330 * (1-pow(((bmp180.p) / 101325.0),(1.0/5.255)));  
}

(2) 然后是BMP180.H部分

#ifndef _BMP180_H_
#define _BMP180_H_

#include "myiic.h"

typedef struct __BMP180
{
    short AC1;
    short AC2;
    short AC3;
    unsigned short AC4;
    unsigned short AC5;
    unsigned short AC6;
    short B1;
    short B2;
    short MB;
    short MC;
    short MD;
    long UT;
    long UP;
    long X1;
    long X2;
    long X3;
    long B3;
    unsigned long B4;
    long B5;
    long B6;
    long B7;
    long p;
    long Temp;
    float altitude;
}_bmp180;

extern _bmp180 bmp180;

void BMP_Init(void);
uint8_t BMP_ReadOneByte(uint8_t ReadAddr);
void BMP_WriteOneByte(uint8_t WriteAddr,uint8_t DataToWrite);
short BMP_ReadTwoByte(uint8_t ReadAddr);
void BMP_ReadCalibrationData(void);
long BMP_Read_UT(void);
long BMP_Read_UP(void);
void BMP_UncompemstatedToTrue(void);

#endif

由于是测试,所以将所有的参数都建了一个结构体,方便DEBUG时通过WATCH窗口查看,实际使用当中可以将一些非必要的参数做成临时变量。

5.测试时遇到的问题:

在BMP_UncompemstatedToTrue函数中,开头时首先读取UT和UP的值。开始时两者都只是读取一次,测算时发现UT值并未正确读出,为0,从而导致算出来的实际温度值在-71度左右,海拔在2500多米。通过逻辑分析仪监测,发现在第一次读取数据时,模拟IIC部分发出的数据是错误的。如下图画线处所示:
这里写图片描述
但是从图中可以看出,后面部分是正常的。针对这个现象我对延时、底层驱动模块都做了改变和测试,没有任何的改观。所以后面将UT值读取两次,就是为了消除这个错误,这也是一个折中的办法。经修改后实测读取正常。

6.测试结果:

这里写图片描述

本人在上海,平均海拔在4m的样子,温度值基本一致。由于海拔、温度、气压三者之间的联系,所以该气压也大致可以认定为测算出的实际大气压。

7.测试源码:

链接:https://pan.baidu.com/s/1qYmD2VU

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于STM32平台的BMP180测试(模拟IIC) 的相关文章

  • GCC - 如何停止链接 malloc?

    我正在努力将我的代码缩减到最小的骨架大小 我使用的是只有 32k 闪存的 STM32F0 需要很大一部分闪存用于数据存储 我的代码已经有大约 20k 闪存大小 其中一些是由于使用了 STM32 HAL 函数 我可以在以后需要时对其进行解释和
  • 135-基于stm32单片机超声波非接触式感应水龙头控制系统Proteus仿真+源程序

    资料编号 135 一 功能介绍 1 采用stm32单片机 LCD1602显示屏 独立按键 DHT11传感器 电机 超声波传感器 制作一个基于stm32单片机超声波非接触式感应水龙头控制系统Proteus仿真 2 通过DHT11传感器检测当前
  • Push_back() 导致程序在进入 main() 之前停止

    我正在为我的 STM32F3 Discovery 板使用 C 进行开发 并使用 std deque 作为队列 在尝试调试我的代码 直接在带有 ST link 的设备上或在模拟器中 后 代码最终在 main 中输入我的代码之前在断点处停止 然
  • STM32F4 通过软复位跳转到引导加载程序,无需 BOOT0 和 BOOT1 引脚

    我问这个问题是因为可以在这里找到类似问题的答案 通过应用程序跳转到 STM32 中的引导加载程序 即从用户闪存在引导模式下使用引导 0 和引导 1 引脚 用户 JF002 JF002回答 当我想跳转到引导加载程序时 我在其中一个备份寄存器中
  • STM32F103

    提示 来源正点原子 参考STM32F103 战舰开发指南V1 3PDF资料 文章目录 前言 一 pandas是什么 二 使用步骤 1 引入库 2 读入数据 总结 前言 提示 这里可以添加本文要记录的大概内容 开发环境硬件普中科技 接线图在g
  • 毕业设计 江科大STM32的智能温室控制蓝牙声光报警APP系统设计

    基于STM32的智能温室控制蓝牙声光报警APP系统设计 1 项目简介 1 1 系统构成 1 2 系统功能 2 部分电路设计 2 1 stm32f103c8t6单片机最小系统电路设计 2 2 LCD1602液晶显示电路设计 2 2 风
  • STM32F103概要

    The STM32F103x4 STM32F103x6 STM32F103xC STM32F103xD and STM32F103xE are a drop in replacement for STM32F103x8 B medium d
  • SHT10温湿度传感器——STM32驱动

    实验效果 硬件外观 接线 3 3V供电 IIC通讯 代码获取 查看下方 END
  • HAL 锁定和解锁函数如何使用以及为什么?

    我试图理解另一位程序员编写的代码 它使用了I C http en wikipedia org wiki I C2 B2C通信以将数据写入 STM32 微控制器的 EEPROM 一般来说 我理解他的代码是如何工作的 但我不明白他为什么使用HA
  • VS Code 有没有办法导入 Makefile 项目?

    正如标题所说 我可以从现有的 Makefile 自动填充 c cpp properties json 吗 Edit 对于其他尝试导入 makefile 的人 我找到了一组脚本 它们完全可以实现我想要实现的目标 即通过 VS Code 管理
  • 跟着野火学FreeRTOS:第一段(任务定义,切换以及临界段)

    在裸机系统中 系统的主体就是 C P U CPU CP U 按照预先设定的程序逻辑在 m a i n
  • 串口通讯第一次发送数据多了一字节

    先初始化IO再初始化串口 导致第一次发送时 多出一个字节数据 优化方案 先初始化串口再初始化IO 即可正常通讯
  • Arm:objcopy 如何知道 elf 中的哪些部分要包含在二进制或 ihex 中?

    我正在开发一个项目 其中涉及解析arm elf 文件并从中提取部分 显然 elf 文件中有很多部分没有加载到闪存中 但我想知道 objcopy 到底如何知道要在二进制文件中包含哪些部分以直接闪存到闪存中 以arm elf文件的以下reade
  • 特殊寄存器

    特殊寄存器 文章目录 前言 一 背景 二 2 1 2 2 总结 前言 前期疑问 STM32特殊寄存器到底是什么 特殊寄存器怎么查看和调试代码 本文目标 记录和理解特殊寄存器 一 背景 最近在看ucosIII文章是 里面提到特殊寄存器 这就进
  • Cortex-M3与M4权威指南

    处理器类型 所有的ARM Cortex M 处理器是32位的精简指令集处理器 它们有 32位寄存器 32位内部数据路径 32位总线接口 除了32位数据 Cortex M处理器也可以有效地处理器8位和16位数据以及支持许多涉及64位数据的操作
  • 核心耦合内存在 STM32F4xx 上可执行吗?

    尝试从 STM32F429s CCM 运行代码 但每当我命中 CCM 中的第一条指令时 我总是会遇到硬故障 并且 IBUSERR 标志被设置 该指令有效且一致 STM32F4xx 是否可能不允许从 CCM 执行 数据访问效果良好 alios
  • 通过JTAG恢复STM32 MCU磨掉的标记

    我有一块可能带有 STM32 MCU 的板 我想为该板制作定制固件 因为库存板有很多问题 不幸的是 电路板制造商很友善地磨掉了所有标记 有没有办法通过 jtag 获取设备 系列 ID 并将其交叉引用到型号 我能找到的一切都是关于获取芯片的唯
  • 嵌入式 C++11 代码 — 我需要 volatile 吗?

    采用 Cortex M3 MCU STM32F1 的嵌入式设备 它具有嵌入式闪存 64K MCU固件可以在运行时重新编程闪存扇区 这是由闪存控制器 FMC 寄存器完成的 所以它不像a b那么简单 FMC 获取缓冲区指针并将数据刻录到某个闪存
  • 在 Contiki 程序中使用 malloc

    考虑以下 Contiki 程序 include
  • 哪些变量类型/大小在 STM32 微控制器上是原子的?

    以下是 STM32 微控制器上的数据类型 http www keil com support man docs armcc armcc chr1359125009502 htm http www keil com support man d

随机推荐

  • 2021-06-02

    在ROS中仿真模型中添加gps传感器 获取gps传感器模型包为自己的机器人添加gps传感器将gps之中的经度纬度坐标转化为自己地图中的坐标 1 获取gps传感器模型包 link http wiki ros org hector gazebo
  • Dockerfile如何编写(指令详解)

    本文个人博客地址 xff1a https www leafage top posts detail 21525V8AP Dockerfile Dockerfile 描述了组装镜像的步骤 xff0c 其中每条指令都是单独执行的 除了FROM指
  • 关于Home Lab的搭建——硬件选择篇(迷你主机)(一)

    关于Home Lab 这个名词出自哪里 xff0c 我也不清楚 不过 xff0c 可以这样来理解Home Lab xff0c Home Lab是一台作为实验使用的电脑 xff0c 试验的内容多数是关于计算机网络的搭建 系统安装 测试 xff
  • Adaboost基本二分类算法

    最早类型的Adaboost是由Yoav Freund和Robert E Schapire提出的 xff0c 一种用于二分类的boosting集成学习方法 也是李航 统计学习方法 中所介绍的Adaboost 它将一系列弱分类器的线性组合 xf
  • Springboot 项目金蝶中间件AAS-9.0启动报错 javax.persistence.Table.indexes()[Ljavax/persistence/Index 问题解决

    Springboot 项目金蝶中间件AAS 9 0启动报错 java lang NoSuchMethodError javax persistence Table indexes Ljavax persistence Index问题解决方法
  • CMakeLists配置(常用的)

    一 xff1a 最小组成 cmake 最小版本需求 cmake minimum required VERSION 2 8 project 名字 project MyEsp32AllCode 可执行文件生成 add executable PR
  • SLAM学习笔记(四)定位

    原创博客 xff1a http blog csdn net renshengrumenglibing viewmode 61 contents 机器人定位的目的是为了知道 自己在什么地方 xff0c 目前 xff0c 机器人定位的方法可以分
  • SLAM实习岗位面经

    一 地平线 一面主要是在问关于SLAM岗位的技术问题 xff0c 然后还问了一些比较简单的C 43 43 基础知识 其实总体而言 xff0c 面试的问题都比较基础 xff0c 比较考验SLAM基本功 xff0c 如果只知道一些SLAM皮毛的
  • Canal数据库监听

    1 什么是canal canal是用java开发的基于数据库增量日志解析 xff0c 提供增量数据订阅 amp 消费的中间件 目前 xff0c canal主要支持了MySQL的binlog解析 xff0c 解析完成后才利用canal cli
  • linux下安裝mitmproxy 详解傻瓜式文档

    前言 xff1a mitmproxy 就是用于 MITM 的 proxy xff0c MITM 即中间人攻击 xff08 Man in the middle attack xff09 用于中间人攻击的代理首先会向正常的代理一样转发请求 xf
  • ROS学习笔记(2)——ROS架构

    ROS学习笔记 xff08 2 xff09 ROS架构 0 学习来源1 ROS架构2 文件系统级2 1 工作空间 3 计算图级4 ROS开源社区级4 1 发行版 xff08 Distribution xff09 4 2 软件库 xff08
  • STM32_中断

    STM32 中断 一 介绍 1 1解释 打断CPU执行正常的程序 xff0c 转而处理紧急程序 xff0c 然后返回原暂停的程序继续运行 xff0c 就叫中断 1 2作用和意义 作用 xff1a 实时控制 xff1a 在确定时间内对相应事件
  • Oracle创建用户并授权

    很多时候 xff0c 我们不需要用系统原始的sys xff0c sysdba等系统账户 xff0c 需要创建个性化的用户并授权 xff0c 那就需要我们首先登录到dba账户 xff0c 然后通过dba账户进行用户创建并授权 1 用dba权限
  • 【Linux】vim 中批量添加注释

    本期主题 xff1a vim 中批量添加注释博客主页 xff1a 小峰同学分享小编的在Linux中学习到的知识和遇到的问题小编的能力有限 xff0c 出现错误希望大家不吝赐 此文主要介绍两种方法 xff1a 方法一 xff1a 块选择模式
  • 对gazebo启动后黑屏或者没有模型的解决

    1 问题 卡在加载模型界面 xff1b 加载太慢或者黑屏 xff1a 报错信息如下 xff1a 图1 打开界面 xff1a 图2 2 解决办法 直接下载所有模型到用户的根目录下的 gazebo models 下 xff1a 方法1 xff1
  • 【Python与机器学习】5.K-Means聚类

    聚类 xff08 clustering xff09 什么是聚类 聚类属于无监督学习 xff08 unsupervised learning xff09 xff0c 即无类别标记 是数据挖掘经典算法之一 算法接收参数k xff1b 然后将样本
  • 穿过已知点画平滑曲线(3次贝塞尔曲线)

    为了把一串点连成光滑的曲线 xff0c 先研究贝塞尔曲线 xff0c 又搞B样条插值 都没有成功 数学没那么强 后来在 翻译 AGG 之贝塞尔插值 http liyiwen javaeye com blog 705489 看到一种比较好的方
  • 二值信号量和互斥锁到底有什么区别?

    原文链接 xff1a https www cnblogs com codescrew p 8970514 html 在说明之前我先抛出结论 xff1a 互斥锁和二值信号量在使用上非常相似 xff0c 但是互斥锁解决了优先级翻转的问题 假定我
  • 使用stm32CubeMX自动配置的工程文件,进行串口的不定长接收(非DMA方式)

    方法描述 xff1a 使用stm32CubeMX自动配置的工程文件 xff0c 进行串口的不定长接收 xff08 非DMA方式 xff09 实际问题解决尝试 xff1a 1 HAL库函数只有接收定长数据HAL UART Receive xf
  • 基于STM32平台的BMP180测试(模拟IIC)

    1 测试描述 xff1a 使用模拟IIC xff0c 从BMP180中获取ID号 温度值 气压值以及计算海拔高度 2 测试准备 xff1a 硬件平台 xff1a 原子战舰V3开发板 测试工具 xff1a 逻辑分析仪 串口调试工具 3 数据手