仿正点原子驱动BMP280气压传感器实例

文章目录

前言

一、寄存器头文件定义

二、设备树文件中添加节点

 三、驱动文件编写

四、编写驱动测试文件并编译测试

总结


前言

本文驱动开发仿照正点原子的iic驱动实现,同时附上bmp280的数据手册,可访问下面的链接:

BMP280_Bosch(博世)_BMP280中文资料_PDF手册_价格-立创商城下载数据手册。


一、寄存器头文件定义

        在查看数据手册时,可发现bmp280器件对各个寄存器,如数据,校准,采样,滤波等等寄存器进行定义,如下代码所示:

#ifndef BMP280_H
#define BMP280_H#define BMP280_ADDR    	0x76	/* BMP280器件地址*//* BMP280寄存器 */
#define BMP280_ID_REG          0xD0  /* 芯片ID寄存器,值是0x58 */
#define BMP280_RESET_REG       0xE0  /* 复位寄存器 */
#define BMP280_STATUS_REG      0xF3  /* 状态寄存器 */
#define BMP280_CTRL_MEAS_REG   0xF4  /* 测量控制寄存器 */
#define BMP280_CONFIG_REG      0xF5  /* 配置寄存器 *//* 数据寄存器 */
#define BMP280_PRESSURE_MSB    0xF7  /* 压力数据高字节 */
#define BMP280_PRESSURE_LSB    0xF8  /* 压力数据中字节 */
#define BMP280_PRESSURE_XLSB   0xF9  /* 压力数据低字节 */
#define BMP280_TEMP_MSB        0xFA  /* 温度数据高字节 */
#define BMP280_TEMP_LSB        0xFB  /* 温度数据中字节 */
#define BMP280_TEMP_XLSB       0xFC  /* 温度数据低字节 *//* 校准参数寄存器 - 存储补偿计算需要的出厂校准数据 */
#define BMP280_DIG_T1_LSB_REG  0x88
#define BMP280_DIG_T1_MSB_REG  0x89
#define BMP280_DIG_T2_LSB_REG  0x8A
#define BMP280_DIG_T2_MSB_REG  0x8B
#define BMP280_DIG_T3_LSB_REG  0x8C
#define BMP280_DIG_T3_MSB_REG  0x8D
#define BMP280_DIG_P1_LSB_REG  0x8E
#define BMP280_DIG_P1_MSB_REG  0x8F
#define BMP280_DIG_P2_LSB_REG  0x90
#define BMP280_DIG_P2_MSB_REG  0x91
#define BMP280_DIG_P3_LSB_REG  0x92
#define BMP280_DIG_P3_MSB_REG  0x93
#define BMP280_DIG_P4_LSB_REG  0x94
#define BMP280_DIG_P4_MSB_REG  0x95
#define BMP280_DIG_P5_LSB_REG  0x96
#define BMP280_DIG_P5_MSB_REG  0x97
#define BMP280_DIG_P6_LSB_REG  0x98
#define BMP280_DIG_P6_MSB_REG  0x99
#define BMP280_DIG_P7_LSB_REG  0x9A
#define BMP280_DIG_P7_MSB_REG  0x9B
#define BMP280_DIG_P8_LSB_REG  0x9C
#define BMP280_DIG_P8_MSB_REG  0x9D
#define BMP280_DIG_P9_LSB_REG  0x9E
#define BMP280_DIG_P9_MSB_REG  0x9F/* 复位值 */
#define BMP280_RESET_VALUE     0xB6/* 工作模式 */
#define BMP280_SLEEP_MODE      0x00
#define BMP280_FORCED_MODE     0x01
#define BMP280_NORMAL_MODE     0x03/* 过采样设置 */
#define BMP280_OSRS_T_SKIP     0x00 /* 温度测量跳过 */
#define BMP280_OSRS_T_X1       0x20 /* 温度测量1倍过采样 */
#define BMP280_OSRS_T_X2       0x40
#define BMP280_OSRS_T_X4       0x60
#define BMP280_OSRS_T_X8       0x80
#define BMP280_OSRS_T_X16      0xA0#define BMP280_OSRS_P_SKIP     0x00 /* 压力测量跳过 */
#define BMP280_OSRS_P_X1       0x04 /* 压力测量1倍过采样 */
#define BMP280_OSRS_P_X2       0x08
#define BMP280_OSRS_P_X4       0x0C
#define BMP280_OSRS_P_X8       0x10
#define BMP280_OSRS_P_X16      0x14/* 滤波器设置 */
#define BMP280_FILTER_OFF      0x00
#define BMP280_FILTER_COEF_2   0x04
#define BMP280_FILTER_COEF_4   0x08
#define BMP280_FILTER_COEF_8   0x0C
#define BMP280_FILTER_COEF_16  0x10/* 待机时间设置 */
#define BMP280_STANDBY_0_5_MS  0x00
#define BMP280_STANDBY_62_5_MS 0x20
#define BMP280_STANDBY_125_MS  0x40
#define BMP280_STANDBY_250_MS  0x60
#define BMP280_STANDBY_500_MS  0x80
#define BMP280_STANDBY_1000_MS 0xA0
#define BMP280_STANDBY_2000_MS 0xC0
#define BMP280_STANDBY_4000_MS 0xE0/* 结构体定义 */
struct bmp280_calib_param {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;
};#endif 

