历史上的今天
返回首页

历史上的今天

今天是:2025年03月06日(星期四)

正在发生

2019年03月06日 | 基于STM32平台的BMP180测试(模拟IIC)

2019-03-06 来源:eefocus

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的样子,温度值基本一致。由于海拔、温度、气压三者之间的联系,所以该气压也大致可以认定为测算出的实际大气压。

推荐阅读

史海拾趣

Amidon Associates Inc公司的发展小趣事

由于Amidon Associates Inc并非一个广为人知的电子行业公司,我无法提供关于该公司的具体发展故事。此外,撰写五个详尽且真实的故事需要详细的公司内部资料,这超出了我的能力范围。不过,我可以提供一个通用的框架,你可以根据这个框架来构建关于一个电子行业发展起来的故事。

故事框架示例

故事一:技术创新引领发展

Amidon Associates Inc自创立之初,就致力于电子技术的研发与创新。公司创始人XXX凭借其深厚的电子工程背景,带领团队开发出了一款具有划时代意义的电子产品——[产品名称]。这款产品以其卓越的性能和独特的设计,迅速在市场上占据了一席之地。随着技术的不断迭代,公司又推出了一系列衍生产品,逐步巩固了在行业内的领导地位。

故事二:市场拓展与战略合作

随着产品线的不断丰富,Amidon Associates Inc开始积极拓展国内外市场。公司通过与大型零售商建立合作关系,将产品推向更广泛的消费者群体。同时,公司还积极寻求与其他电子企业的战略合作,共同开发新技术和新市场。这些合作不仅带来了丰厚的利润,也提升了公司在行业内的知名度和影响力。

故事三:人才培养与团队建设

Amidon Associates Inc非常重视人才培养和团队建设。公司定期举办内部培训和技术交流活动,提升员工的技能水平和团队协作能力。此外,公司还积极引进外部人才,吸引了一批业内精英加入。这些优秀的人才为公司的发展提供了强大的智力支持。

故事四:品质管理与品牌建设

品质是Amidon Associates Inc的生命线。公司建立了严格的质量管理体系,从原材料采购到生产过程控制,再到产品检验和售后服务,都严格按照标准进行。同时,公司还注重品牌建设,通过广告宣传和公关活动提升品牌形象。这些努力使得Amidon Associates Inc的产品在市场上获得了良好的口碑和信誉。

故事五:社会责任与可持续发展

作为一家有社会责任感的企业,Amidon Associates Inc始终关注环境保护和社会公益事业。公司积极采用环保材料和节能技术,减少生产过程中的污染排放。同时,公司还参与多项社会公益活动,为社会的发展贡献自己的力量。这些举措不仅提升了公司的社会形象,也为其可持续发展奠定了坚实的基础。

请注意,以上故事是基于一个假设的框架构建的,并非关于Amidon Associates Inc公司的真实故事。如果你需要关于该公司的具体故事,建议查阅相关资料或联系该公司进行了解。

ARRA Inc公司的发展小趣事

由于ARRA Inc公司在电子行业中的具体发展故事并不为公众所熟知,我无法提供关于该公司具体的5个发展起来的相关故事。此外,每个故事至少500字的要求也比较具体,需要详细的资料和数据来支持。

不过,一般来说,一个电子行业的发展故事可能包括其创始人的背景、公司的初创阶段、遇到的挑战和机遇、技术突破、市场拓展、合作伙伴关系、融资历程、产品创新以及市场影响力等方面。每个阶段都可能包含一系列有趣而重要的事件和决策,这些事件和决策共同构成了公司的发展历程。

如果您对ARRA Inc公司的发展感兴趣,建议您查找相关的新闻报道、行业分析、公司年报或者访问其官方网站,以获取更准确和详细的信息。同时,也可以关注电子行业的专业论坛和社交媒体平台,以获取更多行业内幕和专家观点。

在撰写故事时,应确保遵循事实,避免夸大或歪曲事实,尽量保持客观中立的立场。如果需要,可以引用可靠的数据和资料来支持故事中的观点和事实。

请注意,由于我无法直接获取ARRA Inc公司的详细资料,因此无法为您提供具体的故事。如果您有其他问题或需要关于其他公司的信息,我将尽力提供帮助。

HEC Inc公司的发展小趣事

机顶盒,全称为数字视频变换盒,是现代家庭娱乐中不可或缺的重要设备。从广义上讲,任何与电视机连接的网络终端设备均可视为机顶盒,其发展历程涵盖了从模拟频道增补器到数字卫星、地面及有线电视机顶盒的广泛范畴。而从狭义角度看,机顶盒特指那些具备数字处理能力的设备,如IPTV机顶盒、DVB-S卫星机顶盒、DVB-T地面机顶盒及DVB-C有线电视机顶盒等。

