STM32软件SPI驱动BMP280(OLED显示)

STM32软件SPI驱动BMP280 OLED显示

  • BMP280简介
    • 寄存器简要说明
    • SPI通讯
    • 代码逻辑
    • 代码展示
  • 现象
  • 总结

BMP280简介

在这里插入图片描述

数字接口类型:IIC(从模式3.4MHz)或SPI(3线或4线制从模式10MHz)
气压测量范围:300~1100hPa(百帕斯卡)
气压测量误差:±1hPa 分辨率:0.16Pa
温度测量范围:0℃~65℃
温度测量误差:±0.5℃(25℃下) ±1℃(0-65℃情况下)以内 分辨率:0.01℃
工作电压:3.3V
带M3固定螺丝孔,方便安装及固定。

寄存器简要说明

在这里插入图片描述

0xFA-0xFC:温度寄存器原始值
0xF7-0xF9:压力寄存器原始值
0xF4-0xF5:参数配置,待机时间(t_sb),滤波参数(fliter),3线SPI使能(spi3w_en),过采样(osrs_t,osrs_P),模式(mode)
0xE0:默认写入0xB6,使用完整的上电复位过程复位设备
0xF3:状态寄存器
在这里插入图片描述

0xD0:ID寄存器,只读,值为0x58

SPI通讯

SPI模式可选择0或者3,这里使用的是模式0进行编写代码。
SPI写:把对应寄存器的最高位位7去掉,写成固定的0即可形成SPI的写指令,这里使用的是将原有的寄存器地址和0x7F进行与操作。同时注意这里的写不是自动递增的,需要写完一个字节后再次发送写指令写下一个寄存器。
在这里插入图片描述

SPI读:跟写指令一样是把位7去掉,写成固定的1形成SPI的读指令,这里使用的是原有的寄存器地址和0x80进行或操作来实现。读指令是自动递增的,读取一个指令后可以直接交换数据后读取下一寄存器的数据。
在这里插入图片描述
模块还支持3线的SPI和IIC通讯,IIC通讯就是普通的IIC通讯协议,发送对应的从机地址和指令进行读写操作,从机地址由SDO引脚控制,这个模块默认拉低位为0x76,拉高则为0x77。
3线SPI的通讯协议和4线SPI的相同,不过是通讯线只有一条为SDI,半双工通讯。

代码逻辑

在这里插入图片描述

代码展示

这里使用的是四线SPI进行通讯,单片机使用的是STM32F103C8T6。
main.c :

/**
接线(模拟SPI-4线)
BMP280-----STM32F103C8T6
SCL----SCK----PA5
SDA----MOSI---PA7
CSB----SS-----PA4
SDO----MISO---PA6
OLED----STM32F103C8T6
SCL-------PB8
SDA-------PB9
VCC-------3V3
GND-------GND
**/
int32_t	BMP_Temperature;
uint32_t BMP_Pressure;
int32_t BMP_Altitude;
uint8_t ID;							//定义用于存放ID号的变量
uint8_t ArrayRead[4];               //定义要读取数据的测试数组
int main(void)
{/*模块初始化*/OLED_Init();						//OLED初始化BMP280_Init();						//BMP280初始化Serial_Init();                      //串口初始化/*显示静态字符串*/OLED_ShowString(1, 6, "BMP280");OLED_ShowString(2, 1, "ID:");/*显示ID号*/BMP280_ReadID(&ID);			//获取BMP280的ID号OLED_ShowHexNum(2, 4, ID, 2);		//显示IDwhile (1){//Temperature//OLED显示BMP_Temperature = BMP280_GetTemp();OLED_ShowString(3, 1, "T:");OLED_ShowNum(3, 3, BMP_Temperature / 100.0, 2);OLED_ShowString(3, 5, ".");OLED_ShowNum(3, 6, BMP_Temperature, 2); OLED_ShowString(3, 9, "C");//Pressure//OLED显示BMP_Pressure =  BMP280_GetPress();OLED_ShowString(4, 1, "P:"); OLED_ShowNum(4, 3, BMP_Pressure / 256 / 100, 4);  //单位为hPa,需要再除以100OLED_ShowString(4, 7, ".");OLED_ShowNum(4, 8, BMP_Pressure / 25.6, 3);  OLED_ShowString(4, 12, "hPa");}
}