二、设备树文件中添加节点

  在设备树文件中的i2c1节点中添加子节点,如下:,其中bmp280的器件地址即reg定义为0x76,使用的引脚定义是SCL使用:MX6UL_PAD_UART4_TX_DATA__I2C1_SCL  SDA使用:MX6UL_PAD_UART4_RX_DATA__I2C1_SDA及完成设备树的节点定义,加载到内核:

 查看节点:

 三、驱动文件编写

(1)首先就是字符设备的结构体定义:添加了温度和气压数据。

struct bmp280_dev {dev_t devid;               // 设备号struct cdev cdev;          // 字符设备结构体struct class *class;       // 类struct device *device;     // 设备struct device_node *nd;    // 设备树节点int major;                 // 主设备号void *private_data;        // I2C客户端指针int temperature;           // 温度值(单位:0.01℃)int pressure;              // 气压值(单位:Pa)struct bmp280_calib_param calib_param; // 校准参数int32_t t_fine;            // 温度补偿中间值
};

 (2)接着完成对读寄存器函数的编写:,使用i2c_msg来加载数据,发送的数据是bmp280的器件地址以及加载要写入的数据,并调用i2c_transfer来完成数据发送

 (3)写寄存器:发送的数据位器件地址0x76+寄存器地址+数据

 (4)读取寄存器的校准参数:从0x88开始两个字节的读,

(5)计算实际的温度和气压值,参考数据手册给出的计算公式和实现例程代码,有兴趣的话可以仔细看看手册:

 仿照实现的计算函数:
 

static int32_t bmp280_compensate_temperature(struct bmp280_dev *dev, int32_t adc_T)
{int32_t var1, var2, temperature;var1 = ((((adc_T >> 3) - ((int32_t)dev->calib_param.dig_T1 << 1))) * ((int32_t)dev->calib_param.dig_T2)) >> 11;var2 = (((((adc_T >> 4) - ((int32_t)dev->calib_param.dig_T1)) * ((adc_T >> 4) - ((int32_t)dev->calib_param.dig_T1))) >> 12) * ((int32_t)dev->calib_param.dig_T3)) >> 14;dev->t_fine = var1 + var2;temperature = (dev->t_fine * 5 + 128) >> 8;return temperature;
}/** @description  : 计算实际气压值,避免使用64位除法* @param - dev  : bmp280设备* @param - adc_P: 原始气压ADC值* @return       : 实际气压值(Pa)*/
static uint32_t bmp280_compensate_pressure(struct bmp280_dev *dev, int32_t adc_P)
{int32_t var1, var2;uint32_t p;var1 = (((int32_t)dev->t_fine) >> 1) - (int32_t)64000;var2 = (((var1 >> 2) * (var1 >> 2)) >> 11) * ((int32_t)dev->calib_param.dig_P6);var2 = var2 + ((var1 * ((int32_t)dev->calib_param.dig_P5)) << 1);var2 = (var2 >> 2) + (((int32_t)dev->calib_param.dig_P4) << 16);var1 = (((dev->calib_param.dig_P3 * (((var1 >> 2) * (var1 >> 2)) >> 13)) >> 3) + ((((int32_t)dev->calib_param.dig_P2) * var1) >> 1)) >> 18;var1 = ((((32768 + var1)) * ((int32_t)dev->calib_param.dig_P1)) >> 15);if (var1 == 0)return 0; // 避免除零错误p = (((uint32_t)(((int32_t)1048576) - adc_P) - (var2 >> 12))) * 3125;if (p < 0x80000000)p = (p << 1) / ((uint32_t)var1);elsep = (p / (uint32_t)var1) * 2;var1 = (((int32_t)dev->calib_param.dig_P9) * ((int32_t)(((p >> 3) * (p >> 3)) >> 13))) >> 12;var2 = (((int32_t)(p >> 2)) * ((int32_t)dev->calib_param.dig_P8)) >> 13;p = (uint32_t)((int32_t)p + ((var1 + var2 + dev->calib_param.dig_P7) >> 4));return p;
}

(6) 实现读取数据函数定义:从数据寄存器0xf7读到0xfc