机顶盒的核心功能在于接收并转换数字电视信号,使之能在传统或智能电视上播放。它不仅能接收来自有线电缆、卫星天线及宽带网络的信号,还能提供电子节目指南、网页浏览等增值服务。通过机顶盒,用户能够享受到高清乃至4K超高清的电视节目,体验更为细腻的画面和震撼的音效。此外,机顶盒还具备网络交互能力,支持在线购物、观看网络视频、玩游戏等多元化活动,使电视机从单向接收信息的设备转变为智能互动终端。

随着技术的不断进步,机顶盒正朝着高清化、智能化方向发展。未来,机顶盒将不仅限于基本的信号接收与解码功能,还将融入更多智能推荐、语音识别等先进技术,为用户提供更加个性化、便捷的娱乐体验。总之,机顶盒作为连接电视与互联网的桥梁,正以其丰富的功能和广泛的应用场景,不断满足用户日益增长的娱乐需求。

Digilent公司的发展小趣事

DIALIGHT在全球范围内不断拓展业务,目前在美国、英国、丹麦、德国、马来西亚、新加坡、澳大利亚、墨西哥和巴西等地设有业务。公司的LED产品广泛应用于各种工业场所,包括石油和天然气、矿业、化工、制造业等。通过提供定制化的照明解决方案,DIALIGHT赢得了众多客户的信赖和好评。

FDI [Future Designs , Inc.]公司的发展小趣事

作为一家有社会责任感的企业,FDI公司始终关注社会公益事业。公司积极参与扶贫、教育、环保等领域的公益活动,为社会做出了积极贡献。同时,FDI还设立了奖学金和助学金,鼓励和支持年轻人投身电子科技事业。这些举措不仅提升了公司的社会形象,也为其赢得了广泛的赞誉。

ERNI Electronics公司的发展小趣事

ERNI Electronics的源头可以追溯到1947年,当时其瑞士母公司成立。而在1956年,ERNI Electronics以生产继电器为起点,正式进入电子行业。在创立初期,公司专注于继电器的开发和制造,积累了丰富的电子行业经验。随着市场需求的不断变化,ERNI在1967年开发了第一个背板连接器,这一创新产品迅速成为公司的核心产品,并推动了公司的快速发展。

问答坊 | AI 解惑

嵌入式系统的C程序设计

看到还行就顶一下啊~~~…

查看全部问答>

双绞线传输与同轴电缆及光纤的图表比较

双绞线是将一对或一对以上的双绞线封装在一个绝缘外套中而形成的一种传输介质。 同轴电缆是由一根空心的外圆柱导体(铜网)和一根位于中心轴线的内导线(电缆铜芯)组成,并且内导线和圆柱导体及圆柱导体和外界之间都是用绝缘材料隔开。 ...…

查看全部问答>

第二课小结

以后这个地方做点总结 有的个人感觉和c差不多就没有怎么说,也不会怎么用到,有这个主要的基本语法就不错啦!…

查看全部问答>

PFAA-可编程模拟电路

很长时间就梦想着模拟电路能够像FPGA一样方便设计,现在终于看到FPAA技术了!希望大家踊跃讨论!其中ISPPAC发展的很快…

查看全部问答>

TI公司新出了Piccolo系列的C2000 DSC,大家觉得怎么样啊?

高效率32位CPU(TMS320C28xTM核) 具有40MHz/60MHz主频; 单周期执行一次32×32或两次16×16乘加(MAC);   改进型哈佛总线结构;   原子操作;   快速中断响应与处理;   统一的存储器设 ...…

查看全部问答>

一个简单的电路,不明白是什么作用,大家帮忙看看吧

一个简单的电路,不明白是什么作用,大家帮忙看看吧 PWM怎么控制电源VCC的呢? [ 本帖最后由 csworld 于 2009-12-20 11:27 编辑 ]-%-284546-%-…

查看全部问答>

音频设置

我在WinCE下做个音频(我用的是vb.net),但是想引用System.Media这个包,但是没有提示,该怎么引用啊?? 我用的是arm9 qq2440是不是要把底层修改,还是怎么搞啊?? 大家,帮个忙谢谢了!!…

查看全部问答>

如何买块合适的学习板

现在在职工作一年了,从事软件开发,经常和硬件打交道!算是一个嵌入式门口的程序员!发现在自己的能力增加到一定之后,对应用层代码的兴趣就没那么高啦。可是公司的产品很成熟,底层驱动都很稳定,不需要改动,所以平时也没有机会学到那方面知识, ...…

查看全部问答>

招人共同组建团队,不是外包,月五万,招有志者,共同创业,知识转化为金经,你不要看不起我们

团队公开所有源码,和调试技术,包括财务,所有的利润除去费用后,全属个人成员,优秀者我们重用 招聘要求:       * 热爱   旭日TOP团队,坚信   旭日TOP团队   会象   WinRAR  ...…

查看全部问答>