BMP280.c

#define BMP280_RESET_VALUE					0xB6		//复位寄存器写入值
#define BMP280_S32_t long signed int
#define BMP280_U32_t long unsigned int
#define BMP280_S64_t long long signed int
BMP280_S32_t t_fine;
uint16_t    Dig_T1;
int16_t     Dig_T2;
int16_t     Dig_T3;
uint16_t    Dig_P1;
int16_t     Dig_P2;
int16_t     Dig_P3;
int16_t     Dig_P4;
int16_t     Dig_P5;
int16_t     Dig_P6;
int16_t     Dig_P7;
int16_t     Dig_P8;
int16_t     Dig_P9;
/*** 函    数:BMP280等待忙* 参    数:无* 返 回 值:无*/
void BMP280_WaitBusy(void)
{uint32_t Timeout, state;MySPI_Start();								//SPI起始MySPI_SwapByte(BMP280_STATUS_REG | 0x80);	//交换发送读状态寄存器1的指令Timeout = 100000;							//给定超时计数时间state = MySPI_SwapByte(BMP280_DUMMY_BYTE) >> 3;while ((state & 0x01) == 0x01)	//循环等待忙标志位{Timeout --;if (Timeout == 0)						//自减到0后,等待超时{Serial_Printf("Timeout");/*超时的错误处理代码,可以添加到此处*/break;								//跳出等待,不等了}}MySPI_Stop();								//SPI终止
}/*** 函    数:BMP280写寄存器* 参    数:Address  编程的起始地址* 参    数:Byte 写入一个字节数据* 返 回 值:无*/
void BMP280_WriteData(uint8_t Address, uint8_t Byte)
{MySPI_Start();								//SPI起始MySPI_SwapByte(Address & 0x7F);             //交换发送写寄存器的指令MySPI_SwapByte(Byte);MySPI_Stop();								//SPI终止BMP280_WaitBusy();							//等待忙
}
/*** 函    数:BMP280读寄存器* 参    数:Address 读取数据的起始地址* 参    数:DataArray 用于接收读取数据的数组,通过输出参数返回* 参    数:Count 要读取数据的数量* 返 回 值:无*/
void BMP280_ReadData(uint8_t Address, uint8_t *DataArray, uint8_t Count)
{uint32_t i;MySPI_Start();								//SPI起始MySPI_SwapByte(Address | 0x80);			    //交换发送读寄存器的指令for (i = 0; i < Count; i ++)				//循环Count次{DataArray[i] = MySPI_SwapByte(BMP280_DUMMY_BYTE);	//依次在起始地址后读取数据}MySPI_Stop();								//SPI终止
}
/*** 函    数:BMP280读ID* 参    数:*ID 用于接收读取的数据,通过输出参数返回* 返 回 值:无*/
void BMP280_ReadID(uint8_t *ID)
{MySPI_Start();								//SPI起始MySPI_SwapByte(BMP280_CHIPID_REG | 0x80);	//交换发送读取ID的指令*ID = MySPI_SwapByte(BMP280_DUMMY_BYTE);	//交换接收ID,通过输出参数返回MySPI_Stop();								//SPI终止
}
/*** 函    数:读取转换3个连续寄存器* 参    数:首个读取的寄存器* 返 回 值:合并后的总值*/
long BMP280_RegReadThree(unsigned char addr)
{unsigned char ArrayReadThree[3];               //定义要读取数据的测试数组long temp = 0;BMP280_ReadData(addr, ArrayReadThree, 3);temp = (long)(((unsigned long)ArrayReadThree[0] << 12)|((unsigned long)ArrayReadThree[1] << 4)|((unsigned long)ArrayReadThree[2] >> 4));return temp;
}
/*** 函    数:读取转换2个连续寄存器* 参    数:首个读取的寄存器* 返 回 值:合并后的总值*/
short BMP280_RegReadTwo(unsigned char addr)
{unsigned char ArrayReadTwo[2];               //定义要读取数据的测试数组short temp = 0;BMP280_ReadData(addr, ArrayReadTwo, 2);   //ArrayRead[0]:LSB ArrayRead[1]:MSB temp = (short)ArrayReadTwo[1] << 8;temp |= (short)ArrayReadTwo[0];return temp;
}
/*** 函    数:BMP280初始化* 参    数:无* 返 回 值:无*/
void BMP280_Init(void)
{MySPI_Init();					//先初始化底层的SPIuint8_t Osrs_T = 1;             //Temperature oversampling x 1uint8_t Osrs_P = 3;             //Pressure oversampling x 1uint8_t Mode = 3;               //Normal modeuint8_t T_sb = 5;               //Tstandby 1000msuint8_t Filter = 4;             //Filter  uint8_t Spi3w_en = 0;           //3-wire SPI Disableuint8_t Ctrl_meas_reg = (Osrs_T << 5) | (Osrs_P << 2) | Mode;uint8_t Config_reg    = (T_sb << 5) | (Filter << 2) | Spi3w_en;//状态全部清零BMP280_WriteData(BMP280_RESET_REG, BMP280_RESET_VALUE);BMP280_WriteData(BMP280_CTRLMEAS_REG, Ctrl_meas_reg);BMP280_WriteData(BMP280_CONFIG_REG, Config_reg);Delay_ms(20);Dig_T1 = BMP280_RegReadTwo(BMP280_DIG_T1_LSB_REG);Dig_T2 = BMP280_RegReadTwo(BMP280_DIG_T2_LSB_REG);Dig_T3 = BMP280_RegReadTwo(BMP280_DIG_T3_LSB_REG);Dig_P1 = BMP280_RegReadTwo(BMP280_DIG_P1_LSB_REG);Dig_P2 = BMP280_RegReadTwo(BMP280_DIG_P2_LSB_REG);Dig_P3 = BMP280_RegReadTwo(BMP280_DIG_P3_LSB_REG);Dig_P4 = BMP280_RegReadTwo(BMP280_DIG_P4_LSB_REG);Dig_P5 = BMP280_RegReadTwo(BMP280_DIG_P5_LSB_REG);Dig_P6 = BMP280_RegReadTwo(BMP280_DIG_P6_LSB_REG);Dig_P7 = BMP280_RegReadTwo(BMP280_DIG_P7_LSB_REG);Dig_P8 = BMP280_RegReadTwo(BMP280_DIG_P8_LSB_REG);Dig_P9 = BMP280_RegReadTwo(BMP280_DIG_P9_LSB_REG);}/*** 函    数:BMP280获取温度值* 参    数:无* 返 回 值:温度值*/
int32_t BMP280_GetTemp(void)
{BMP280_S32_t var1, var2, T;BMP280_S32_t adc_T;adc_T = BMP280_RegReadThree(BMP280_TEMPERATURE_MSB_REG);var1 = ((((adc_T >> 3) - ((BMP280_S32_t)Dig_T1 << 1))) * ((BMP280_S32_t)Dig_T2)) >> 11;var2 = (((((adc_T >> 4) - ((BMP280_S32_t)Dig_T1)) * ((adc_T >> 4) - ((BMP280_S32_t)Dig_T1))) >> 12) * ((BMP280_S32_t)Dig_T3)) >> 14;t_fine = var1 + var2;T = (t_fine * 5 + 128) >> 8;return T;
}/*** 函    数:BMP280获取压力值* 参    数:无* 返 回 值:压力值*/
uint32_t BMP280_GetPress(void)
{BMP280_S64_t var1, var2, p;BMP280_S32_t adc_P;adc_P = BMP280_RegReadThree(BMP280_PRESSURE_MSB_REG);var1 = ((BMP280_S64_t)t_fine) - 128000;var2 = var1 * var1 * (BMP280_S64_t)Dig_P6;var2 = var2 + ((var1 * (BMP280_S64_t)Dig_P5) << 17);var2 = var2 + (((BMP280_S64_t)Dig_P4) << 35);var1 = ((var1 * var1 * (BMP280_S64_t)Dig_P3) >> 8) + ((var1 * (BMP280_S64_t)Dig_P2) << 12);var1 = (((((BMP280_S64_t)1) << 47) + var1)) * ((BMP280_S64_t)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 = (((BMP280_S64_t)Dig_P9) * (p>>13) * (p>>13)) >> 25;var2 = (((BMP280_S64_t)Dig_P8) * p) >> 19;p = ((p + var1 + var2) >> 8) + (((BMP280_S64_t)Dig_P7) << 4);return (BMP280_U32_t)p;}

现象

在这里插入图片描述

总结

1.复位寄存器不管写入什么值读出来都是0x00,这个寄存器可写不可读。
2.可以通过大气压强去拓展海拔高度的计算,网上有很多公式的转换,自己选择自己所需的去换算即可。
需要整个工程代码可以在下方评论留言哦!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/12547.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

基于Servlet实现MVC

目录 1.MVC相关概念 核心思想&#xff1a; 主要作用&#xff1a; 2.基于Servlet实现MVC 组成部分&#xff1a; 案例 实验步骤&#xff1a; 新建maven项目SpringMvcDemo 删除src目录并添加子模块MvcServlet ​编辑 导入相关依赖&#xff1a; 编写servlet 注册S…

剪辑师必备50多种擦拭转场/光效过渡效果Premiere Pro模板素材

项目特点&#xff1a; Premiere Pro的擦拭转场和光效闪烁过渡效果 Premiere Pro 2023及更高版本 适用于任何FPS和分辨率的照片和视频 易于使用 包含视频教程 无需插件 拖放方法 高品质 提高视频剪辑效率&#xff0c;节省时间&#xff0c;为视频创作添加独特且专业的转场风格。 …

数字化转型的架构蓝图构建指南:从理论到实践的系统实施路径

企业数字化转型的挑战与架构蓝图的重要性 在数字化浪潮的推动下&#xff0c;企业面临着前所未有的转型压力。传统业务模式和运营流程逐渐被更具弹性和敏捷性的数字化模式所取代&#xff0c;而企业架构蓝图作为战略转型的“导航仪”&#xff0c;能够为企业指明方向。企业架构治…

24.11.10

星期一&#xff1a; 补 23ICPC 合肥 G cf传送门 思路&#xff1a;由使第 k个最大这种条件易联想到二分&#xff0c;但是如何check是个问题 check使用dp&#xff0c;先想到个比较朴素的状态设定&#xff0c;dp【i】【j】…

Ubuntu 的 ROS 操作系统turtlebot3环境搭建

引言 本文介绍如何在Ubuntu系统中为TurtleBot3配置ROS环境&#xff0c;包括安装和配置ROS Noetic的步骤&#xff0c;为PC端控制TurtleBot3提供操作指南。 安装和配置的过程分为PC设置、系统安装、依赖安装等部分&#xff0c;并在最后进行网络配置&#xff0c;确保PC端能够顺利…

《深度学习图像分割》第3章:图像分割关键技术组件

《深度学习图像分割》这本书写写停停&#xff0c;历经三年多&#xff0c;目前在二稿修订中。正式出版之前&#xff0c;计划先在GitHub做逐步的内容和代码开源。 以下为本书第3章节选内容&#xff1a; 近年来&#xff0c;基于深度学习的图像分割技术发展迅猛&#xff0c;涌现出大…

【英特尔IA-32架构软件开发者开发手册第3卷:系统编程指南】2001年版翻译,2-20

文件下载与邀请翻译者 学习英特尔开发手册&#xff0c;最好手里这个手册文件。原版是PDF文件。点击下方链接了解下载方法。 讲解下载英特尔开发手册的文章 翻译英特尔开发手册&#xff0c;会是一件耗时费力的工作。如果有愿意和我一起来做这件事的&#xff0c;那么&#xff…

【论文复现】ChatGPT多模态命名实体识别

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀ChatGPT ChatGPT辅助细化知识增强&#xff01;1. 研究背景2. 模型结构和代码3. 任务流程第一阶段&#xff1a;辅助精炼知识启发式生成第二阶段…

【拉箱子——模拟+DFS】

题目 代码 #include <bits/stdc.h> using namespace std; map<vector<vector<int>>, int> check; vector<vector<int>> mp; int n, m, ans; int dx[] {1, -1, 0, 0}; int dy[] {0, 0, 1, -1}; void dfs(vector<vector<int>>…

2024 年 Postman 进行 Websocket 接口测试的图文教程

Postman 进行 Websocket 接口测试的图文教程

绘制地理空间矢量场

用 Folium 绘制地理空间矢量场 地学和许多应用领域中&#xff0c;数据的视觉化非常重要。尤其是一些表示方向和速度的矢量数据&#xff0c;例如风速、海流、车速等&#xff0c;使用矢量图进行绘制能够更加直观地表达这些数据的特性。 示例数据集选择 为了便于说明矢量场的绘…

深度伪造检测(Deepfake Detection):识别真假影像的关键技术

随着人工智能技术的进步&#xff0c;深度伪造&#xff08;Deepfake&#xff09;技术迅速发展。深度伪造利用深度学习技术生成高仿真的人脸、声音、影像&#xff0c;使得虚假内容可以几乎以假乱真。这一技术最早用于娱乐和广告领域&#xff0c;但逐渐被不良分子用于制造虚假信息…

基于SSD模型的高压输电线障碍物检测系统,支持图像、视频和摄像实时检测【pytorch框架、python源码】

更多目标检测和图像分类识别项目可看我主页其他文章 功能演示&#xff1a; 基于SSD模型的高压输电线障碍物检测系统&#xff0c;支持图像、视频和摄像实时检测【python源码、pytorch框架】_哔哩哔哩_bilibili &#xff08;一&#xff09;简介 基于SSD模型的高压输电线障碍物…

大数据技术与应用专业教学体系如何无缝对接职业技能需求

针对高职院校大数据技术应用专业人才培养与行业需求对接中存在的岗位适应性不足等问题&#xff0c;结合教育部职业技能等级证书要求&#xff0c;本文深入分析了高职院校人才培养对接职业技能等级证书标准的必要性和可行性&#xff0c;并探索了面向岗位职业技能的专业课程体系重…

OPC学习笔记

一. 解决使用milo读取OPC设备字符串类型时&#xff0c;出现中文和特殊符号乱码的情况 解决前&#xff0c;读取字符串&#xff1a;你好 2. 解决后&#xff0c;读取字符串&#xff1a;你好 3. 解决前&#xff0c;读取字符串&#xff1a;165℃ 解决后&#xff0c;读取字符串&am…

数据结构查找-B-树(C语言代码)

#include<stdio.h> #include<stdlib.h>typedef struct Node {int level;//树的阶数int keyNum;//关键字的数量int childNum;//孩子数量int* keys;//关键字数组struct Node** children;//孩子数组struct Node* parent;//父亲指针 }Node;//初始化 Node* initNode(int…

网页web无插件播放器EasyPlayer.js播放器返回错误 Incorrect response MIME type 的解决方式

在使用EasyPlayer.js播放器进行视频流播放时&#xff0c;尤其是在SpringBoot环境中部署静态资源时&#xff0c;可能会遇到“Incorrect response MIME type”的错误&#xff0c;这通常与WebAssembly&#xff08;WASM&#xff09;文件的MIME类型配置有关。 WASM是一种新的代码格式…

[阻塞队列]

目录 1. 阻塞队列 2. 阻塞队列的优点 (1) 实现服务器之间的"低耦合". (2) 实现"削峰填谷"的功能. 3. 阻塞队列代码举例 4. 自己实现阻塞队列 1. 阻塞队列 我们知道, 标准库中原有的队列Queue及其子类, 都是线程不安全的, 所以java封装了一个名为&quo…

DCA-X 采样示波器

DCA-X 采样示波器 苏州新利通 | 综述 | DCA-X 宽带采样示波器属于我们的数字通信分析仪&#xff08;DCA&#xff09;系列。 这些示波器都是模块化平台&#xff0c;可对 50 Mb/s 到 224 Gb/s 的高速数字设计执行精准的测量。 您可以选择各种插入式模块来配置 DCA-X 主机&…

将webserver部署到公网(使用阿里云服务器)

阿里云轻量应用服务器介绍 这里我是用的是阿里云进行部署&#xff0c;阿里云推出的相关产品包括 云服务器 ECS 和轻量应用服务器。阿里云的指引和说明我觉得还是比较清楚详细的&#xff0c;适合新手。 先来介绍相关的一些名词&#xff1a; 云服务器 ECS&#xff08;Elastic …