(7)剩下就是完成对bmp280初始化定义,设备文件的操作函数定义,如下所示即为,设备初始化代码:,主要完成对设备的唤醒,校准以及采样配置:

static int bmp280_init_sensor(struct bmp280_dev *dev)
{uint8_t chip_id;/* 1. 读取芯片ID,确认设备存在 */chip_id = bmp280_read_reg(dev, BMP280_ID_REG);printk("BMP280 Chip ID: 0x%02X\n", chip_id);if (chip_id != 0x58) {//0x76地址存储的是0x58printk("BMP280 Chip ID not matching, expected 0x58, got 0x%02X\n", chip_id);return -ENODEV;}/* 2. 软复位 */bmp280_write_reg(dev, BMP280_RESET_REG, BMP280_RESET_VALUE);mdelay(10); // 等待复位完成/* 3. 读取校准参数 */bmp280_read_calibration_data(dev);/* 4. 配置传感器 * - 设置过采样: 温度16x,压力16x* - 设置工作模式: 正常模式*/bmp280_write_reg(dev, BMP280_CONFIG_REG, BMP280_FILTER_COEF_16 | BMP280_STANDBY_500_MS);bmp280_write_reg(dev, BMP280_CTRL_MEAS_REG, BMP280_OSRS_T_X16 | BMP280_OSRS_P_X16 | BMP280_NORMAL_MODE);mdelay(100); // 等待配置生效return 0;
}

 如上即为主要关键驱动代码的定义。

四、编写驱动测试文件并编译测试

类似正点原子的驱动测试文件:

打开设备并读取到数据时,间隔2s打印一次数据

 编译加载驱动文件和驱动测试文件:

测试结果:

 

能够正确获取数据并进行打印,完成驱动!!!


总结

通过对IIC驱动的学习测试以及完成对具体iic设备的驱动来获取数据,对嵌入式linux的驱动了解更加深刻了。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

论坛系统(中-1)

软件开发 编写公共代码 定义状态码 对执⾏业务处理逻辑过程中可能出现的成功与失败状态做针对性描述(根据需求分析阶段可以遇见的问题提前做出定义)&#xff0c;⽤枚举定义状态码&#xff0c;先定义⼀部分&#xff0c;业务中遇到新的问题再添加 定义状态码如下 状态码类型描…

E+H流量计通过Profibus DP主站转Modbus TCP网关与上位机轻松通讯

EH流量计通过Profibus DP主站转Modbus TCP网关与上位机轻松通讯 在现代工业自动化的广阔舞台上&#xff0c;Profibus DP与Modbus TCP这两种通信协议各领风骚&#xff0c;它们在不同的应用场景中发挥着举足轻重的作用。但工业生产的复杂性往往要求不同设备、系统之间能够顺畅沟…

服务器中存储空间不足该怎么办?

服务器作为存储数据信息的重要网络设备&#xff0c;随着企业业务的不断拓展&#xff0c;所需要存储的数据信息也在不断增加&#xff0c;最终会导致服务器中存储空间不足&#xff0c;这不仅会影响到服务器系统性能&#xff0c;还会造成业务无法正常执行&#xff0c;那么&#xf…

C++23 views::chunk_by (P2443R1) 详解

文章目录 引言C23 范围库概述范围视图&#xff08;Range Views&#xff09;范围算法&#xff08;Range Algorithms&#xff09;范围适配器&#xff08;Range Adapters&#xff09; std::views::chunk_by 介绍基本概念特性使用场景 示例代码简单示例自定义谓词示例 总结 引言 在…

零碳园区能源系统-多能互补体系

构建以可再生能源为核心的零碳园区能源系统&#xff0c;需整合光储直柔、光伏发电、微电网、氢能与储能技术&#xff0c;通过多能协同与智能调控实现能源生产、存储、消费全链条优化。以下是系统性实施方案&#xff1a; 一、系统架构设计 1. 多能互补体系 &#xff08;图示&a…

elastic search学习

首先在自己电脑上安装elastic search。安装成功后&#xff0c;查看ES是否启动成功。 安装过程参考&#xff1a;ElasticSearch入门1: mac 安装 - 霜井 - 博客园 安装完成后&#xff0c;直接执行bin目录中的elastic search命令后&#xff0c;就可以启动成功&#xff01; 在网页…

mysql8常用sql语句

查询结果带行号 -- 表名为 mi_user&#xff0c; 假设包含列 id &#xff0c;address SELECT ROW_NUMBER() OVER (ORDER BY id) AS row_num, t.id, t.address FROM mi_user t ; SELECT ROW_NUMBER() OVER ( ) AS row_num, t.id, t.address FROM mi_user t ; 更新某列数…

Memcached 服务搭建和集成使用的详细步骤示例

以下是 Memcached 服务搭建和集成使用的详细步骤示例&#xff1a; 一、搭建 Memcached 服务 安装 Memcached Linux 系统 yum 安装&#xff1a;执行命令 yum install -y memcached memcached-devel。源码安装 下载源码&#xff1a;wget http://www.memcached.org/files/memcach…

2. 盒模型/布局模块 - 响应式产品展示页_案例:电商产品网格布局

2. 盒模型/布局模块 - 响应式产品展示页 案例&#xff1a;电商产品网格布局 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title></head><style type"text/css">:root {--primary-color…

Go基于plugin的热更新初体验

背景 对于一个部署在生产环境的项目来说&#xff0c;我们希望当代码出现bug的时候&#xff0c;可以不用重启进程而达到动态修改代码的目的—— 这就是代码热部署&#xff01; 使用java做游戏服务器&#xff0c;最大的好处是&#xff0c;当代码出现bug&#xff0c;可以直接热…

【RabbitMQ】工作队列和发布/订阅模式的具体实现

文章目录 建立连接工作队列模式实现创建队列和交换机生产者代码消费者代码运行程序启动消费者启动生产者 发布/订阅模式实现创建队列和交换机生产者代码创建交换机声明两个队列绑定队列和交换机发送消息完整代码 消费者代码完整代码 运行程序启动生产者启动消费者 建立连接 我…

Codeforces Round 998 (Div. 3)

A. Fibonacciness 题目大意 给你四个数字abde&#xff0c;让你找到一个中间值c&#xff0c;问 a b c a b c abc &#xff0c; b c d b c d bcd &#xff0c; c d e c d e cde 最多能有几个式子成立 解题思路 显然最多就六种情况&#xff0c;暴力枚举即可 代…

火山引擎发展初始

火山引擎是字节跳动旗下的云计算服务品牌&#xff0c;其云服务业务的启动和正式商业化时间线如下&#xff1a; 1. **初期探索&#xff08;2020年之前&#xff09;** 字节跳动在早期为支持自身业务&#xff08;如抖音、今日头条等&#xff09;构建了强大的基础设施和技术中…

【认知思维】光环效应:第一印象的持久力量

什么是光环效应 光环效应&#xff08;Halo Effect&#xff09;是指人们倾向于让对某人或某物的一个显著特质的印象影响对其他特质的评价的认知偏差。简单来说&#xff0c;当我们对某人的一个特质&#xff08;如外表、智力或某项技能&#xff09;形成积极印象时&#xff0c;我们…

Java Solon v3.3.0 发布(国产优秀应用开发基座)

Solon 框架&#xff01; Solon 是新一代&#xff0c;Java 企业级应用开发框架。从零开始构建&#xff08;No Java-EE&#xff09;&#xff0c;有灵活的接口规范与开放生态。采用商用友好的 Apache 2.0 开源协议&#xff0c;是“杭州无耳科技有限公司”开源的根级项目&#xff…

力扣-104.二叉树的最大深度

题目描述 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 class Solution { public:int maxDepth(TreeNode* root) {if(!root){return 0;}return max(maxDepth(root->left), maxDepth(root->…

单反和无反(私人笔记)

① 单反相机&#xff1a; 定义&#xff1a; 单反相机&#xff08;Single-Lens Reflex&#xff0c;SLR&#xff09;是一种带有反光镜结构的数码相机。光线通过镜头进入后&#xff0c;先被反光镜反射到五棱镜/五面镜&#xff0c;再通过取景器进入人眼。按下快门时&#xff0c;反…

超详细讲解C语言转义字符\a \b \r \t \? \n等等

转义字符 C语言有一组字符很特殊&#xff0c;叫做转义字符&#xff0c;顾名思义&#xff0c;改变原来的意思的字符。 1 \? ??)是一个三字母词&#xff0c;在以前的编译器它会被编译为] (??会被编译为[ 因此在以前输入(are you ok ??)就会被编译为are you ok ] 解决这个…

Java Spring MVC -01

SpringMVC 是一种基于 的实现 MVC 设计模式的请求驱动类型的轻量级 Web 框架&#xff0c;属于 Spring FrameWork 的后续产品&#xff0c;已经融合在 Spring Web Flow 中。 First:SpringMVC-01-SpringMVC 概述 SpringMVC 是 Spring 框架的一个模块&#xff0c;用于构建 Web 应…

Spring MessageSource 详解:如何在国际化消息中传递参数

在开发多语言应用程序时,Spring 的 MessageSource 是处理国际化(i18n)文本的核心组件。它允许我们根据用户的 Locale (区域设置) 显示不同的消息。然而,很多时候我们的消息并不是静态的,而是需要包含动态数据,比如用户名、数量、文件名等。这时,我们就需要在获取国际化消…