目录

一、I2C总线协议

二、I2C协议的两种从机应对方式

三、传感器信息

四、工程创建及引脚配置

五、STCH1传感器实现

六、LTR_553ALS传感器(light sensor [ALS] and proximity sensor)

七、BMP280传感器(气压传感器)

八、LSM6DSL传感器(加速度及角速度)

九、MMC3680KJ传感器(三轴磁传感器)

十、驱动代码调用及数据采集与展示

十一、附件


一、I2C总线协议

I2C(Inter Integrated Circuit)总线是 PHILIPS 公司开发的一种半双工、双向二线制同步串行总线。I2C 总线传输数据时只需两根信号线,一根是双向数据线 SDA(serial data),另一根是双向时钟线 SCL(serial clock)。SPI 总线有两根线分别用于主从设备之间接收数据和发送数据,而 I2C 总线只使用一根线进行数据收发。I2C 以主从的方式工作,并允许同时有多个主设备存在,每个连接到总线上的器件都有唯一的地址,主设备启动数据传输并产生时钟信号,从设备被主设备寻址,同一时刻只允许有一个主设备。

I2C 总线主要的数据传输格式:

当总线空闲时,SDA 和 SCL 都处于高电平状态,当主机要和某个从机通讯时,会先发送一个开始条件,然后发送从机地址和读写控制位,接下来传输数据(主机发送或者接收数据),数据传输结束时主机会发送停止条件。传输的每个字节为8位,高位在前,低位在后。

开始标记:SCL 为高电平时,主机将 SDA 拉低,表示数据传输即将开始;

从设备地址(或叫从机地址):主机发送的第一个字节为从机地址,高 7 位为地址,最低位为 R/W 读写控制位,1 表示读操作,0 表示写操作。一般从机地址有 7 位地址模式和 10 位地址模式两种,如果是 10 位地址模式,需要用两个字节(16位)来表述,第一个字节的头 7 位 是 11110XX 的组合,其中最后两位(XX)是 10 位地址的两个最高位,第二个字节为 10 位从机地址的剩下8位:       

应答: 每传输完成一个字节的数据,接收方就需要回复一个 ACK(acknowledge)。写数据时由从机发送 ACK,读数据时由主机发送 ACK。当主机读到最后一个字节数据时,可发送 NACK(Not acknowledge)然后跟停止条件。

数据: 从机地址发送完后可能会发送一些指令,依从机而定,然后开始传输数据,由主机或者从机发送,每个数据为 8 位,数据的字节数没有限制。

重复开始: 在一次通信过程中,主机可能需要和不同的从机传输数据或者需要切换读写操作时,主机可以再发送一个开始条件。

停止标记: 在 SDA 为低电平时,主机将 SCL 拉高并保持高电平,然后在将 SDA 拉高,表示传输结束。

二、I2C协议的两种从机应对方式

从机对I2C协议通讯我本人认为提供了两种实现方式:

寄存器直接访问方式:这种方式是从机直接将其参数、采集数据放置存储区域,并将存储地址暴露给主机,让主机直接按存储地址获取数据,或修改存储地址上的数据,从机感知数据变化做应对处理,从而实现对从机下行控制。我个人管这种方式叫从机地址+寄存器地址。

命令接口间接访问方式:这种方式从机对主机采用问答式服务,不会提供存储地址给主机,只是给出相关指令信息给主机,这些指令相当于从机对外提供的业务接口,例如主机需要读取某个数值,需要先向从机发送读取指令,从机将需要的数据做准备并等待主机下一次指令,主机再去读取数据。我个人管这种方式叫从机地址+CMD指令。

我们再看HLA标准库提供I2C接口API,也支持这两种方式:

//从机地址+CMD
HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,//从机地址+寄存器地址
HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress,uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress,uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout);

PS:I2C在写入和读取时,从机地址是不同的,例如一般“读取从机地址=写入从机地址+1”,在实际使用HAL标准库已经做了内部处理,所以我们就不管读还是写操作,只传入写地址即可,HAL库的读写函数会调用I2C_TransferConfig来完成相关配置,包括从机地址问题,开始条件问题、时钟问题等。

/*** @brief  Handles I2Cx communication when starting transfer or during transfer (TC or TCR flag are set).* @param  hi2c I2C handle.* @param  DevAddress Specifies the slave address to be programmed.* @param  Size Specifies the number of bytes to be programmed.*   This parameter must be a value between 0 and 255.* @param  Mode New state of the I2C START condition generation.*   This parameter can be one of the following values:*     @arg @ref I2C_RELOAD_MODE Enable Reload mode .*     @arg @ref I2C_AUTOEND_MODE Enable Automatic end mode.*     @arg @ref I2C_SOFTEND_MODE Enable Software end mode.* @param  Request New state of the I2C START condition generation.*   This parameter can be one of the following values:*     @arg @ref I2C_NO_STARTSTOP Don't Generate stop and start condition.*     @arg @ref I2C_GENERATE_STOP Generate stop condition (Size should be set to 0).*     @arg @ref I2C_GENERATE_START_READ Generate Restart for read request.*     @arg @ref I2C_GENERATE_START_WRITE Generate Restart for write request.* @retval None*/
static void I2C_TransferConfig(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t Size, uint32_t Mode,uint32_t Request)

三、传感器信息

本文采用STM32L496VGTX的ali开发板, 该开发板已经连接了以下5个传感器,下图蓝色部分标注的5个传感器就是本文需要实现的(音频、摄像头不仅仅I2C接口,还需要其他接口支持,暂时不在本文展开):

这些传感器的硬件原理图如下:

1)SHTC1温湿度传感器

2)LTR-553ALS光感及接近传感器,注:它除了I2C支持,还需要一个额外的GPIO引脚

3)BMP280气压传感器

4) LSM6DSL加速度及角速度传感器

5) MMC3680KJ三轴磁传感器

这些传感器都是通过I2C总线连接到STM32L496VGT3的MCU上,MCU的I2C引脚接口如下:

另外 LTR-553ALS还需要一个GPIO引脚辅助

四、工程创建及引脚配置

本文新建了一个STM32L496VGTX_I2C工程,并移植了前面已经实现过的串口调试输出及OLED屏幕输出文字的源码,详细见:

cubeIDE开发, stm32调试信息串口通信输出显示_py_free的博客-CSDN博客

cubeIDE开发, stm32的OLED点亮及字符显示设计(基于SPI通信)_py_free的博客-CSDN博客

假设已经基于STM32L496VGTX的MCU上实现了lpusart调试信息输出,和SPI1的oled屏幕显示,接下来配置I2C2和I2C4接口及PA15引脚。

1)开启I2C2配置,参数保持默认,注意从机地址7bit长度的

2)开启I2C2的DMA支持和中断支持(本文代码实现暂时没采用DMA,只是先开启)

3)同样开启I2C4接口以及开启其DMA功能和中断功能

I2C4的DMA及中断功能

4) I2C2、I2C4引脚参数配置

5)配置LTR-553ALS传感器需要的PA15引脚,并开启该PA15的中断功能支持

配置完成后点击保存或生成代码按钮,完成图形配置到代码生产的输出。

五、STCH1传感器实现

在ICore源码目录下添加STCH1文件夹,并在该文件夹下添加STCH1.h和STCH1.c文件作为STCH1传感器的驱动文件。

本人去网上下载了一份STCH1传感器的数据手册,读取分析发现采用前面所述的从机地址+CMD指令方式,先明确STCH1的设备地址是0X70,而开发板给出的地址是0XE0,STCH1集成到开发板是经过了微调(0XE0=(0X70<<1)),那我们采用0XE0就好:

MCU通过I2C协议读取STCH1传感器的温湿度数据需要经历以下几个过程:

1)STCH1传感器的ID号确认,简单描述就是向STCH1写入两字节的0XEF 0XC8(告诉STCH1我要稍后来读取这个注册地址的数据,请准备好),再读取两个字节数据(16bit),取0~5bit的数据如果是0X07就表明OK。

2)STCH1软重置要求,就是向STCH1写入两字节(16bit)的0X80 0X5D数据即可实现软重置。

3)STCH1读取数据前,需要明确数据读取组合格式,意思就是I2C开启Clock Stretching时,向STCH1写入16bit的0X7C 0XA2数据,再去读取数据时就是温度数据在前、湿度数据灾后,其他类似,如下图,是否开启Clock Stretching和是否温度在前组合共有四种组合方式。

4)下图指出如何读取数据,在告知数据组合方式后,需要读取六字节(6*8 bit)的数据,其中第三和第六字节是CRC数据,剩余的是温湿度数据,第一、第二字节组成一个具体数据,最高有效位(MSB)在前、最低有效位(LSB)在后,第三、第四字节组成一个具体数据,第一、第二字节是温度还是湿度数据,由读取前写入指令确定,详见3)。

5)数据换算到的原数据,需要经过换算公式换算后,才能表示实际的温湿度数值。

6)伪代码设计:

init:
write 0xef 0xc8 to 0XE0
read  两字节Data     from 0XE0
取出 Data的0~5位数据与0X07比较完成ID识别
write 0X80, 0X5D to 0XE0 完成重置read data
write 读取方式指令,例如0X7C 0XA2 to 0XE0
read 六字节Data from 0XE0
Data 1、2字节为温度原始数据,经换算公式获得实际温度值
Data 3、4字节为湿度原始数据,经换算公式获得实际湿度值

7)源码STCH1.h和STCH1.c文件内容如下:

STCH1.h

#ifndef SHTC1_SHTC1_H_
#define SHTC1_SHTC1_H_#include "main.h"void shtc1_init();
uint8_t read_ht(float *cur_humi,float *cur_temp);#endif /* SHTC1_SHTC1_H_ */

STCH1.c,注意的是由于STCH1传感器采用从机地址+CMD指令方式实现,所以驱动文件调用的是HAL_I2C_Master_Transmit和HAL_I2C_Master_Receive完成I2C数据收发,有别于后面涉及的4种传感器。

#include <stdio.h>
#include "SHTC1.h"extern I2C_HandleTypeDef hi2c2;#define SHTC1_I2C_SLAVE_ADDR 0x70#define SHTC1_ADDR_TRANS(n) ((n) << 1)
#define SHTC1_I2C_ADDR SHTC1_ADDR_TRANS(SHTC1_I2C_SLAVE_ADDR)/* delays for non-blocking i2c commands, both in ms */
#define SHTC1_NONBLOCKING_WAIT_TIME_HPM 15
#define SHTC1_NONBLOCKING_WAIT_TIME_LPM 1#define SHTC1_CHIP_ID_VAL 0x07
#define SHTC1_ID_REG_MASK 0x1f#define SHTC1_CMD_LENGTH 2
#define SHTC1_RESPONSE_LENGTH 6#define SHTC1_DATA_READ_MIN_INTERVAL 200 /* in millisecond */typedef enum
{FLAG_INIT_TEMP = 0,FLAG_INIT_HUMI,
} FLAG_INIT_BIT;typedef enum
{SHTC1_CMD_read_id_reg,SHTC1_CMD_measure_blocking_hpm,SHTC1_CMD_measure_nonblocking_hpm,SHTC1_CMD_measure_blocking_lpm,SHTC1_CMD_measure_nonblocking_lpm,SHTC1_CMD_END
} CMD_SHTC1_ENUM;uint8_t SHTC1_id_check()
{HAL_StatusTypeDef hi2c2_status = 0x00;uint8_t data[SHTC1_CMD_LENGTH] = { 0xef, 0xc8 };hi2c2_status = HAL_I2C_Master_Transmit(&hi2c2,SHTC1_I2C_ADDR,data,SHTC1_CMD_LENGTH,1000);if(HAL_OK!=hi2c2_status){printf("set SHTC1_id error\r\n");return 1;}uint8_t value[2] = { 0 };hi2c2_status = HAL_I2C_Master_Receive(&hi2c2,SHTC1_I2C_ADDR,value,2,1000);if(HAL_OK!=hi2c2_status){printf("get SHTC1_id error\r\n");return 1;}printf("SHTC1_id:0X%02X%02X\r\n",value[0],value[1]);//SHTC1_ID_REG_MASK=0X1F,SHTC1_CHIP_ID_VAL=0X07if ((value[1] & SHTC1_ID_REG_MASK) != SHTC1_CHIP_ID_VAL) {return 1;}printf("SHTC1_id check successfully\r\n");return 0;
}
//软重置
void reSet()
{HAL_StatusTypeDef hi2c2_status = 0x00;uint8_t temp[2] = {0X80, 0X5D};hi2c2_status = HAL_I2C_Master_Transmit(&hi2c2,SHTC1_I2C_ADDR,temp,2,1000);if(HAL_OK!=hi2c2_status){printf("SHTC1 reset error\r\n");return;}printf("SHTC1 reSet successfully\r\n");
}/*SHTC1提供了定义测量期间的传感器行为以及测量结果的传输序列的可能性。*每个测量命令都会同时触发温度测量和湿度测量。*bool enabled时钟是否启用,bool humi是否在前*/
void clock_set(uint8_t enabled,uint8_t humi)
{uint8_t temp[2] = {0, 0};if(enabled){/*时钟拉伸 已启用*/if(humi){/*湿度、温度*/temp[0] = 0x5C;temp[1] = 0x24;}else{/*温度、湿度*/temp[0] = 0x7C;temp[1] = 0xA2;}}else{/*时钟拉伸 丧失能力的*/if(humi){/*湿度、温度*/temp[0] = 0x58;temp[1] = 0xE0;}else{/*温度、湿度*/temp[0] = 0x78;temp[1] = 0x66;}}printf("out model:");for(uint8_t i=0; i<2; i++ ){printf("%02X ", temp[i]);}printf("\n");HAL_I2C_Master_Transmit(&hi2c2,SHTC1_I2C_ADDR,temp,2,1000);
}void shtc1_init()
{SHTC1_id_check();reSet();HAL_Delay(1000);/*温度在前*/clock_set(1,0);HAL_Delay(1000);
}uint8_t read_ht(float *cur_humi,float *cur_temp)
{/* 1、先发送要读取确认 */clock_set(1,0);/*时钟拉伸 已启用 && 温度、湿度->0X7C 0XA2*//* 2、读取数据 */;HAL_StatusTypeDef hi2c2_status = 0x00;uint8_t retval[SHTC1_RESPONSE_LENGTH] = {0x00};hi2c2_status = HAL_I2C_Master_Receive(&hi2c2, SHTC1_I2C_ADDR, retval, 6, 1000);if(HAL_OK!=hi2c2_status)return 1;else{uint32_t val01 = (retval[0] << 8 | retval[1]);uint32_t val02 = (retval[3] << 8 | retval[4]);printf("val01:%d,val02:%d\n",(int)val01,(int)val02);/* 温度数据转换 */*cur_temp =  val01 * 175.0 / (1 << 16) - 45;//*cur_temp = (int32_t)((21875 * val01) >> 13) - 45000;//千位表示/* 湿度数据转换 */*cur_humi = val02 * 100.0 / (1 << 16);//*cur_humi = (uint32_t)((12500 * val02) >> 13);//lpusartprintf("\nread shtc1 sensor humidity   : %d.%d\n", (int)(*cur_humi), (int)((*cur_humi) * 100) % 100);if( (*cur_temp) >= 0 ){printf("read shtc1 sensor temperature: %d.%d\n", (int)(*cur_temp), (int)((*cur_temp) * 100) % 100);}else{printf("read shtc1 sensor temperature: %d.%d\n", (int)(*cur_temp), (int)(-(*cur_temp) * 100) % 100);}return 0;}
}

六、LTR_553ALS传感器(light sensor [ALS] and proximity sensor)

在ICore目录下,创建LTR-553ALS-WA文件夹,并在该文件夹下创建LTR-553ALS-WA.h和LTR-553ALS-WA.c源码文件,作为LTR-553ALS传感器驱动。

本人在网上下载了一份LTR-553ALS-WA的数据手册文档,进行分析其实是我们前面所述的从机地址+寄存器地址方式来实现的,那么主要就是分析寄存器地址及相关含义即可,从机地址如下(0X46=0X23<<1),显然开发板做了调整:

1)先看LTR-553ALS的I2C通信格式,下图是写入通信,典型从机地址(Slave address)+寄存器地址(Register Address)方式+写入数据(Register Command)。

读通信方式,类似写入方式。

2)下图是LTR-553ALS-WA的总寄存器地址描述表,可以看出0X80是ALS(光感应)的模式控制、重置的功能地址,OX81是PS(接近感应)的模式控制,0X82是PS_LED取值地址,0X84、0X85是ALS、PS的激活地址,0X86、0X87是设备的ID验证地址,0X88、0X89、0X8A、0X8B是ALS 数值存储地址,0X8D、0X8E是PS数值存储地址。

3)设备ID验证,就是读取0X86的PART_ID数据,正确返回值是0X92,读取0X87的manufac_id数据,正确返回值是0X05.

4)ALS的启用,主要:1.就是向0X85写入激活mode。设置检测time 和 rate,

2.向0X80写入contr mode,开启或关闭ACTIVE,如果想保留原来设置,可先读取oldconf,再oldconf&需要的设值,重新写入实现增加或删减支持模式,0X80还支持 software reset.

5)PS的启用,类似于ALS设置,0X84开启Meas Rate激活PS,具体功能支持参考一下图。

向0X81写入数据设置contr mode,开启或关闭ACTIVE

6)ALS数据读取,最低有效位在前,0X88、0X89读取通道1(ch1)数据

0X8A、0X8B读取通道0(ch0)数据

7)读取PS数据,访问0X8D、0X8E地址,最低有效位在前。

8)读取ALS(光感应)、PS(接近感应)数据伪代码实现:

从机地址是0x46
Init:
read data1 from 从机0x46 寄存地址 0X86
read data2 from 从机0x46 寄存地址 0X87
确保data1=0x92,data2=0x05ALS init
write 设值 to 从机0x46 寄存地址 0X85 设置Measure Time and Rate
write 设值 to 从机0x46 寄存地址 0X80 设置 ActivePS init
write 设值 to 从机0x46 寄存地址 0X84 设置Measure Rate
write 设值 to 从机0x46 寄存地址 0X81 设置 Active读取数据ALS read 前提确保0X80 设置 Active开启
read data1~4 from 从机0x46 寄存地址 0X88 0X89 0X8A 0X8B
对data1~4数据进行换算处理PS read 前提确保0X81 设置 Active开启
read data1~2 from 从机0x46 寄存地址 0X8D 0X8E
对data1~2数据进行换算处理

9)LTR-553ALS传感器驱动具体代码,见LTR-553ALS-WA.h和LTR-553ALS-WA.c文件

LTR-553ALS-WA.h

#ifndef _LTR_553ALS_WA_H_
#define _LTR_553ALS_WA_H_#include "main.h"void LTR_ALS_init();
void LTR_PS_init();uint8_t ltr553_als_open();
uint8_t ltr553_als_close();uint8_t ltr553_ps_open();
uint8_t ltr553_ps_close();uint8_t read_als(uint32_t *als_data);
uint8_t read_ps(uint32_t *ps_data);#endif /* LTR_553ALS_WA_LTR_553ALS_WA_H_ */

LTR-553ALS-WA.c,由于是从机地址+寄存器地址方式,驱动文件调用了HAL标准库的HAL_I2C_Mem_Write和HAL_I2C_Mem_Read函数实现I2C收发。

#include <stdio.h>
#include "LTR-553ALS-WA.h"#define WAIT_FOREVER 0xffffffffuextern I2C_HandleTypeDef hi2c2;#define LTR553_ALS_CONTR 0x80 /* ALS operation mode, SW reset */
#define LTR553_PS_CONTR 0x81  /* PS operation mode */
#define LTR553_PS_LED 0x82    /* LED pulse freq, current duty, peak current */
#define LTR553_PS_MEAS_RATE 0x84  /* measurement rate*/
#define LTR553_ALS_MEAS_RATE 0x85 /* ALS integ time, measurement rate*/
#define LTR553_PART_ID 0x86
#define LTR553_MANUFAC_ID 0x87
#define LTR553_ALS_DATA1_L 0x88
#define LTR553_ALS_DATA1_H 0x89
#define LTR553_ALS_DATA0_L 0x8a
#define LTR553_ALS_DATA0_H 0x8b
#define LTR553_ALS_PS_STATUS 0x8c
#define LTR553_PS_DATA_L 0x8d
#define LTR553_PS_DATA_H 0x8e
#define LTR553_INTR 0x8f           /* output mode, polarity, mode */
#define LTR553_PS_THRESH_UP 0x90   /* 11 bit, ps upper threshold */
#define LTR553_PS_THRESH_LOW 0x92  /* 11 bit, ps lower threshold */
#define LTR553_ALS_THRESH_UP 0x97  /* 16 bit, ALS upper threshold */
#define LTR553_ALS_THRESH_LOW 0x99 /* 16 bit, ALS lower threshold */
#define LTR553_INTR_PRST 0x9e      /* ps thresh, als thresh */
#define LTR553_MAX_REG 0x9f#define LTR553_I2C_SLAVE_ADDR 0x23#define LTR553_ADDR_TRANS(n) ((n) << 1)
#define LTR553_I2C_ADDR LTR553_ADDR_TRANS(LTR553_I2C_SLAVE_ADDR)
#define LTR553_PART_ID_VAL 0x92
#define LTR553_MANUFAC_ID_VAL 0x05#define LTR553_ALS_CONTR_REG_ALS_GAIN__POS (2)
#define LTR553_ALS_CONTR_REG_ALS_GAIN__MSK (0x1c)
#define LTR553_ALS_CONTR_REG_ALS_GAIN__REG (LTR553_ALS_CONTR)#define LTR553_ALS_CONTR_REG_ALS_MODE__POS (0)
#define LTR553_ALS_CONTR_REG_ALS_MODE__MSK (0x01)
#define LTR553_ALS_CONTR_REG_ALS_MODE__REG (LTR553_ALS_CONTR)#define LTR553_ALS_MEAS_RATE_REG_INTEG_TIME__POS (3)
#define LTR553_ALS_MEAS_RATE_REG_INTEG_TIME__MSK (0x38)
#define LTR553_ALS_MEAS_RATE_REG_INTEG_TIME__REG (LTR553_ALS_MEAS_RATE)#define LTR553_ALS_MEAS_RATE_REG_MEAS_RATE__POS (0)
#define LTR553_ALS_MEAS_RATE_REG_MEAS_RATE__MSK (0x07)
#define LTR553_ALS_MEAS_RATE_REG_MEAS_RATE__REG (LTR553_ALS_MEAS_RATE)#define LTR553_ALS_PS_STATUS_REG_ALS_STATUS__POS (2)
#define LTR553_ALS_PS_STATUS_REG_ALS_STATUS__MSK (0x04)
#define LTR553_ALS_PS_STATUS_REG_ALS_STATUS__REG (LTR553_ALS_PS_STATUS)#define LTR553_PS_CONTR_REG_PS_GAIN__POS (2)
#define LTR553_PS_CONTR_REG_PS_GAIN__MSK (0x0c)
#define LTR553_PS_CONTR_REG_PS_GAIN__REG (LTR553_PS_CONTR)#define LTR553_PS_CONTR_REG_PS_MODE__POS (0)
#define LTR553_PS_CONTR_REG_PS_MODE__MSK (0x03)
#define LTR553_PS_CONTR_REG_PS_MODE__REG (LTR553_PS_CONTR)#define LTR553_PS_LED_REG_PLUSE_FREQ__POS (5)
#define LTR553_PS_LED_REG_PLUSE_FREQ__MSK (0xe0)
#define LTR553_PS_LED_REG_PLUSE_FREQ__REG (LTR553_PS_LED)#define LTR553_PS_LED_REG_CURRENT_DUTY__POS (3)
#define LTR553_PS_LED_REG_CURRENT_DUTY__MSK (0x18)
#define LTR553_PS_LED_REG_CURRENT_DUTY__REG (LTR553_PS_LED)#define LTR553_PS_LED_REG_CURRENT__POS (0)
#define LTR553_PS_LED_REG_CURRENT__MSK (0x07)
#define LTR553_PS_LED_REG_CURRENT__REG (LTR553_PS_LED)#define LTR553_PS_MEAS_RATE_REG_MEAS_RATE__POS (0)
#define LTR553_PS_MEAS_RATE_REG_MEAS_RATE__MSK (0x0F)
#define LTR553_PS_MEAS_RATE_REG_MEAS_RATE__REG (LTR553_PS_MEAS_RATE)#define LTR553_ALS_PS_STATUS_REG_PS_STATUS__POS (0)
#define LTR553_ALS_PS_STATUS_REG_PS_STATUS__MSK (0x01)
#define LTR553_ALS_PS_STATUS_REG_PS_STATUS__REG (LTR553_ALS_PS_STATUS)#define LTR553_GET_BITSLICE(regvar, bitname) \((regvar & bitname##__MSK) >> bitname##__POS)
#define LTR553_SET_BITSLICE(regvar, bitname, val) \((regvar & ~bitname##__MSK) | ((val << bitname##__POS) & bitname##__MSK))#define LTR553_WAIT_TIME_PER_CHECK (10)
#define LTR553_WAIT_TIME_TOTAL (1000)typedef enum
{AG_GAIN_1X  = 0x0, /* 1 lux to 64k lux (default) */AG_GAIN_2X  = 0x1, /* 0.5 lux to 32k lux */AG_GAIN_4X  = 0x2, /* 0.25 lux to 16k lux */AG_GAIN_8X  = 0x3, /* 0.125 lux to 8k lux */AG_GAIN_48X = 0x6, /* 0.02 lux to 1.3k lux */AG_GAIN_96X = 0x7, /* 0.01 lux to 600 lux */
} CFG_ALS_Gain;typedef enum
{PG_GAIN_X16 = 0x0, /* X16 (default) */PG_GAIN_X32 = 0x2, /* X32 */PG_GAIN_X64 = 0x3, /* X64 */
} CFG_PS_Gain;typedef enum
{LPMF_PERIOD_30K  = 0x0, /* LED pulse period = 30kHz */LPMF_PERIOD_40K  = 0x1, /* LED pulse period = 40kHz */LPMF_PERIOD_50K  = 0x2, /* LED pulse period = 50kHz */LPMF_PERIOD_60K  = 0x3, /* LED pulse period = 60kHz(default) */LPMF_PERIOD_70K  = 0x4, /* LED pulse period = 70kHz */LPMF_PERIOD_80K  = 0x5, /* LED pulse period = 80kHz */LPMF_PERIOD_90K  = 0x6, /* LED pulse period = 90kHz */LPMF_PERIOD_100K = 0x7, /* LED pulse period = 100kHz */
} CFG_LED_pulse_Modulation_Frequency;typedef enum
{LCD_PER_25  = 0x0, /* DUTY = 25% */LCD_PER_50  = 0x1, /* DUTY = 50% */LCD_PER_75  = 0x2, /* DUTY = 75% */LCD_PER_100 = 0x3, /* DUTY = 100%(default) */
} CFG_LED_Current_DUTY;typedef enum
{LC_LEVEL_5   = 0x0, /* LED pulse current level = 5mA */LC_LEVEL_10  = 0x1, /* LED pulse current level = 10mA */LC_LEVEL_20  = 0x2, /* LED pulse current level = 20mA */LC_LEVEL_50  = 0x3, /* LED pulse current level = 50mA */LC_LEVEL_100 = 0x4, /* LED pulse current level = 100mA(default) */
} CFG_LED_Current;typedef enum
{PMR_RATE_50   = 0x0, /* PS Measurement Repeat Rate = 50ms */PMR_RATE_70   = 0x1, /* PS Measurement Repeat Rate = 70ms */PMR_RATE_100  = 0x2, /* PS Measurement Repeat Rate = 100ms(default) */PMR_RATE_200  = 0x3, /* PS Measurement Repeat Rate = 200ms */PMR_RATE_500  = 0x4, /* PS Measurement Repeat Rate = 500ms */PMR_RATE_1000 = 0x5, /* PS Measurement Repeat Rate = 1000ms */PMR_RATE_2000 = 0x6, /* PS Measurement Repeat Rate = 2000ms */PMR_RATE_10   = 0x8, /* PS Measurement Repeat Rate = 10ms */
} CFG_PS_measurement_rate;typedef enum
{AIT_TIME_100 = 0x0, /* ALS integration_time = 100ms(default) */AIT_TIME_50  = 0x1, /* ALS integration_time = 50ms */AIT_TIME_200 = 0x2, /* ALS integration_time = 200ms */AIT_TIME_400 = 0x3, /* ALS integration_time = 400ms */AIT_TIME_150 = 0x4, /* ALS integration_time = 150ms */AIT_TIME_250 = 0x5, /* ALS integration_time = 250ms */AIT_TIME_300 = 0x6, /* ALS integration_time = 300ms */AIT_TIME_350 = 0x7, /* ALS integration_time = 350ms */
} CFG_ALS_integration_time;typedef enum
{AMR_RATE_50   = 0x0, /* ALS Measurement Repeat Rate = 50ms */AMR_RATE_100  = 0x1, /* ALS Measurement Repeat Rate = 100ms */AMR_RATE_200  = 0x2, /* ALS Measurement Repeat Rate = 200ms */AMR_RATE_500  = 0x3, /* ALS Measurement Repeat Rate = 500ms(default) */AMR_RATE_1000 = 0x4, /* ALS Measurement Repeat Rate = 1000ms */AMR_RATE_2000 = 0x5, /* ALS Measurement Repeat Rate = 2000ms */
} CFG_ALS_measurement_rate;typedef enum
{PM_MODE_STANDBY = 0,PM_MODE_ACTIVE  = 3,
} CFG_PS_mode;typedef enum
{AM_MODE_STANDBY = 0,AM_MODE_ACTIVE  = 1,
} CFG_ALS_mode;typedef enum
{ADS_STATUS_OLD = 0,ADS_STATUS_NEW = 1,
} CFG_ALS_data_status;typedef enum
{PDS_STATUS_OLD = 0,PDS_STATUS_NEW = 1,
} CFG_PS_data_status;typedef enum
{FLAG_INIT_ALS = 0,FLAG_INIT_PS,
} FLAG_INIT_BIT;typedef enum {DEV_POWER_OFF = 0,DEV_POWER_ON,DEV_SLEEP,DEV_SUSPEND,DEV_DEEP_SUSPEND,
} LTR_power_mode;uint8_t LTR553_id_check()
{HAL_StatusTypeDef hi2c2_status = 0x00;/*ID check*///LTR553_PART_ID=0X86,LTR553_MANUFAC_ID=0X87//LTR553_PART_ID_VAL=0X92,LTR553_MANUFAC_ID_VAL=0X05uint8_t id_addr_val[6] = {LTR553_PART_ID,LTR553_PART_ID_VAL,0x00,LTR553_MANUFAC_ID,LTR553_MANUFAC_ID_VAL,0x00};hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,LTR553_I2C_ADDR,id_addr_val[0],1,&id_addr_val[2],1,1000);if(HAL_OK!=hi2c2_status){printf("get part_id error\r\n");return 1;}hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,LTR553_I2C_ADDR,id_addr_val[3],1,&id_addr_val[5],1,1000);if(HAL_OK!=hi2c2_status){printf("get manufac_id error\r\n");return 1;}if(id_addr_val[1]!=id_addr_val[2]||id_addr_val[4]!=id_addr_val[5]){printf("drv_als_ps_liteon_ltr553_validate_id is error\r\n");return 1;}printf("part_id:%02X,manufac_id:%02X\r\n",id_addr_val[2],id_addr_val[5]);return 0;
}uint8_t ltr553_als_set_power_mode(LTR_power_mode mode)
{HAL_StatusTypeDef hi2c2_status = 0x00;uint8_t dev_mode  = 0;uint8_t value     = 0;hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,LTR553_I2C_ADDR,LTR553_ALS_CONTR,1,&value,1,WAIT_FOREVER);if(HAL_OK!=hi2c2_status){printf("get als_contr error\r\n");return 1;}printf("ALS_CONTR old:%02X\r\n",value);switch (mode) {case DEV_POWER_OFF:case DEV_SLEEP:dev_mode = LTR553_SET_BITSLICE(dev_mode, LTR553_ALS_CONTR_REG_ALS_MODE, AM_MODE_STANDBY);break;case DEV_POWER_ON:dev_mode = LTR553_SET_BITSLICE(dev_mode, LTR553_ALS_CONTR_REG_ALS_MODE, AM_MODE_ACTIVE);break;default:return 1;}printf("ALS_CONTR new:%02X\r\n",dev_mode);hi2c2_status = HAL_I2C_Mem_Write(&hi2c2,LTR553_I2C_ADDR,LTR553_ALS_CONTR,1,&dev_mode,1,WAIT_FOREVER);if(HAL_OK!=hi2c2_status){printf("set ALS_CONTR error\r\n");return 1;}printf("successfully LTR553_ALS set_power_mode!\r\n");return 0;
}uint8_t ltr553_ps_set_power_mode(LTR_power_mode mode)
{HAL_StatusTypeDef hi2c2_status = 0x00;uint8_t dev_mode  = 0;uint8_t value     = 0;hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,LTR553_I2C_ADDR,LTR553_PS_CONTR,1,&value,1,WAIT_FOREVER);if(HAL_OK!=hi2c2_status){printf("get ps_contr error\r\n");return 1;}printf("PS_CONTR old:%02X\r\n",value);switch (mode) {case DEV_POWER_OFF:case DEV_SLEEP:dev_mode = LTR553_SET_BITSLICE(value, LTR553_PS_CONTR_REG_PS_MODE,PM_MODE_STANDBY);break;case DEV_POWER_ON:dev_mode = LTR553_SET_BITSLICE(value, LTR553_PS_CONTR_REG_PS_MODE,PM_MODE_ACTIVE);break;default:return 1;}printf("ALS_CONTR new:%02X\r\n",dev_mode);hi2c2_status = HAL_I2C_Mem_Write(&hi2c2,LTR553_I2C_ADDR,LTR553_PS_CONTR,1,&dev_mode,1,WAIT_FOREVER);if(HAL_OK!=hi2c2_status){printf("set PS_CONTR error\r\n");return 1;}printf("successfully LTR553_PS set_power_mode!\r\n");return 0;
}uint8_t ltr553_als_is_ready()
{HAL_StatusTypeDef hi2c2_status = 0x00;uint8_t value = 0;hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,LTR553_I2C_ADDR,LTR553_ALS_PS_STATUS,1,&value,1,WAIT_FOREVER);if(HAL_OK!=hi2c2_status){printf("get ps_contr error\r\n");return 0;}
//  printf("PS_CONTR old:%02X\r\n",value);uint8_t ret = (LTR553_GET_BITSLICE(value, LTR553_ALS_PS_STATUS_REG_ALS_STATUS) == ADS_STATUS_NEW)? 1 : 0;return ret;
}uint8_t ltr553_ps_is_ready()
{HAL_StatusTypeDef hi2c2_status = 0x00;uint8_t value = 0;hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,LTR553_I2C_ADDR,LTR553_ALS_PS_STATUS,1,&value,1,WAIT_FOREVER);if(HAL_OK!=hi2c2_status){printf("get ps_contr error\r\n");return 0;}
//  printf("PS_CONTR old:%02X\r\n",value);uint8_t ret = (LTR553_GET_BITSLICE(value, LTR553_ALS_PS_STATUS_REG_PS_STATUS) == PDS_STATUS_NEW)? 1 : 0;return ret;
}uint8_t ltr553_als_set_default_config()
{HAL_StatusTypeDef hi2c2_status = 0x00;uint8_t value = 0;value = LTR553_SET_BITSLICE(value, LTR553_ALS_MEAS_RATE_REG_INTEG_TIME,AIT_TIME_100);value = LTR553_SET_BITSLICE(value, LTR553_ALS_MEAS_RATE_REG_MEAS_RATE,AMR_RATE_100);printf("ALS_MEAS_RATE:%02X\r\n",value);hi2c2_status = HAL_I2C_Mem_Write(&hi2c2,LTR553_I2C_ADDR,LTR553_ALS_MEAS_RATE,1,&value,1,WAIT_FOREVER);if(HAL_OK!=hi2c2_status){printf("set ALS_MEAS_RATE error\r\n");return 1;}hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,LTR553_I2C_ADDR,LTR553_ALS_CONTR,1,&value,1,WAIT_FOREVER);if(HAL_OK!=hi2c2_status){printf("get als_contr error\r\n");return 1;}printf("ALS_CONTR old:%02X\r\n",value);value =   LTR553_SET_BITSLICE(value, LTR553_ALS_CONTR_REG_ALS_GAIN, AG_GAIN_1X);printf("ALS_CONTR new:%02X\r\n",value);hi2c2_status = HAL_I2C_Mem_Write(&hi2c2,LTR553_I2C_ADDR,LTR553_ALS_CONTR,1,&value,1,WAIT_FOREVER);if(HAL_OK!=hi2c2_status){printf("get ALS_CONTR error\r\n");return 1;}printf("successfully LTR553_ALS_default_config!\r\n");return 0;
}uint8_t ltr553_ps_set_default_config()
{HAL_StatusTypeDef hi2c2_status = 0x00;//LTR553_PS_MEAS_RATE=0X84,LTR553_PS_LED=0X82,LTR553_PS_CONTR=0X81uint8_t value = 0;value = LTR553_SET_BITSLICE(value, LTR553_PS_MEAS_RATE_REG_MEAS_RATE,PMR_RATE_100);printf("PS_MEAS_RATE:%02X\r\n",value);hi2c2_status = HAL_I2C_Mem_Write(&hi2c2,LTR553_I2C_ADDR,LTR553_PS_MEAS_RATE,1,&value,1,1000);if(HAL_OK!=hi2c2_status){printf("set PS_MEAS_RATE error\r\n");return 1;}//value default 0X7Fvalue = LTR553_SET_BITSLICE(value, LTR553_PS_LED_REG_PLUSE_FREQ, LPMF_PERIOD_60K);value = LTR553_SET_BITSLICE(value, LTR553_PS_LED_REG_CURRENT_DUTY, LCD_PER_100);value = LTR553_SET_BITSLICE(value, LTR553_PS_LED_REG_CURRENT, LC_LEVEL_100);printf("PS_LED:%02X\r\n",value);hi2c2_status = HAL_I2C_Mem_Write(&hi2c2,LTR553_I2C_ADDR,LTR553_PS_MEAS_RATE,1,&value,1,1000);if(HAL_OK!=hi2c2_status){printf("get PS_LED error\r\n");return 1;}//checkhi2c2_status = HAL_I2C_Mem_Read(&hi2c2,LTR553_I2C_ADDR,LTR553_PS_CONTR,1,&value,1,WAIT_FOREVER);if(HAL_OK!=hi2c2_status){printf("get ps_contr error\r\n");return 1;}printf("PS_CONTR old:%02X\r\n",value);value = LTR553_SET_BITSLICE(value, LTR553_PS_CONTR_REG_PS_GAIN, PG_GAIN_X16);printf("PS_CONTR new:%02X\r\n",value);//hi2c2_status = HAL_I2C_Mem_Write(&hi2c2,LTR553_I2C_ADDR,LTR553_PS_CONTR,1,&value,1,1000);if(HAL_OK!=hi2c2_status){printf("get PS_CONTR error\r\n");return 1;}printf("successfully LTR553_PS default_config!\r\n");return 0;
}uint8_t ltr553_als_open()
{uint8_t ret = 0;ret = ltr553_als_set_power_mode(DEV_POWER_ON);if (ret>0) {return 1;}printf("successfully LTR553_ALS Open!\r\n");return 0;
}uint8_t ltr553_als_close()
{uint8_t ret = 0;ret = ltr553_als_set_power_mode(DEV_POWER_OFF);if (ret>0) {return 1;}printf("successfully LTR553_ALS Close!\r\n");return 0;
}uint8_t ltr553_ps_open()
{uint8_t ret = 0;ret = ltr553_ps_set_power_mode(DEV_POWER_ON);if (ret>0) {return 1;}printf("successfully LTR553_ALS Open!\r\n");return 0;
}uint8_t ltr553_ps_close()
{uint8_t ret = 0;ret = ltr553_ps_set_power_mode(DEV_POWER_OFF);if (ret>0) {return 1;}printf("successfully LTR553_ALS Close!\r\n");return 0;
}void LTR_ALS_init()
{/*ID check*/if(LTR553_id_check()>0){return;}if(ltr553_als_set_default_config()>0)return;printf("successfully LTR553_ALS_init!\r\n");
}void LTR_PS_init()
{/*ID check*/if(LTR553_id_check()){return;}/*PS check*/if(ltr553_ps_set_default_config()>0)return;printf("successfully LTR553_PS_init!\r\n");
}uint8_t read_als(uint32_t *als_data)
{HAL_StatusTypeDef hi2c2_status = 0x00;/** LTR553_ALS_DATA1_L=0X88,LTR553_ALS_DATA1_H=0X89* LTR553_ALS_DATA0_L=0X8A,LTR553_ALS_DATA0_H=0X8B*/uint8_t ALS_addr[4] = {LTR553_ALS_DATA1_L,LTR553_ALS_DATA1_H,LTR553_ALS_DATA0_L,LTR553_ALS_DATA0_H};uint8_t ALS_data[4] = {0x00};for(uint8_t i=0; i<4; i++){hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,LTR553_I2C_ADDR,ALS_addr[i],1,&ALS_data[i],1,1000);if(HAL_OK!=hi2c2_status){return 1;}}uint32_t val01 = ALS_data[0]|(ALS_data[1]<<8);uint32_t val02 = ALS_data[2]|(ALS_data[3]<<8);printf("val01:%lu,val02:%lu\n",val01,val01);*als_data =  (uint32_t)((val01 + val02) >> 1);printf("als_data: %lu\r\n",*als_data);return 0;
}uint8_t read_ps(uint32_t *ps_data)
{HAL_StatusTypeDef hi2c2_status = 0x00;/** LTR553_PS_DATA_L=0X8D,LTR553_PS_DATA_H=0X8E*/uint8_t PS_addr[2] = {LTR553_PS_DATA_L,LTR553_PS_DATA_H};uint8_t PS_data[2] = {0x00};for(uint8_t i=0; i<2; i++){hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,LTR553_I2C_ADDR,PS_addr[i],1,&PS_data[i],1,1000);if(HAL_OK!=hi2c2_status){return 1;}}uint32_t val03 = PS_data[0]|(PS_data[1]<<8);printf("val03:%lu\n",val03);*ps_data = val03;printf("ps_data: %lu\r\n",*ps_data);return 0;
}

七、BMP280传感器(气压传感器)

在ICore源码目录下,创建bmp280文件夹,再在该目录下创建bmp280.h和bmp280.c源码文件,作为BMP280传感器驱动。
同样在网上查找下载bmp280数据手册,逐步分析,bmp280的从设备地址(0XEE=0X77<<1),开发板同样做了微调,采用从机地址+寄存器地址+数据等方式通信,支持SPI或I2C通信,我们只研究I2C通信,如下:

1)I2C读写通信设计如下

2)设备ID寄存器地址0XD0,正确返回值应该是0X58,及软重置寄存器地址XE0,写入数据是0XB6重置生效,其他值无效。

3)power模式设置地址0XF4,bit0~1设置0X03(0000 0011)开启正常模式,可以读取数据。bit5~7设置温度相关,bit2~4设置气压相关.

4)设备参数配置地址0XF5,可设置设备作业的rate, filter and interface。I2C通信需要设置5~7bit。

5)数据读取时的微调参数配置,其中dig_T1、dig_T2、dig_T3是为温度数据调整使用,dig_P1~9是气压数据调整时使用。

6)读取数据,0XF7~F9读取气压相关数据,共3字节(24bit),0XFA~FC读取温度相关数据,共3字节(24bit)

7)至此可设计出BMP280的伪代码

bmp280从机地址0XEE
init:
read data1 from 从机地址0XEE 寄存器地址 0XD0
确保data1==0X58
write 0XB6 to 从机地址0XEE 寄存器地址 0XE0 完成软重置
write val1 to 从机地址0XEE 寄存器地址 0XF4 完成设备模式设置
write val2 to 从机地址0XEE 寄存器地址 0XF5 完成设备参数设置
read conf1~24 from 从机地址0XEE 寄存器地址 0X88~0XA1 获取数据换算微调参数读取数据:
确保设备为正常模式,例如write 0X03 to 从机地址0XEE 寄存器地址 0XF4 完成设备模式设置
read P1~3 from 从机地址0XEE 寄存器地址 0XF7~F9
将P1~3与conf4~24进行换算处理得到实际数据
read t1~3 from 从机地址0XEE 寄存器地址 0XFA~FC
将t1~3与conf1~3进行换算处理得到实际数据

8)依据上面伪代码描述及数据手册分析,BMP280传感器驱动文件源码如下:

bmp280.h

#ifndef _BMP280_H_
#define _BMP280_H_#include "main.h"void BMP280_init();
uint8_t bmp280_open(void);
uint8_t bmp280_close(void);
uint8_t read_bmp280_temp(uint32_t *comp_temp);
uint8_t read_bmp280_baro(uint32_t *comp_baro);
#endif /* BMP280_BMP280_H_ */

bmp280.c

#include <stdio.h>
#include "bmp280.h"extern I2C_HandleTypeDef hi2c2;#define BMP280_TEMPERATURE_CALIB_DIG_T1_LSB_REG (0x88)
#define BMP280_TEMPERATURE_CALIB_DIG_T1_MSB_REG (0x89)
#define BMP280_TEMPERATURE_CALIB_DIG_T2_LSB_REG (0x8A)
#define BMP280_TEMPERATURE_CALIB_DIG_T2_MSB_REG (0x8B)
#define BMP280_TEMPERATURE_CALIB_DIG_T3_LSB_REG (0x8C)
#define BMP280_TEMPERATURE_CALIB_DIG_T3_MSB_REG (0x8D)
#define BMP280_PRESSURE_CALIB_DIG_P1_LSB_REG (0x8E)
#define BMP280_PRESSURE_CALIB_DIG_P1_MSB_REG (0x8F)
#define BMP280_PRESSURE_CALIB_DIG_P2_LSB_REG (0x90)
#define BMP280_PRESSURE_CALIB_DIG_P2_MSB_REG (0x91)
#define BMP280_PRESSURE_CALIB_DIG_P3_LSB_REG (0x92)
#define BMP280_PRESSURE_CALIB_DIG_P3_MSB_REG (0x93)
#define BMP280_PRESSURE_CALIB_DIG_P4_LSB_REG (0x94)
#define BMP280_PRESSURE_CALIB_DIG_P4_MSB_REG (0x95)
#define BMP280_PRESSURE_CALIB_DIG_P5_LSB_REG (0x96)
#define BMP280_PRESSURE_CALIB_DIG_P5_MSB_REG (0x97)
#define BMP280_PRESSURE_CALIB_DIG_P6_LSB_REG (0x98)
#define BMP280_PRESSURE_CALIB_DIG_P6_MSB_REG (0x99)
#define BMP280_PRESSURE_CALIB_DIG_P7_LSB_REG (0x9A)
#define BMP280_PRESSURE_CALIB_DIG_P7_MSB_REG (0x9B)
#define BMP280_PRESSURE_CALIB_DIG_P8_LSB_REG (0x9C)
#define BMP280_PRESSURE_CALIB_DIG_P8_MSB_REG (0x9D)
#define BMP280_PRESSURE_CALIB_DIG_P9_LSB_REG (0x9E)
#define BMP280_PRESSURE_CALIB_DIG_P9_MSB_REG (0x9F)#define BMP280_CHIP_ID_REG (0xD0)
#define BMP280_RST_REG (0xE0)
#define BMP280_STAT_REG (0xF3)
#define BMP280_CTRL_MEAS_REG (0xF4)
#define BMP280_CONFIG_REG (0xF5)
#define BMP280_PRESSURE_MSB_REG (0xF7)
#define BMP280_PRESSURE_LSB_REG (0xF8)
#define BMP280_PRESSURE_XLSB_REG (0xF9)
#define BMP280_TEMPERATURE_MSB_REG (0xFA)
#define BMP280_TEMPERATURE_LSB_REG (0xFB)
#define BMP280_TEMPERATURE_XLSB_REG (0xFC)#define BMP280_SHIFT_BY_01_BIT (1)
#define BMP280_SHIFT_BY_02_BITS (2)
#define BMP280_SHIFT_BY_03_BITS (3)
#define BMP280_SHIFT_BY_04_BITS (4)
#define BMP280_SHIFT_BY_05_BITS (5)
#define BMP280_SHIFT_BY_08_BITS (8)
#define BMP280_SHIFT_BY_11_BITS (11)
#define BMP280_SHIFT_BY_12_BITS (12)
#define BMP280_SHIFT_BY_13_BITS (13)
#define BMP280_SHIFT_BY_14_BITS (14)
#define BMP280_SHIFT_BY_15_BITS (15)
#define BMP280_SHIFT_BY_16_BITS (16)
#define BMP280_SHIFT_BY_17_BITS (17)
#define BMP280_SHIFT_BY_18_BITS (18)
#define BMP280_SHIFT_BY_19_BITS (19)
#define BMP280_SHIFT_BY_25_BITS (25)
#define BMP280_SHIFT_BY_31_BITS (31)
#define BMP280_SHIFT_BY_33_BITS (33)
#define BMP280_SHIFT_BY_35_BITS (35)
#define BMP280_SHIFT_BY_47_BITS (47)#define BMP280_PRESSURE_TEMPERATURE_CALIB_DATA_LENGTH (24)
#define BMP280_GEN_READ_WRITE_DATA_LENGTH (1)
#define BMP280_REGISTER_READ_DELAY (1)
#define BMP280_TEMPERATURE_DATA_LENGTH (3)
#define BMP280_PRESSURE_DATA_LENGTH (3)
#define BMP280_ALL_DATA_FRAME_LENGTH (6)
#define BMP280_INIT_VALUE (0)
#define BMP280_CHIP_ID_READ_COUNT (5)
#define BMP280_CHIP_ID_READ_SUCCESS (0)
#define BMP280_CHIP_ID_READ_FAIL ((int8_t)-1)
#define BMP280_INVALID_DATA (0)#define BMP280_TEMPERATURE_DATA_SIZE (3)
#define BMP280_PRESSURE_DATA_SIZE (3)
#define BMP280_DATA_FRAME_SIZE (6)
#define BMP280_CALIB_DATA_SIZE (24)#define BMP280_TEMPERATURE_MSB_DATA (0)
#define BMP280_TEMPERATURE_LSB_DATA (1)
#define BMP280_TEMPERATURE_XLSB_DATA (2)#define BMP280_I2C_ADDRESS1 (0x76)
#define BMP280_I2C_ADDRESS2 (0x77)#define BMP280_SLEEP_MODE (0x00)
#define BMP280_FORCED_MODE (0x01)
#define BMP280_NORMAL_MODE (0x03)
#define BMP280_SOFT_RESET_CODE (0xB6)#define BMP280_STANDBY_TIME_1_MS (0x00)
#define BMP280_STANDBY_TIME_63_MS (0x01)
#define BMP280_STANDBY_TIME_125_MS (0x02)
#define BMP280_STANDBY_TIME_250_MS (0x03)
#define BMP280_STANDBY_TIME_500_MS (0x04)
#define BMP280_STANDBY_TIME_1000_MS (0x05)
#define BMP280_STANDBY_TIME_2000_MS (0x06)
#define BMP280_STANDBY_TIME_4000_MS (0x07)#define BMP280_OVERSAMP_SKIPPED (0x00)
#define BMP280_OVERSAMP_1X (0x01)
#define BMP280_OVERSAMP_2X (0x02)
#define BMP280_OVERSAMP_4X (0x03)
#define BMP280_OVERSAMP_8X (0x04)
#define BMP280_OVERSAMP_16X (0x05)#define BMP280_FILTER_COEFF_OFF (0x00)
#define BMP280_FILTER_COEFF_2 (0x01)
#define BMP280_FILTER_COEFF_4 (0x02)
#define BMP280_FILTER_COEFF_8 (0x03)
#define BMP280_FILTER_COEFF_16 (0x04)#define BMP280_ULTRA_LOW_POWER_MODE (0x00)
#define BMP280_LOW_POWER_MODE (0x01)
#define BMP280_STANDARD_RESOLUTION_MODE (0x02)
#define BMP280_HIGH_RESOLUTION_MODE (0x03)
#define BMP280_ULTRA_HIGH_RESOLUTION_MODE (0x04)#define BMP280_ULTRALOWPOWER_OVERSAMP_PRESSURE BMP280_OVERSAMP_1X
#define BMP280_ULTRALOWPOWER_OVERSAMP_TEMPERATURE BMP280_OVERSAMP_1X#define BMP280_LOWPOWER_OVERSAMP_PRESSURE BMP280_OVERSAMP_2X
#define BMP280_LOWPOWER_OVERSAMP_TEMPERATURE BMP280_OVERSAMP_1X#define BMP280_STANDARDRESOLUTION_OVERSAMP_PRESSURE BMP280_OVERSAMP_4X
#define BMP280_STANDARDRESOLUTION_OVERSAMP_TEMPERATURE BMP280_OVERSAMP_1X#define BMP280_HIGHRESOLUTION_OVERSAMP_PRESSURE BMP280_OVERSAMP_8X
#define BMP280_HIGHRESOLUTION_OVERSAMP_TEMPERATURE BMP280_OVERSAMP_1X#define BMP280_ULTRAHIGHRESOLUTION_OVERSAMP_PRESSURE BMP280_OVERSAMP_16X
#define BMP280_ULTRAHIGHRESOLUTION_OVERSAMP_TEMPERATURE BMP280_OVERSAMP_2X#define BMP280_STATUS_REG_MEASURING__POS (3)
#define BMP280_STATUS_REG_MEASURING__MSK (0x08)
#define BMP280_STATUS_REG_MEASURING__LEN (1)
#define BMP280_STATUS_REG_MEASURING__REG (BMP280_STAT_REG)#define BMP280_STATUS_REG_IM_UPDATE__POS (0)
#define BMP280_STATUS_REG_IM_UPDATE__MSK (0x01)
#define BMP280_STATUS_REG_IM_UPDATE__LEN (1)
#define BMP280_STATUS_REG_IM_UPDATE__REG (BMP280_STAT_REG)#define BMP280_CTRL_MEAS_REG_OVERSAMP_TEMPERATURE__POS (5)
#define BMP280_CTRL_MEAS_REG_OVERSAMP_TEMPERATURE__MSK (0xE0)
#define BMP280_CTRL_MEAS_REG_OVERSAMP_TEMPERATURE__LEN (3)
#define BMP280_CTRL_MEAS_REG_OVERSAMP_TEMPERATURE__REG (BMP280_CTRL_MEAS_REG)#define BMP280_CTRL_MEAS_REG_OVERSAMP_PRESSURE__POS (2)
#define BMP280_CTRL_MEAS_REG_OVERSAMP_PRESSURE__MSK (0x1C)
#define BMP280_CTRL_MEAS_REG_OVERSAMP_PRESSURE__LEN (3)
#define BMP280_CTRL_MEAS_REG_OVERSAMP_PRESSURE__REG (BMP280_CTRL_MEAS_REG)#define BMP280_CTRL_MEAS_REG_POWER_MODE__POS (0)
#define BMP280_CTRL_MEAS_REG_POWER_MODE__MSK (0x03)
#define BMP280_CTRL_MEAS_REG_POWER_MODE__LEN (2)
#define BMP280_CTRL_MEAS_REG_POWER_MODE__REG (BMP280_CTRL_MEAS_REG)#define BMP280_CONFIG_REG_STANDBY_DURN__POS (5)
#define BMP280_CONFIG_REG_STANDBY_DURN__MSK (0xE0)
#define BMP280_CONFIG_REG_STANDBY_DURN__LEN (3)
#define BMP280_CONFIG_REG_STANDBY_DURN__REG (BMP280_CONFIG_REG)#define BMP280_CONFIG_REG_FILTER__POS (2)
#define BMP280_CONFIG_REG_FILTER__MSK (0x1C)
#define BMP280_CONFIG_REG_FILTER__LEN (3)
#define BMP280_CONFIG_REG_FILTER__REG (BMP280_CONFIG_REG)#define BMP280_CONFIG_REG_SPI3_ENABLE__POS (0)
#define BMP280_CONFIG_REG_SPI3_ENABLE__MSK (0x01)
#define BMP280_CONFIG_REG_SPI3_ENABLE__LEN (1)
#define BMP280_CONFIG_REG_SPI3_ENABLE__REG (BMP280_CONFIG_REG)#define BMP280_PRESSURE_XLSB_REG_DATA__POS (4)
#define BMP280_PRESSURE_XLSB_REG_DATA__MSK (0xF0)
#define BMP280_PRESSURE_XLSB_REG_DATA__LEN (4)
#define BMP280_PRESSURE_XLSB_REG_DATA__REG (BMP280_PRESSURE_XLSB_REG)#define BMP280_TEMPERATURE_XLSB_REG_DATA__POS (4)
#define BMP280_TEMPERATURE_XLSB_REG_DATA__MSK (0xF0)
#define BMP280_TEMPERATURE_XLSB_REG_DATA__LEN (4)
#define BMP280_TEMPERATURE_XLSB_REG_DATA__REG (BMP280_TEMPERATURE_XLSB_REG)#define BMP280_TEMPERATURE_MSB_DATA (0)
#define BMP280_TEMPERATURE_LSB_DATA (1)
#define BMP280_TEMPERATURE_XLSB_DATA (2)#define BMP280_PRESSURE_MSB_DATA (0)
#define BMP280_PRESSURE_LSB_DATA (1)
#define BMP280_PRESSURE_XLSB_DATA (2)#define BMP280_DATA_FRAME_PRESSURE_MSB_BYTE (0)
#define BMP280_DATA_FRAME_PRESSURE_LSB_BYTE (1)
#define BMP280_DATA_FRAME_PRESSURE_XLSB_BYTE (2)
#define BMP280_DATA_FRAME_TEMPERATURE_MSB_BYTE (3)
#define BMP280_DATA_FRAME_TEMPERATURE_LSB_BYTE (4)
#define BMP280_DATA_FRAME_TEMPERATURE_XLSB_BYTE (5)#define BMP280_TEMPERATURE_CALIB_DIG_T1_LSB (0)
#define BMP280_TEMPERATURE_CALIB_DIG_T1_MSB (1)
#define BMP280_TEMPERATURE_CALIB_DIG_T2_LSB (2)
#define BMP280_TEMPERATURE_CALIB_DIG_T2_MSB (3)
#define BMP280_TEMPERATURE_CALIB_DIG_T3_LSB (4)
#define BMP280_TEMPERATURE_CALIB_DIG_T3_MSB (5)
#define BMP280_PRESSURE_CALIB_DIG_P1_LSB (6)
#define BMP280_PRESSURE_CALIB_DIG_P1_MSB (7)
#define BMP280_PRESSURE_CALIB_DIG_P2_LSB (8)
#define BMP280_PRESSURE_CALIB_DIG_P2_MSB (9)
#define BMP280_PRESSURE_CALIB_DIG_P3_LSB (10)
#define BMP280_PRESSURE_CALIB_DIG_P3_MSB (11)
#define BMP280_PRESSURE_CALIB_DIG_P4_LSB (12)
#define BMP280_PRESSURE_CALIB_DIG_P4_MSB (13)
#define BMP280_PRESSURE_CALIB_DIG_P5_LSB (14)
#define BMP280_PRESSURE_CALIB_DIG_P5_MSB (15)
#define BMP280_PRESSURE_CALIB_DIG_P6_LSB (16)
#define BMP280_PRESSURE_CALIB_DIG_P6_MSB (17)
#define BMP280_PRESSURE_CALIB_DIG_P7_LSB (18)
#define BMP280_PRESSURE_CALIB_DIG_P7_MSB (19)
#define BMP280_PRESSURE_CALIB_DIG_P8_LSB (20)
#define BMP280_PRESSURE_CALIB_DIG_P8_MSB (21)
#define BMP280_PRESSURE_CALIB_DIG_P9_LSB (22)
#define BMP280_PRESSURE_CALIB_DIG_P9_MSB (23)#define BMP280_SOFT_RESRT_VALUE (0XB6)#define BMP280_I2C_SLAVE_ADDR_LOW (0X76)
#define BMP280_I2C_SLAVE_ADDR_HIGH (0X77)#define BMP280_DEFAULT_ODR_1HZ (1)#define BMP280_BIT(x) ((uint8_t)(x))
#define BMP280_CHIP_ID_VAL BMP280_BIT(0X58)
#define BMP280_I2C_ADDR_TRANS(n) ((n) << 1)
#define BMP280_I2C_ADDR BMP280_I2C_ADDR_TRANS(BMP280_I2C_SLAVE_ADDR_HIGH)#define BMP280_GET_BITSLICE(regvar, bitname) \((regvar & bitname##__MSK) >> bitname##__POS)
#define BMP280_SET_BITSLICE(regvar, bitname, val) \((regvar & ~bitname##__MSK) | ((val << bitname##__POS) & bitname##__MSK))typedef struct bmp280_calib_param_t
{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;int      t_fine;
} bmp280_calib_param_t;typedef struct bmp280_device_cfg_t
{uint8_t odr;uint8_t mode_filter;uint8_t mode_baro;uint8_t mode_temp;uint8_t mode_power;uint8_t oversamp_temp;uint8_t oversamp_baro;
} bmp280_device_cfg_t;typedef enum {DEV_POWER_OFF = 0,DEV_POWER_ON,DEV_SLEEP,DEV_SUSPEND,DEV_DEEP_SUSPEND,
} bmp280_power_mode;typedef enum {SENSOR_IOCTL_ODR_SET = 1,SENSOR_IOCTL_RANGE_SET,SENSOR_IOCTL_SET_POWER,SENSOR_IOCTL_GET_INFO,SENSOR_IOCTL_MAX
} cmd_type;static bmp280_calib_param_t g_bmp280_calib_table;uint8_t bmp280_id_check()
{HAL_StatusTypeDef hi2c2_status = 0x00;/*ID check*///BMP280_CHIP_ID_REG = 0XD0,BMP280_CHIP_ID_VAL = 0X58uint8_t id_addr_val[3] = {0xD0,0x58,0x00};hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,BMP280_I2C_ADDR,id_addr_val[0],1,&id_addr_val[2],1,1000);if(HAL_OK!=hi2c2_status){printf("get part_id error\r\n");return 1;}if(id_addr_val[1]!=id_addr_val[2]){printf("bmp280_validate_id is error\r\n");return 1;}printf("bmp280_id:%02X\r\n",id_addr_val[2]);return 0;
}uint8_t bmp280_reset()
{HAL_StatusTypeDef hi2c2_status = 0x00;/*reset*///BMP280_RST_REG = 0XE0,BMP280_SOFT_RESRT_VALUE=0XB6uint8_t addr_val[2] = {BMP280_RST_REG,BMP280_SOFT_RESRT_VALUE};hi2c2_status = HAL_I2C_Mem_Write(&hi2c2,BMP280_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);if(HAL_OK!=hi2c2_status){printf("bmp280_reset error\r\n");return 1;}return 0;
}uint8_t bmp280_set_power_mode(bmp280_power_mode mode)
{uint8_t dev_mode = 0x00;switch (mode) {case DEV_POWER_OFF:case DEV_SLEEP: {dev_mode = (uint8_t)BMP280_SLEEP_MODE;break;}case DEV_POWER_ON: {dev_mode = (uint8_t)BMP280_NORMAL_MODE;break;}default:return 1;}HAL_StatusTypeDef hi2c2_status = 0x00;//BMP280_CTRL_MEAS_REG=0XF4uint8_t mode_addr_val[3] = {BMP280_CTRL_MEAS_REG,0x00,dev_mode};hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,BMP280_I2C_ADDR,mode_addr_val[0],1,&mode_addr_val[1],1,1000);if(HAL_OK!=hi2c2_status){printf("get bmp280_power_mode error\r\n");return 1;}printf("bmp280 mode_val[1]:%02X\r\n",mode_addr_val[1]);mode_addr_val[1] = BMP280_SET_BITSLICE(mode_addr_val[1], BMP280_CTRL_MEAS_REG_POWER_MODE, mode_addr_val[2]);printf("bmp280 mode_val[1]:%02X\r\n",mode_addr_val[1]);/*reset*/hi2c2_status = HAL_I2C_Mem_Write(&hi2c2,BMP280_I2C_ADDR,mode_addr_val[0],1,&mode_addr_val[1],1,1000);if(HAL_OK!=hi2c2_status){printf("bmp280_set_power_mode error\r\n");return 1;}return 0;
}
uint8_t bmp280_set_odr(uint8_t odr)
{HAL_StatusTypeDef hi2c2_status = 0x00;//BMP280_CONFIG_REG_STANDBY_DURN__REG=0XF5uint8_t odr_addr_val[2] = {BMP280_CONFIG_REG_STANDBY_DURN__REG,0x00};hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,BMP280_I2C_ADDR,odr_addr_val[0],1,&odr_addr_val[1],1,1000);if(HAL_OK!=hi2c2_status){printf("get bmp280_odr error\r\n");return 1;}printf("bmp280 odr_val[1]:%02X\r\n",odr_addr_val[1]);//BMP280_DEFAULT_ODR_1HZ = 0X01odr_addr_val[1] = BMP280_SET_BITSLICE(odr_addr_val[1], BMP280_CONFIG_REG_STANDBY_DURN, odr);printf("bmp280 odr_val[1]:%02X\r\n",odr_addr_val[1]);/*reset*/hi2c2_status = HAL_I2C_Mem_Write(&hi2c2,BMP280_I2C_ADDR,odr_addr_val[0],1,&odr_addr_val[1],1,1000);if(HAL_OK!=hi2c2_status){printf("bmp280_set_odr error\r\n");return 1;}return 0;
}static uint8_t bmp280_hz2odr(int hz)
{if (hz > 80) {return BMP280_STANDBY_TIME_1_MS;} else if (hz > 13) {return BMP280_STANDBY_TIME_63_MS;} else if (hz > 7) {return BMP280_STANDBY_TIME_125_MS;} else if (hz > 3) {return BMP280_STANDBY_TIME_250_MS;} else {return BMP280_STANDBY_TIME_500_MS;}
}uint8_t bmp280_ioctl(cmd_type cmd,uint32_t arg)
{uint8_t ret = 0;switch (cmd) {case SENSOR_IOCTL_ODR_SET: {uint8_t odr = bmp280_hz2odr(arg);ret         = bmp280_set_odr( odr);if (ret>0) {return 1;}} break;case SENSOR_IOCTL_SET_POWER: {ret = bmp280_set_power_mode(arg);if (ret>0) {return 1;}} break;case SENSOR_IOCTL_GET_INFO: {} break;default:break;}return 0;
}uint8_t bmp280_set_default_config()
{uint8_t ret = bmp280_set_power_mode(DEV_SLEEP);if(ret>0)return 1;ret = bmp280_set_odr(BMP280_DEFAULT_ODR_1HZ);if(ret>0)return 1;return 0;
}uint8_t bmp280_get_calib_param()
{HAL_StatusTypeDef hi2c2_status = 0x00;uint8_t data_u8[BMP280_CALIB_DATA_SIZE] = { 0x00 };hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,BMP280_I2C_ADDR,BMP280_TEMPERATURE_CALIB_DIG_T1_LSB_REG,1,data_u8,BMP280_PRESSURE_TEMPERATURE_CALIB_DATA_LENGTH,1000);if(HAL_OK!=hi2c2_status){printf("get bmp280_calib_param error\r\n");return 1;}g_bmp280_calib_table.dig_T1 = (uint16_t)((((uint16_t)((uint8_t)data_u8[BMP280_TEMPERATURE_CALIB_DIG_T1_MSB])) << BMP280_SHIFT_BY_08_BITS)| data_u8[BMP280_TEMPERATURE_CALIB_DIG_T1_LSB]);g_bmp280_calib_table.dig_T2 = (int16_t)((((int16_t)((int8_t)data_u8[BMP280_TEMPERATURE_CALIB_DIG_T2_MSB])) << BMP280_SHIFT_BY_08_BITS)| data_u8[BMP280_TEMPERATURE_CALIB_DIG_T2_LSB]);g_bmp280_calib_table.dig_T3 = (int16_t)((((int16_t)((int8_t)data_u8[BMP280_TEMPERATURE_CALIB_DIG_T3_MSB])) << BMP280_SHIFT_BY_08_BITS)| data_u8[BMP280_TEMPERATURE_CALIB_DIG_T3_LSB]);g_bmp280_calib_table.dig_P1 = (uint16_t)((((uint16_t)((uint8_t)data_u8[BMP280_PRESSURE_CALIB_DIG_P1_MSB])) << BMP280_SHIFT_BY_08_BITS)| data_u8[BMP280_PRESSURE_CALIB_DIG_P1_LSB]);g_bmp280_calib_table.dig_P2 = (int16_t)((((int16_t)((int8_t)data_u8[BMP280_PRESSURE_CALIB_DIG_P2_MSB])) << BMP280_SHIFT_BY_08_BITS)| data_u8[BMP280_PRESSURE_CALIB_DIG_P2_LSB]);g_bmp280_calib_table.dig_P3 = (int16_t)((((int16_t)((int8_t)data_u8[BMP280_PRESSURE_CALIB_DIG_P3_MSB])) << BMP280_SHIFT_BY_08_BITS)| data_u8[BMP280_PRESSURE_CALIB_DIG_P3_LSB]);g_bmp280_calib_table.dig_P4 = (int16_t)((((int16_t)((int8_t)data_u8[BMP280_PRESSURE_CALIB_DIG_P4_MSB])) << BMP280_SHIFT_BY_08_BITS)| data_u8[BMP280_PRESSURE_CALIB_DIG_P4_LSB]);g_bmp280_calib_table.dig_P5 = (int16_t)((((int16_t)((int8_t)data_u8[BMP280_PRESSURE_CALIB_DIG_P5_MSB])) << BMP280_SHIFT_BY_08_BITS)| data_u8[BMP280_PRESSURE_CALIB_DIG_P5_LSB]);g_bmp280_calib_table.dig_P6 = (int16_t)((((int16_t)((int8_t)data_u8[BMP280_PRESSURE_CALIB_DIG_P6_MSB])) << BMP280_SHIFT_BY_08_BITS)| data_u8[BMP280_PRESSURE_CALIB_DIG_P6_LSB]);g_bmp280_calib_table.dig_P7 = (int16_t)((((int16_t)((int8_t)data_u8[BMP280_PRESSURE_CALIB_DIG_P7_MSB])) << BMP280_SHIFT_BY_08_BITS)| data_u8[BMP280_PRESSURE_CALIB_DIG_P7_LSB]);g_bmp280_calib_table.dig_P8 = (int16_t)((((int16_t)((int8_t)data_u8[BMP280_PRESSURE_CALIB_DIG_P8_MSB])) << BMP280_SHIFT_BY_08_BITS)| data_u8[BMP280_PRESSURE_CALIB_DIG_P8_LSB]);g_bmp280_calib_table.dig_P9 = (int16_t)((((int16_t)((int8_t)data_u8[BMP280_PRESSURE_CALIB_DIG_P9_MSB])) << BMP280_SHIFT_BY_08_BITS)| data_u8[BMP280_PRESSURE_CALIB_DIG_P9_LSB]);return 0;
}uint8_t bmp280_set_baro_work_mode(uint8_t mode)
{uint8_t value = 0;uint8_t temp  = 0;uint8_t baro  = 0;switch (mode) {case BMP280_ULTRA_LOW_POWER_MODE:temp = BMP280_OVERSAMP_1X;baro = BMP280_OVERSAMP_1X;break;case BMP280_LOW_POWER_MODE:temp = BMP280_OVERSAMP_2X;baro = BMP280_OVERSAMP_2X;break;case BMP280_STANDARD_RESOLUTION_MODE:temp = BMP280_OVERSAMP_4X;baro = BMP280_OVERSAMP_4X;break;case BMP280_HIGH_RESOLUTION_MODE:temp = BMP280_OVERSAMP_8X;baro = BMP280_OVERSAMP_8X;break;case BMP280_ULTRA_HIGH_RESOLUTION_MODE:temp = BMP280_OVERSAMP_16X;baro = BMP280_OVERSAMP_16X;break;default:return 1;}HAL_StatusTypeDef hi2c2_status = 0x00;hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,BMP280_I2C_ADDR,BMP280_CTRL_MEAS_REG,1,&value,1,1000);if(HAL_OK!=hi2c2_status){printf("get bmp280_calib_param error\r\n");return 1;}value =    BMP280_SET_BITSLICE(value, BMP280_CTRL_MEAS_REG_OVERSAMP_PRESSURE, baro);value = BMP280_SET_BITSLICE(value, BMP280_CTRL_MEAS_REG_OVERSAMP_TEMPERATURE, temp);hi2c2_status = HAL_I2C_Mem_Write(&hi2c2,BMP280_I2C_ADDR,BMP280_CTRL_MEAS_REG,1,&value,1,1000);if(HAL_OK!=hi2c2_status){printf("bmp280_set_power_mode error\r\n");return 1;}printf("successfully BMP280 set  baro_work_mode \r\n");return 0;
}uint8_t bmp280_open(void)
{uint8_t ret = bmp280_set_baro_work_mode(BMP280_ULTRA_LOW_POWER_MODE);if(ret>0)return 1;ret = bmp280_set_power_mode(DEV_POWER_ON);if(ret>0)return 1;return 0;
}uint8_t bmp280_close(void)
{uint8_t ret = bmp280_set_power_mode(DEV_POWER_OFF);if(ret>0)return 1;return 0;
}void BMP280_init()
{if(bmp280_id_check()>0)return;if(bmp280_reset()>0)return;if(bmp280_set_default_config()>0)return;if(bmp280_get_calib_param()>0)return;printf("successfully BMP280 init\r\n");
}uint8_t read_bmp280_temp(uint32_t *comp_temp)
{*comp_temp = 0;uint8_t data_u8[BMP280_TEMPERATURE_DATA_SIZE] = { 0 };int32_t temp;HAL_StatusTypeDef hi2c2_status = 0x00;hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,BMP280_I2C_ADDR,BMP280_TEMPERATURE_MSB_REG,1,data_u8,BMP280_TEMPERATURE_DATA_SIZE,1000);if(HAL_OK!=hi2c2_status){printf("get bmp280_calib_param error\r\n");return 1;}temp = (int)((((uint32_t)(data_u8[BMP280_TEMPERATURE_MSB_DATA]))<< BMP280_SHIFT_BY_12_BITS) | (((uint32_t)(data_u8[BMP280_TEMPERATURE_LSB_DATA]))<< BMP280_SHIFT_BY_04_BITS) | ((uint32_t)data_u8[BMP280_TEMPERATURE_XLSB_DATA]>> BMP280_SHIFT_BY_04_BITS));//int v_x1_u32r = 0;int v_x2_u32r = 0;v_x1_u32r = ((((temp >> BMP280_SHIFT_BY_03_BITS) -((int)g_bmp280_calib_table.dig_T1 << BMP280_SHIFT_BY_01_BIT))) *((int)g_bmp280_calib_table.dig_T2)) >> BMP280_SHIFT_BY_11_BITS;v_x2_u32r = (((((temp >> BMP280_SHIFT_BY_04_BITS) -((int)g_bmp280_calib_table.dig_T1)) *((temp >> BMP280_SHIFT_BY_04_BITS) -((int)g_bmp280_calib_table.dig_T1))) >>BMP280_SHIFT_BY_12_BITS) *((int)g_bmp280_calib_table.dig_T3)) >>BMP280_SHIFT_BY_14_BITS;g_bmp280_calib_table.t_fine = v_x1_u32r + v_x2_u32r;temp = (g_bmp280_calib_table.t_fine * 5 + 128) >> BMP280_SHIFT_BY_08_BITS;printf("comp_temp: %d.%d\n", (int)temp/100, (int)(temp % 100));*comp_temp = temp;return 0;
}uint8_t read_bmp280_baro(uint32_t *comp_baro)
{*comp_baro = 0;uint8_t data_u8[BMP280_PRESSURE_DATA_SIZE] = { 0 };int32_t temp;HAL_StatusTypeDef hi2c2_status = 0x00;//BMP280_PRESSURE_MSB_REG=0XF7,BMP280_PRESSURE_DATA_SIZE=0X03hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,BMP280_I2C_ADDR,BMP280_PRESSURE_MSB_REG,1,data_u8,BMP280_PRESSURE_DATA_SIZE,1000);if(HAL_OK!=hi2c2_status){printf("get bmp280_calib_param error\r\n");return 1;}temp = (int)((((uint32_t)(data_u8[BMP280_PRESSURE_MSB_DATA])) << BMP280_SHIFT_BY_12_BITS)| (((uint32_t)(data_u8[BMP280_PRESSURE_LSB_DATA])) << BMP280_SHIFT_BY_04_BITS)| ((uint32_t)data_u8[BMP280_PRESSURE_XLSB_DATA]  >> BMP280_SHIFT_BY_04_BITS));//int      v_x1_u32r = 0;int      v_x2_u32r = 0;v_x1_u32r = (((int)g_bmp280_calib_table.t_fine) >> BMP280_SHIFT_BY_01_BIT) - (int)64000;v_x2_u32r = (((v_x1_u32r >> BMP280_SHIFT_BY_02_BITS) * (v_x1_u32r >> BMP280_SHIFT_BY_02_BITS)) >>BMP280_SHIFT_BY_11_BITS) * ((int)g_bmp280_calib_table.dig_P6);v_x2_u32r = v_x2_u32r + ((v_x1_u32r * ((int)g_bmp280_calib_table.dig_P5)) << BMP280_SHIFT_BY_01_BIT);v_x2_u32r = (v_x2_u32r >> BMP280_SHIFT_BY_02_BITS) + (((int)g_bmp280_calib_table.dig_P4) << BMP280_SHIFT_BY_16_BITS);v_x1_u32r = (((g_bmp280_calib_table.dig_P3 *  (((v_x1_u32r >> BMP280_SHIFT_BY_02_BITS) *(v_x1_u32r >> BMP280_SHIFT_BY_02_BITS)) >> BMP280_SHIFT_BY_13_BITS)) >> BMP280_SHIFT_BY_03_BITS) +((((int)g_bmp280_calib_table.dig_P2) * v_x1_u32r) >> BMP280_SHIFT_BY_01_BIT)) >> BMP280_SHIFT_BY_18_BITS;v_x1_u32r = ((((32768 + v_x1_u32r)) * ((int)g_bmp280_calib_table.dig_P1)) >> BMP280_SHIFT_BY_15_BITS);if (v_x1_u32r == 0){return 1; // avoid exception caused by division by zero}//uint32_t val_baro = 0;val_baro = (((uint32_t)(((int)1048576) - temp) - (v_x2_u32r >> BMP280_SHIFT_BY_12_BITS))) * 3125;if (val_baro < 0x80000000) {if (v_x1_u32r != 0) {val_baro =    (val_baro << BMP280_SHIFT_BY_01_BIT) / ((uint32_t)v_x1_u32r);} else {return 1;}} else if (v_x1_u32r != 0) {val_baro = (val_baro / (uint32_t)v_x1_u32r) * 2;} else {return 1;}v_x1_u32r = (((int)g_bmp280_calib_table.dig_P9) * ((int)(((val_baro >> BMP280_SHIFT_BY_03_BITS) *(val_baro >> BMP280_SHIFT_BY_03_BITS)) >> BMP280_SHIFT_BY_13_BITS))) >> BMP280_SHIFT_BY_12_BITS;v_x2_u32r = (((int)(val_baro >> BMP280_SHIFT_BY_02_BITS)) * ((int)g_bmp280_calib_table.dig_P8)) >>  BMP280_SHIFT_BY_13_BITS;val_baro = (uint32_t)((int)val_baro +((v_x1_u32r + v_x2_u32r + g_bmp280_calib_table.dig_P7) >> BMP280_SHIFT_BY_04_BITS));printf("comp_baro:%d.%d\r\n",(int)val_baro/100, (int)(val_baro % 100));*comp_baro = val_baro;return 0;
}

八、LSM6DSL传感器(加速度及角速度)

在ICore源码目录下,创建LSM6DSL文件夹,再在该目录下创建LSM6DSL.h和LSM6DSL.c源文件。

在网上查找下载LSM6DSL传感器数据手册,逐步分析,该传感器的I2C通信也是采用了从机地址+寄存器地址+数据的通信方式,传感器从设备地址0XD4(0X6A(01101010)<<1)如下:

但中间这段文字描述翻译如下:LSM6DSL相关的从属AD地址(SAD)为110101xb。SDO/SA0引脚可用于修改设备地址的低位。如果SDO/SA0引脚连接到电源电压,LSb为“1”(地址1101011b);否则,如果SDO/SA0引脚接地,则LSb值为“0”(地址1101010b)。该解决方案允许将两个不同的惯性模块连接并寻址到同一I2C总线,即有两个地址0X6A(1101010)、0X6B(1101011)。结合开发板的硬件原理图,在R500和R502接线下,取值不同,经测试0XD6、0XD7才能正确读取设备ID,开发板应该是R502接线,从设备地址是0XD6/0XD7。

1)设备ID,地址是0X0F,正确返回值是0X6A

2)软重置设置,寄存器地址是0X12,设置mydata|0x01可重置设备

3)acc加速度模式设置,涉及odr(rate、power)、 刻度(scale)、频宽、是否启动。

4)Gyro角速度模式设置,涉及odr(rate)、刻度(scale)、是否启动。

5)读取数据 地址0X22~0X27为gyro数值,共6字节(16bit).地址0X28~0X2D为acc数值,共6字节(16bit)

ACC和GYRO数值换算表如下,相关含义读者可以查找加速度及角速度相关知识了解:

6)按以上分析,给出LSM6DSl传感器的伪代码

LSM6DSL从机地址是0XD6
init:
read id from 从机地址是0XD6 寄存器地址0X0F
确定id==0X6A
write myconf|0X01 to 从机地址是0XD6 寄存器地址0X12 软重置设备
write mymode to 从机地址是0XD6 寄存器地址0X10 设置设备ACC模式
write mymode to 从机地址是0XD6 寄存器地址0X11 设置设备GYRO模式读取数据
acc 读取数据前确保设置了相关参数,如power mode,range,频宽等,在寄存器地址0X10 设置
read acc1~6 from 从机地址是0XD6 寄存器地址0X28,0X29,0X2A,0X2B,0X2C,0X2D
acc1~6进行换算处理得到acc数值acc 读取数据前确保设置了相关参数,如power mode,range,频宽等,寄存器地址0X11设置
read gyro1~6 from 从机地址是0XD6 寄存器地址0X22,0X23,0X24,0X25,0X26,0X27
gyro1~6进行换算处理得到gyro数值

7)按以上分析及伪代码设计,LSM6DSL传感器的给出LSM6DSL.h和LSM6DSL.c源文件

LSM6DSL.h

#ifndef _LSM6DSL_H_
#define _LSM6DSL_H_#include "main.h"void LSM6DSL_init();
uint8_t LSM6DSL_acc_st_open(void);
uint8_t LSM6DSL_acc_st_close(void);uint8_t LSM6DSL_gyro_st_open(void);
uint8_t LSM6DSL_gyro_st_close(void);uint8_t LSM6DSL_acc_read(int32_t *x_data,int32_t *y_data,int32_t *z_data);
uint8_t LSM6DSL_gyro_read(int32_t *x_data,int32_t *y_data,int32_t *z_data);#endif /* LSM6DSL_LSM6DSL_H_ */

LSM6DSL.c

#include <stdio.h>
#include "LSM6DSL.h"extern I2C_HandleTypeDef hi2c4;#define LSM6DSL_I2C_ADDR1 (0x6A)
#define LSM6DSL_I2C_ADDR2 (0x6B)
#define LSM6DSL_I2C_ADDR_TRANS(n) ((n) << 1)
#define LSM6DSL_I2C_ADDR LSM6DSL_I2C_ADDR_TRANS(LSM6DSL_I2C_ADDR2)#define LSM6DSL_ACC_GYRO_FUNC_CFG_ACCESS 0x01
#define LSM6DSL_ACC_GYRO_SENSOR_SYNC_TIME 0x04
#define LSM6DSL_ACC_GYRO_SENSOR_RES_RATIO 0x05
#define LSM6DSL_ACC_GYRO_FIFO_CTRL1 0x06
#define LSM6DSL_ACC_GYRO_FIFO_CTRL2 0x07
#define LSM6DSL_ACC_GYRO_FIFO_CTRL3 0x08
#define LSM6DSL_ACC_GYRO_FIFO_CTRL4 0x09
#define LSM6DSL_ACC_GYRO_FIFO_CTRL5 0x0A
#define LSM6DSL_ACC_GYRO_DRDY_PULSE_CFG_G 0x0B
#define LSM6DSL_ACC_GYRO_INT1_CTRL 0x0D
#define LSM6DSL_ACC_GYRO_INT2_CTRL 0x0E
#define LSM6DSL_ACC_GYRO_WHO_AM_I_REG 0x0F
#define LSM6DSL_ACC_GYRO_CTRL1_XL 0x10
#define LSM6DSL_ACC_GYRO_CTRL2_G 0x11
#define LSM6DSL_ACC_GYRO_CTRL3_C 0x12
#define LSM6DSL_ACC_GYRO_CTRL4_C 0x13
#define LSM6DSL_ACC_GYRO_CTRL5_C 0x14
#define LSM6DSL_ACC_GYRO_CTRL6_C 0x15
#define LSM6DSL_ACC_GYRO_CTRL7_G 0x16
#define LSM6DSL_ACC_GYRO_CTRL8_XL 0x17
#define LSM6DSL_ACC_GYRO_CTRL9_XL 0x18
#define LSM6DSL_ACC_GYRO_CTRL10_C 0x19#define LSM6DSL_ACC_GYRO_MASTER_CONFIG 0x1A
#define LSM6DSL_ACC_GYRO_WAKE_UP_SRC 0x1B
#define LSM6DSL_ACC_GYRO_TAP_SRC 0x1C
#define LSM6DSL_ACC_GYRO_D6D_SRC 0x1D
#define LSM6DSL_ACC_GYRO_STATUS_REG 0x1E#define LSM6DSL_ACC_GYRO_OUT_TEMP_L 0x20
#define LSM6DSL_ACC_GYRO_OUT_TEMP_H 0x21
#define LSM6DSL_ACC_GYRO_OUTX_L_G 0x22
#define LSM6DSL_ACC_GYRO_OUTX_H_G 0x23
#define LSM6DSL_ACC_GYRO_OUTY_L_G 0x24
#define LSM6DSL_ACC_GYRO_OUTY_H_G 0x25
#define LSM6DSL_ACC_GYRO_OUTZ_L_G 0x26
#define LSM6DSL_ACC_GYRO_OUTZ_H_G 0x27
#define LSM6DSL_ACC_GYRO_OUTX_L_XL 0x28
#define LSM6DSL_ACC_GYRO_OUTX_H_XL 0x29
#define LSM6DSL_ACC_GYRO_OUTY_L_XL 0x2A
#define LSM6DSL_ACC_GYRO_OUTY_H_XL 0x2B
#define LSM6DSL_ACC_GYRO_OUTZ_L_XL 0x2C
#define LSM6DSL_ACC_GYRO_OUTZ_H_XL 0x2D
#define LSM6DSL_ACC_GYRO_SENSORHUB1_REG 0x2E
#define LSM6DSL_ACC_GYRO_SENSORHUB2_REG 0x2F
#define LSM6DSL_ACC_GYRO_SENSORHUB3_REG 0x30
#define LSM6DSL_ACC_GYRO_SENSORHUB4_REG 0x31
#define LSM6DSL_ACC_GYRO_SENSORHUB5_REG 0x32
#define LSM6DSL_ACC_GYRO_SENSORHUB6_REG 0x33
#define LSM6DSL_ACC_GYRO_SENSORHUB7_REG 0x34
#define LSM6DSL_ACC_GYRO_SENSORHUB8_REG 0x35
#define LSM6DSL_ACC_GYRO_SENSORHUB9_REG 0x36
#define LSM6DSL_ACC_GYRO_SENSORHUB10_REG 0x37
#define LSM6DSL_ACC_GYRO_SENSORHUB11_REG 0x38
#define LSM6DSL_ACC_GYRO_SENSORHUB12_REG 0x39
#define LSM6DSL_ACC_GYRO_FIFO_STATUS1 0x3A
#define LSM6DSL_ACC_GYRO_FIFO_STATUS2 0x3B
#define LSM6DSL_ACC_GYRO_FIFO_STATUS3 0x3C
#define LSM6DSL_ACC_GYRO_FIFO_STATUS4 0x3D
#define LSM6DSL_ACC_GYRO_FIFO_DATA_OUT_L 0x3E
#define LSM6DSL_ACC_GYRO_FIFO_DATA_OUT_H 0x3F
#define LSM6DSL_ACC_GYRO_TIMESTAMP0_REG 0x40
#define LSM6DSL_ACC_GYRO_TIMESTAMP1_REG 0x41
#define LSM6DSL_ACC_GYRO_TIMESTAMP2_REG 0x42#define LSM6DSL_ACC_GYRO_TIMESTAMP_L 0x49
#define LSM6DSL_ACC_GYRO_TIMESTAMP_H 0x4A#define LSM6DSL_ACC_GYRO_STEP_COUNTER_L 0x4B
#define LSM6DSL_ACC_GYRO_STEP_COUNTER_H 0x4C#define LSM6DSL_ACC_GYRO_SENSORHUB13_REG 0x4D
#define LSM6DSL_ACC_GYRO_SENSORHUB14_REG 0x4E
#define LSM6DSL_ACC_GYRO_SENSORHUB15_REG 0x4F
#define LSM6DSL_ACC_GYRO_SENSORHUB16_REG 0x50
#define LSM6DSL_ACC_GYRO_SENSORHUB17_REG 0x51
#define LSM6DSL_ACC_GYRO_SENSORHUB18_REG 0x52#define LSM6DSL_ACC_GYRO_FUNC_SRC 0x53
#define LSM6DSL_ACC_GYRO_TAP_CFG1 0x58
#define LSM6DSL_ACC_GYRO_TAP_THS_6D 0x59
#define LSM6DSL_ACC_GYRO_INT_DUR2 0x5A
#define LSM6DSL_ACC_GYRO_WAKE_UP_THS 0x5B
#define LSM6DSL_ACC_GYRO_WAKE_UP_DUR 0x5C
#define LSM6DSL_ACC_GYRO_FREE_FALL 0x5D
#define LSM6DSL_ACC_GYRO_MD1_CFG 0x5E
#define LSM6DSL_ACC_GYRO_MD2_CFG 0x5F#define LSM6DSL_ACC_GYRO_OUT_MAG_RAW_X_L 0x66
#define LSM6DSL_ACC_GYRO_OUT_MAG_RAW_X_H 0x67
#define LSM6DSL_ACC_GYRO_OUT_MAG_RAW_Y_L 0x68
#define LSM6DSL_ACC_GYRO_OUT_MAG_RAW_Y_H 0x69
#define LSM6DSL_ACC_GYRO_OUT_MAG_RAW_Z_L 0x6A
#define LSM6DSL_ACC_GYRO_OUT_MAG_RAW_Z_H 0x6B#define LSM6DSL_ACC_GYRO_X_OFS_USR 0x73
#define LSM6DSL_ACC_GYRO_Y_OFS_USR 0x74
#define LSM6DSL_ACC_GYRO_Z_OFS_USR 0x75#define LSM6DSL_CHIP_ID_VALUE (0x6A)#define LSM6DSL_RESET_VALUE (0x1)
#define LSM6DSL_RESET_MSK (0X1)
#define LSM6DSL_RESET_POS (0)#define LSM6DSL_ACC_ODR_POWER_DOWN (0X00)
#define LSM6DSL_ACC_ODR_1_6_HZ (0X0B)
#define LSM6DSL_ACC_ODR_12_5_HZ (0x01)
#define LSM6DSL_ACC_ODR_26_HZ (0x02)
#define LSM6DSL_ACC_ODR_52_HZ (0x03)
#define LSM6DSL_ACC_ODR_104_HZ (0x04)
#define LSM6DSL_ACC_ODR_208_HZ (0x05)
#define LSM6DSL_ACC_ODR_416_HZ (0x06)
#define LSM6DSL_ACC_ODR_833_HZ (0x07)
#define LSM6DSL_ACC_ODR_1_66_KHZ (0x08)
#define LSM6DSL_ACC_ODR_3_33_KHZ (0x09)
#define LSM6DSL_ACC_ODR_6_66_KHZ (0x0A)
#define LSM6DSL_ACC_ODR_MSK (0XF0)
#define LSM6DSL_ACC_ODR_POS (4)#define LSM6DSL_GYRO_ODR_POWER_DOWN (0X00)
#define LSM6DSL_GYRO_ODR_12_5_HZ (0x01)
#define LSM6DSL_GYRO_ODR_26_HZ (0x02)
#define LSM6DSL_GYRO_ODR_52_HZ (0x03)
#define LSM6DSL_GYRO_ODR_104_HZ (0x04)
#define LSM6DSL_GYRO_ODR_208_HZ (0x05)
#define LSM6DSL_GYRO_ODR_416_HZ (0x06)
#define LSM6DSL_GYRO_ODR_833_HZ (0x07)
#define LSM6DSL_GYRO_ODR_1_66_KHZ (0x08)
#define LSM6DSL_GYRO_ODR_3_33_KHZ (0x09)
#define LSM6DSL_GYRO_ODR_6_66_KHZ (0x0A)
#define LSM6DSL_GYRO_ODR_MSK (0XF0)
#define LSM6DSL_GYRO_ODR_POS (4)#define LSM6DSL_ACC_RANGE_2G (0x0)
#define LSM6DSL_ACC_RANGE_4G (0x2)
#define LSM6DSL_ACC_RANGE_8G (0x3)
#define LSM6DSL_ACC_RANGE_16G (0x1)
#define LSM6DSL_ACC_RANGE_MSK (0X0C)
#define LSM6DSL_ACC_RANGE_POS (2)#define LSM6DSL_ACC_SENSITIVITY_2G (61)
#define LSM6DSL_ACC_SENSITIVITY_4G (122)
#define LSM6DSL_ACC_SENSITIVITY_8G (244)
#define LSM6DSL_ACC_SENSITIVITY_16G (488)#define LSM6DSL_GYRO_RANGE_245 (0x0)
#define LSM6DSL_GYRO_RANGE_500 (0x1)
#define LSM6DSL_GYRO_RANGE_1000 (0x2)
#define LSM6DSL_GYRO_RANGE_2000 (0x3)
#define LSM6DSL_GYRO_RANGE_MSK (0X0C)
#define LSM6DSL_GYRO_RANGE_POS (2)#define LSM6DSL_GYRO_SENSITIVITY_245DPS (8750)
#define LSM6DSL_GYRO_SENSITIVITY_500DPS (17500)
#define LSM6DSL_GYRO_SENSITIVITY_1000DPS (35000)
#define LSM6DSL_GYRO_SENSITIVITY_2000DPS (70000)#define LSM6DSL_SHIFT_EIGHT_BITS (8)
#define LSM6DSL_16_BIT_SHIFT (0xFF)
#define LSM6DSL_ACC_MUL (1000)
#define LSM6DSL_GYRO_MUL (1)#define LSM6DSL_ACC_DEFAULT_ODR_100HZ (100)
#define LSM6DSL_GYRO_DEFAULT_ODR_100HZ (100)#define LSM6DSL_GET_BITSLICE(regvar, bitname) \((regvar & bitname##_MSK) >> bitname##_POS)#define LSM6DSL_SET_BITSLICE(regvar, bitname, val) \((regvar & ~bitname##_MSK) | ((val << bitname##_POS) & bitname##_MSK))typedef enum {ACC_RANGE_2G,ACC_RANGE_4G,ACC_RANGE_8G,ACC_RANGE_16G,ACC_RANGE_6G,ACC_RANGE_12G,ACC_RANGE_24G,ACC_RANGE_100G,ACC_RANGE_200G,ACC_RANGE_400G,ACC_RANGE_MAX
} acc_range_e;typedef enum {GYRO_RANGE_125DPS,GYRO_RANGE_250DPS,GYRO_RANGE_500DPS,GYRO_RANGE_1000DPS,GYRO_RANGE_2000DPS,GYRO_RANGE_MAX
} gyro_range_e;static int32_t lsm6dsl_acc_factor[ACC_RANGE_MAX] = {LSM6DSL_ACC_SENSITIVITY_2G, LSM6DSL_ACC_SENSITIVITY_4G,LSM6DSL_ACC_SENSITIVITY_8G, LSM6DSL_ACC_SENSITIVITY_16G
};
static int32_t lsm6dsl_gyro_factor[GYRO_RANGE_MAX] = {0, LSM6DSL_GYRO_SENSITIVITY_245DPS, LSM6DSL_GYRO_SENSITIVITY_500DPS,LSM6DSL_GYRO_SENSITIVITY_1000DPS, LSM6DSL_GYRO_SENSITIVITY_2000DPS
};typedef enum {DEV_POWER_OFF = 0,DEV_POWER_ON,DEV_SLEEP,DEV_SUSPEND,DEV_DEEP_SUSPEND,
} LSM6DSL_power_mode;static int32_t cur_acc_factor  = 0;
static int32_t cur_gyro_factor = 0;uint8_t LSM6DSL_ID_check()
{HAL_StatusTypeDef hi2c2_status = 0x00;uint8_t addr_val[3] = {LSM6DSL_ACC_GYRO_WHO_AM_I_REG,0x00,LSM6DSL_CHIP_ID_VALUE};hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,LSM6DSL_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);if(HAL_OK!=hi2c2_status){printf("get LSM6DSL ID error\r\n");return 1;}if(addr_val[1]!=addr_val[2]){printf("LSM6DSL validate_id is error\r\n");return 1;}printf("LSM6DSL_id:%02X\r\n",addr_val[1]);return 0;
}uint8_t LSM6DSL_soft_reset()
{HAL_StatusTypeDef hi2c2_status = 0x00;/*first read*/uint8_t addr_val[2] = {LSM6DSL_ACC_GYRO_CTRL3_C,0x00};hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,LSM6DSL_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);if(HAL_OK!=hi2c2_status){printf("get LSM6DSL ACC_GYRO_CTRL3_C error\r\n");return 1;}printf("LSM6DSL ACC_GYRO_CTRL3_C old:%02X\r\n",addr_val[1]);addr_val[1] |= LSM6DSL_RESET_VALUE;printf("LSM6DSL ACC_GYRO_CTRL3_C new:%02X\r\n",addr_val[1]);hi2c2_status = HAL_I2C_Mem_Write(&hi2c4,LSM6DSL_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);if(HAL_OK!=hi2c2_status){printf("set LSM6DSL ACC_GYRO_CTRL3_C error\r\n");return 1;}printf("successfully LSM6DSL soft reset\r\n");return 0;
}
/** 以正数为例,最大可到32767,如果是Accelerometer数据,量程为2g的情况下,* 32768个刻度,一个刻度代表:2g/32768 = 2000mg/32767 = 0.061035mg* 例如:如果读出数据为16384,则加速度:16384x0.061035mg = 1000mg = 1g*/
uint8_t LSM6DSL_acc_set_range(uint32_t range)
{HAL_StatusTypeDef hi2c2_status = 0x00;/*first read*/uint8_t addr_val[2] = {LSM6DSL_ACC_GYRO_CTRL1_XL,0x00};hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,LSM6DSL_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);if(HAL_OK!=hi2c2_status){printf("get LSM6DSL acc range error\r\n");return 1;}uint8_t tmp   = 0;switch (range) {case ACC_RANGE_2G: {tmp = LSM6DSL_ACC_RANGE_2G;} break;case ACC_RANGE_4G: {tmp = LSM6DSL_ACC_RANGE_4G;} break;case ACC_RANGE_8G: {tmp = LSM6DSL_ACC_RANGE_8G;} break;case ACC_RANGE_16G: {tmp = LSM6DSL_ACC_RANGE_16G;} break;default:break;}addr_val[1] = LSM6DSL_SET_BITSLICE(addr_val[1], LSM6DSL_ACC_RANGE, tmp);hi2c2_status = HAL_I2C_Mem_Write(&hi2c4,LSM6DSL_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);if(HAL_OK!=hi2c2_status){printf("set LSM6DSL acc range error\r\n");return 1;}if (range <= ACC_RANGE_16G) {cur_acc_factor = lsm6dsl_acc_factor[range];}printf("successfully LSM6DSL set acc range\r\n");return 0;
}static uint8_t acc_st_lsm6dsl_hz2odr(uint32_t hz)
{if (hz > 3330)return LSM6DSL_ACC_ODR_6_66_KHZ;else if (hz > 1660)return LSM6DSL_ACC_ODR_3_33_KHZ;else if (hz > 833)return LSM6DSL_ACC_ODR_1_66_KHZ;else if (hz > 416)return LSM6DSL_ACC_ODR_833_HZ;else if (hz > 208)return LSM6DSL_ACC_ODR_416_HZ;else if (hz > 104)return LSM6DSL_ACC_ODR_208_HZ;else if (hz > 52)return LSM6DSL_ACC_ODR_104_HZ;else if (hz > 26)return LSM6DSL_ACC_ODR_52_HZ;else if (hz > 13)return LSM6DSL_ACC_ODR_26_HZ;else if (hz >= 2)return LSM6DSL_ACC_ODR_12_5_HZ;elsereturn LSM6DSL_ACC_ODR_1_6_HZ;
}uint8_t LSM6DSL_acc_set_odr(uint32_t hz)
{HAL_StatusTypeDef hi2c2_status = 0x00;/*first read*/uint8_t addr_val[2] = {LSM6DSL_ACC_GYRO_CTRL1_XL,0x00};hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,LSM6DSL_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);if(HAL_OK!=hi2c2_status){printf("get LSM6DSL acc odr error\r\n");return 1;}uint8_t odr   = acc_st_lsm6dsl_hz2odr(hz);addr_val[1] = LSM6DSL_SET_BITSLICE(addr_val[1], LSM6DSL_ACC_ODR, odr);hi2c2_status = HAL_I2C_Mem_Write(&hi2c4,LSM6DSL_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);if(HAL_OK!=hi2c2_status){printf("set LSM6DSL acc odr error\r\n");return 1;}printf("successfully LSM6DSL set acc odr\r\n");return 0;
}uint8_t LSM6DSL_acc_power_mode(LSM6DSL_power_mode mode)
{HAL_StatusTypeDef hi2c2_status = 0x00;/*first read*/uint8_t addr_val[2] = {LSM6DSL_ACC_GYRO_CTRL1_XL,0x00};hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,LSM6DSL_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);if(HAL_OK!=hi2c2_status){printf("get LSM6DSL acc power_mode error\r\n");return 1;}switch (mode) {case DEV_POWER_ON: {addr_val[1] = LSM6DSL_SET_BITSLICE(addr_val[1], LSM6DSL_ACC_ODR,LSM6DSL_ACC_ODR_12_5_HZ);}break;case DEV_POWER_OFF: {addr_val[1] = LSM6DSL_SET_BITSLICE(addr_val[1], LSM6DSL_ACC_ODR,LSM6DSL_ACC_ODR_POWER_DOWN);}break;case DEV_SLEEP: {addr_val[1] = LSM6DSL_SET_BITSLICE(addr_val[1], LSM6DSL_ACC_ODR,LSM6DSL_ACC_ODR_12_5_HZ);}break;default:break;}hi2c2_status = HAL_I2C_Mem_Write(&hi2c4,LSM6DSL_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);if(HAL_OK!=hi2c2_status){printf("set LSM6DSL acc power_mode error\r\n");return 1;}printf("successfully LSM6DSL acc power_mode\r\n");return 0;
}uint8_t LSM6DSL_acc_st_open(void)
{uint8_t ret = 0;ret = LSM6DSL_acc_power_mode( DEV_POWER_ON);if (ret>0) {return ret;}ret = LSM6DSL_acc_set_range(ACC_RANGE_8G);if (ret>0) {return ret;}ret = LSM6DSL_acc_set_odr(LSM6DSL_ACC_DEFAULT_ODR_100HZ);if (ret>0) {return ret;}printf("successfully LSM6DSL acc open\r\n");return 0;
}uint8_t LSM6DSL_acc_st_close(void)
{uint8_t ret = 0;ret = LSM6DSL_acc_power_mode(DEV_POWER_OFF);if (ret>0) {return ret;}printf("successfully LSM6DSL acc close\r\n");return 0;
}uint8_t LSM6DSL_gyro_set_range(uint32_t range)
{HAL_StatusTypeDef hi2c2_status = 0x00;/*first read*/uint8_t addr_val[2] = {LSM6DSL_ACC_GYRO_CTRL2_G,0x00};hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,LSM6DSL_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);if(HAL_OK!=hi2c2_status){printf("get LSM6DSL gyro range error\r\n");return 1;}uint8_t tmp   = 0;switch (range) {case GYRO_RANGE_250DPS: {tmp = LSM6DSL_GYRO_RANGE_245;} break;case GYRO_RANGE_500DPS: {tmp = LSM6DSL_GYRO_RANGE_500;} break;case GYRO_RANGE_1000DPS: {tmp = LSM6DSL_GYRO_RANGE_1000;} break;case GYRO_RANGE_2000DPS: {tmp = LSM6DSL_GYRO_RANGE_2000;} break;default:break;}addr_val[1] = LSM6DSL_SET_BITSLICE(addr_val[1], LSM6DSL_GYRO_RANGE, tmp);hi2c2_status = HAL_I2C_Mem_Write(&hi2c4,LSM6DSL_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);if(HAL_OK!=hi2c2_status){printf("set LSM6DSL gyro range error\r\n");return 1;}if ((range >= GYRO_RANGE_250DPS) && (range <= GYRO_RANGE_2000DPS)) {cur_gyro_factor = lsm6dsl_gyro_factor[range];}printf("successfully LSM6DSL set gyro range\r\n");return 0;
}static uint8_t gyro_st_lsm6dsl_hz2odr(uint32_t hz)
{if (hz > 3330)return LSM6DSL_GYRO_ODR_6_66_KHZ;else if (hz > 1660)return LSM6DSL_GYRO_ODR_3_33_KHZ;else if (hz > 833)return LSM6DSL_GYRO_ODR_1_66_KHZ;else if (hz > 416)return LSM6DSL_GYRO_ODR_833_HZ;else if (hz > 208)return LSM6DSL_GYRO_ODR_416_HZ;else if (hz > 104)return LSM6DSL_GYRO_ODR_208_HZ;else if (hz > 52)return LSM6DSL_GYRO_ODR_104_HZ;else if (hz > 26)return LSM6DSL_GYRO_ODR_52_HZ;else if (hz > 13)return LSM6DSL_GYRO_ODR_26_HZ;elsereturn LSM6DSL_GYRO_ODR_12_5_HZ;
}uint8_t LSM6DSL_gyro_set_odr(uint32_t hz)
{HAL_StatusTypeDef hi2c2_status = 0x00;/*first read*/uint8_t addr_val[2] = {LSM6DSL_ACC_GYRO_CTRL2_G,0x00};hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,LSM6DSL_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);if(HAL_OK!=hi2c2_status){printf("get LSM6DSL gyro odr error\r\n");return 1;}uint8_t odr = gyro_st_lsm6dsl_hz2odr(hz);addr_val[1] = LSM6DSL_SET_BITSLICE(addr_val[1], LSM6DSL_GYRO_ODR, odr);hi2c2_status = HAL_I2C_Mem_Write(&hi2c4,LSM6DSL_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);if(HAL_OK!=hi2c2_status){printf("set LSM6DSL gyro odr error\r\n");return 1;}printf("successfully LSM6DSL set gyro odr\r\n");return 0;
}uint8_t LSM6DSL_gyro_power_mode(LSM6DSL_power_mode mode)
{HAL_StatusTypeDef hi2c2_status = 0x00;/*first read*/uint8_t addr_val[2] = {LSM6DSL_ACC_GYRO_CTRL2_G,0x00};hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,LSM6DSL_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);if(HAL_OK!=hi2c2_status){printf("get LSM6DSL gyro power_mode error\r\n");return 1;}switch (mode) {case DEV_POWER_ON: {addr_val[1] = LSM6DSL_SET_BITSLICE(addr_val[1], LSM6DSL_GYRO_ODR,LSM6DSL_GYRO_ODR_12_5_HZ);break;}case DEV_POWER_OFF: {addr_val[1] = LSM6DSL_SET_BITSLICE(addr_val[1], LSM6DSL_GYRO_ODR,LSM6DSL_GYRO_ODR_POWER_DOWN);break;}case DEV_SLEEP: {addr_val[1] = LSM6DSL_SET_BITSLICE(addr_val[1], LSM6DSL_GYRO_ODR,LSM6DSL_GYRO_ODR_12_5_HZ);break;}default:break;}hi2c2_status = HAL_I2C_Mem_Write(&hi2c4,LSM6DSL_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);if(HAL_OK!=hi2c2_status){printf("set LSM6DSL gyro power_mode error\r\n");return 1;}printf("successfully LSM6DSL gyro power_mode\r\n");return 0;
}uint8_t LSM6DSL_gyro_st_open(void)
{uint8_t ret = 0;ret   = LSM6DSL_gyro_power_mode(DEV_POWER_ON);if (ret>0) {return 1;}ret = LSM6DSL_gyro_set_range(GYRO_RANGE_1000DPS);if (ret>0) {return 1;}ret = LSM6DSL_gyro_set_odr(LSM6DSL_GYRO_DEFAULT_ODR_100HZ);if (ret>0) {return 1;}printf("successfully LSM6DSL gyro open\r\n");return 0;
}uint8_t LSM6DSL_gyro_st_close(void)
{uint8_t ret = 0;ret   = LSM6DSL_gyro_power_mode(DEV_POWER_OFF);if (ret>0) {return 1;}printf("successfully LSM6DSL gyro close\r\n");return 0;
}void LSM6DSL_init()
{if(LSM6DSL_ID_check()>0)return;if(LSM6DSL_soft_reset()>0)return;if(LSM6DSL_acc_power_mode(DEV_POWER_OFF)>0)return;if(LSM6DSL_gyro_power_mode(DEV_POWER_OFF)>0)return;printf("successfully LSM6DSL init\r\n");
}#define DATA_AXIS_X 0
#define DATA_AXIS_Y 1
#define DATA_AXIS_Z 2uint8_t LSM6DSL_acc_read(int32_t *x_data,int32_t *y_data,int32_t *z_data)
{HAL_StatusTypeDef hi2c2_status = 0x00;/*read 0X28,0X29,0X2A,0X2B,0X2C,0X2D*/uint8_t addr[6] = {LSM6DSL_ACC_GYRO_OUTX_L_XL,LSM6DSL_ACC_GYRO_OUTX_H_XL,LSM6DSL_ACC_GYRO_OUTY_L_XL,LSM6DSL_ACC_GYRO_OUTY_H_XL,LSM6DSL_ACC_GYRO_OUTZ_L_XL,LSM6DSL_ACC_GYRO_OUTZ_H_XL};uint8_t val[6] = {0};for(uint8_t i=0; i<6; i++){hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,LSM6DSL_I2C_ADDR,addr[i],1,&val[i],1,1000);if(HAL_OK!=hi2c2_status){printf("get LSM6DSL acc_read[0X%02X] error\r\n",addr[i]);return 1;}}printf("read acc reg_data 1:%02X, 2:%02X, 3:%02X, 4:%02X, 5:%02X ,6:%02X\r\n",val[0],val[1],val[2],val[3],val[4],val[5]);int32_t data[3] = {0};data[DATA_AXIS_X] = (int16_t)((((int16_t)((int8_t)val[1])) << LSM6DSL_SHIFT_EIGHT_BITS) | (val[0]));data[DATA_AXIS_Y] = (int16_t)((((int16_t)((int8_t)val[3])) << LSM6DSL_SHIFT_EIGHT_BITS) | (val[2]));data[DATA_AXIS_Z] = (int16_t)((((int16_t)((int8_t)val[5])) << LSM6DSL_SHIFT_EIGHT_BITS) | (val[4]));if (cur_acc_factor != 0){data[DATA_AXIS_X] = (data[DATA_AXIS_X] * cur_acc_factor) / LSM6DSL_ACC_MUL;data[DATA_AXIS_Y] = (data[DATA_AXIS_Y] * cur_acc_factor) / LSM6DSL_ACC_MUL;data[DATA_AXIS_Z] = (data[DATA_AXIS_Z] * cur_acc_factor) / LSM6DSL_ACC_MUL;}printf("read acc cur_acc_factor:%ld, X:%ld,Y:%ld,Z:%ld\r\n",cur_acc_factor,data[0],data[1],data[2]);*x_data = data[DATA_AXIS_X];*y_data = data[DATA_AXIS_Y];*z_data = data[DATA_AXIS_Z];return 0;
}uint8_t LSM6DSL_gyro_read(int32_t *x_data,int32_t *y_data,int32_t *z_data)
{HAL_StatusTypeDef hi2c2_status = 0x00;/*read 0X22,0X23,0X24,0X25,0X26,0X27*/uint8_t addr[6] = {LSM6DSL_ACC_GYRO_OUTX_L_G,LSM6DSL_ACC_GYRO_OUTX_H_G,LSM6DSL_ACC_GYRO_OUTY_L_G,LSM6DSL_ACC_GYRO_OUTY_H_G,LSM6DSL_ACC_GYRO_OUTZ_L_G,LSM6DSL_ACC_GYRO_OUTZ_H_G};uint8_t val[6] = {0};for(uint8_t i=0; i<6; i++){hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,LSM6DSL_I2C_ADDR,addr[i],1,&val[i],1,1000);if(HAL_OK!=hi2c2_status){printf("get LSM6DSL gyro_read[0X%02X] error\r\n",addr[i]);return 1;}}printf("read gyro reg_data 1:%02X, 2:%02X, 3:%02X, 4:%02X, 5:%02X ,6:%02X\r\n",val[0],val[1],val[2],val[3],val[4],val[5]);int32_t data[3] = {0};data[DATA_AXIS_X] = (int16_t)((((int32_t)((int8_t)val[1])) << LSM6DSL_SHIFT_EIGHT_BITS) | (val[0]));data[DATA_AXIS_Y] = (int16_t)((((int32_t)((int8_t)val[3])) << LSM6DSL_SHIFT_EIGHT_BITS) | (val[2]));data[DATA_AXIS_Z] = (int16_t)((((int32_t)((int8_t)val[5])) << LSM6DSL_SHIFT_EIGHT_BITS) | (val[4]));if (cur_gyro_factor != 0) {data[DATA_AXIS_X] = (data[DATA_AXIS_X] * cur_gyro_factor) / LSM6DSL_GYRO_MUL;data[DATA_AXIS_Y] = (data[DATA_AXIS_Y] * cur_gyro_factor) / LSM6DSL_GYRO_MUL;data[DATA_AXIS_Z] = (data[DATA_AXIS_Z] * cur_gyro_factor) / LSM6DSL_GYRO_MUL;}printf("read gyro cur_gyro_factor:%ld, X:%ld,Y:%ld,Z:%ld\r\n",cur_gyro_factor,data[0],data[1],data[2]);*x_data = data[DATA_AXIS_X];*y_data = data[DATA_AXIS_Y];*z_data = data[DATA_AXIS_Z];return 0;
}

九、MMC3680KJ传感器(三轴磁传感器)

在ICore源目录下,创建MMC3680KJ文件夹,并在该目录下创建MMC3680KJ.h和MMC3680KJ.c源文件。

同样在网上查找及下载了MMC3680KJ数据手册,逐项分析,MMC3680KJ设备的I2C通信同样采用从机设备地址+寄存器地址+数据的模式,该设备的从机地址0X60(0X30(00110000)<<1)如下:

2)寄存器地址总表,设备产品ID地址是0X2F,设备状态地址是0X07,0X00~0X05共6字节,表示三个轴向数值,0X06是设备作业温度值。0X08~0X0A是三个CTRL标识。

3)三轴向数据值每2个字节表示一个轴向,最低有效位在前。

4)作业温度,一个字节数据,给出范围及换算方法

5)设备状态获取,读取数据前,需要明确设备状态

6)control01地址0X08,主要设置设备set和reset,实现设备启用。

7)control02地址0X09,主要设置设备ODR和OTP。

8)control03地址0X09,主要设置设备连续测量模式下频率,脉冲宽度。

9)设备产品ID验证,寄存器地址是0X2F,正确返回值是0X0A(00001010)

10)按以上分析,伪代码设计如下:

MMC3680KJ从设备地址0x60
init:
read status from 从设备地址0x60 寄存器地址0X07
read p_id from 从设备地址0x60 寄存器地址0X2F
确保p_id==0X0A
分别write myconf to 从设备地址0x60 寄存器地址0X08 0X09 0X0A ,完成频率、脉冲、启用等设置读取数据
读取数据确保设备已经设置及启用,寄存器地址0X08,myconf|0X08|(0X01或 0X02)
read data1~6 from 从设备地址0x60 寄存器地址0X00~0X05,共六字节数据
将data1~6 换算处理
read temp from 从设备地址0x60 寄存器地址0X06,一个字节数据
将temp换算处理

11)按以上分析及伪代码设计,得出MMC3680KJ传感器的MMC3680KJ.h和MMC3680KJ.c源码文件。

MMC3680KJ.h

#ifndef _MMC3680KJ_H_
#define _MMC3680KJ_H_#include "main.h"void mmc3680kj_temp_memsic_init();
void mmc3680kj_mag_memsic_init();uint8_t mmc3680kj_read_temp_memsic(int32_t *temperature);
uint8_t mmc3680kj_read_mag_memsic(int32_t *xval, int32_t *yval, int32_t *zval);#endif /* MMC3680KJ_MMC3680KJ_H_ */

MMC3680KJ.c

#include <stdio.h>
#include "MMC3680KJ.h"extern I2C_HandleTypeDef hi2c4;#define MMC3680KJ_REG_DATA 0x00
#define MMC3680KJ_REG_XL 0x00
#define MMC3680KJ_REG_XH 0x01
#define MMC3680KJ_REG_YL 0x02
#define MMC3680KJ_REG_YH 0x03
#define MMC3680KJ_REG_ZL 0x04
#define MMC3680KJ_REG_ZH 0x05
#define MMC3680KJ_REG_TEMP 0x06
#define MMC3680KJ_REG_STATUS 0x07
#define MMC3680KJ_REG_CTRL0 0x08
#define MMC3680KJ_REG_CTRL1 0x09
#define MMC3680KJ_REG_CTRL2 0x0a
#define MMC3680KJ_REG_X_THD 0x0b
#define MMC3680KJ_REG_Y_THD 0x0c
#define MMC3680KJ_REG_Z_THD 0x0d
#define MMC3680KJ_REG_SELFTEST 0x0e
#define MMC3680KJ_REG_PASSWORD 0x0f
#define MMC3680KJ_REG_OTPMODE 0x12
#define MMC3680KJ_REG_TESTMODE 0x13
#define MMC3680KJ_REG_SR_PWIDTH 0x20
#define MMC3680KJ_REG_OTP 0x2a
#define MMC3680KJ_REG_PRODUCTID 0x2f#define MMC3680KJ_CMD_REFILL 0x20
#define MMC3680KJ_CMD_RESET 0x10
#define MMC3680KJ_CMD_SET 0x08
#define MMC3680KJ_CMD_TM_M 0x01
#define MMC3680KJ_CMD_TM_T 0x02
#define MMC3680KJ_CMD_START_MDT 0x04
#define MMC3680KJ_CMD_100HZ 0x00
#define MMC3680KJ_CMD_200HZ 0x01
#define MMC3680KJ_CMD_400HZ 0x02
#define MMC3680KJ_CMD_600HZ 0x03
#define MMC3680KJ_CMD_CM_14HZ 0x01
#define MMC3680KJ_CMD_CM_5HZ 0x02
#define MMC3680KJ_CMD_CM_1HZ 0x04
#define MMC3680KJ_CMD_SW_RST 0x80
#define MMC3680KJ_CMD_PASSWORD 0xe1
#define MMC3680KJ_CMD_OTP_OPER 0x11
#define MMC3680KJ_CMD_OTP_MR 0x80
#define MMC3680KJ_CMD_OTP_ACT 0x80
#define MMC3680KJ_CMD_OTP_NACT 0x00
#define MMC3680KJ_CMD_STSET_OPEN 0x02
#define MMC3680KJ_CMD_STRST_OPEN 0x04
#define MMC3680KJ_CMD_ST_CLOSE 0x00
#define MMC3680KJ_CMD_INT_MD_EN 0x40
#define MMC3680KJ_CMD_INT_MDT_EN 0x20#define MMC3680KJ_PRODUCT_ID 0x0a
#define MMC3680KJ_OTP_READ_DONE_BIT 0x10
#define MMC3680KJ_PUMP_ON_BIT 0x08
#define MMC3680KJ_MDT_BIT 0x04
#define MMC3680KJ_MEAS_T_DONE_BIT 0x02
#define MMC3680KJ_MEAS_M_DONE_BIT 0x01#define MMC3680KJ_I2C_SLAVE_ADDR 0x30
#define MMC3680KJ_ADDR_TRANS(n) ((n) << 1)
#define MMC3680KJ_I2C_ADDR MMC3680KJ_ADDR_TRANS(MMC3680KJ_I2C_SLAVE_ADDR)#define MMC3680KJ_OFFSET 32768
#define MMC3680KJ_SENSITIVITY 1024000
#define MMC3680KJ_T_ZERO -75
#define MMC3680KJ_T_SENSITIVITY 80#define MMC3680KJ_MAG_DATA_SIZE 6
#define OTP_CONVERT(REG) (((REG) >= 32 ? (32 - (REG)) : (REG)) * 6)typedef enum
{FLAG_INIT_MAG = 0,FLAG_INIT_TEMP,
} FLAG_INIT_BIT;static int32_t g_otp_matrix[3] = { 1000000, 1000000, 1350000 };uint8_t mmc3680kj_check_otp()
{HAL_StatusTypeDef hi2c2_status = 0x00;uint8_t addr_val[3] = {MMC3680KJ_REG_STATUS,0x00,MMC3680KJ_OTP_READ_DONE_BIT};hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,MMC3680KJ_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);if(HAL_OK!=hi2c2_status){printf("get mmc3680kj opt error\r\n");return 1;}if ((addr_val[1] & addr_val[2]) != addr_val[2]) {printf("mmc3680kj opt is error\r\n");return 1;}printf("mmc3680kj opt:%02X\r\n",addr_val[1]);return 0;
}uint8_t mmc3680kj_id_check()
{HAL_StatusTypeDef hi2c2_status = 0x00;uint8_t addr_val[3] = {MMC3680KJ_REG_PRODUCTID,0x00,MMC3680KJ_PRODUCT_ID};hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,MMC3680KJ_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);if(HAL_OK!=hi2c2_status){printf("get mmc3680kj ID error\r\n");return 1;}if(addr_val[1]!=addr_val[2]){printf("mmc3680kj validate_id is error\r\n");return 1;}printf("mmc3680kj_id:%02X\r\n",addr_val[1]);return 0;
}uint8_t mmc3680kj_set_comp_matrix()
{HAL_StatusTypeDef hi2c2_status = 0x00;/*first*/uint8_t addr_val[6][2] = {{MMC3680KJ_REG_PASSWORD,MMC3680KJ_CMD_PASSWORD},{MMC3680KJ_REG_OTPMODE,MMC3680KJ_CMD_OTP_OPER},{MMC3680KJ_REG_TESTMODE,MMC3680KJ_CMD_OTP_MR},{MMC3680KJ_REG_CTRL2,MMC3680KJ_CMD_OTP_ACT},{MMC3680KJ_REG_OTP,0X00},{MMC3680KJ_REG_CTRL2,MMC3680KJ_CMD_OTP_NACT}};for(uint8_t i=0; i<4; i++){hi2c2_status = HAL_I2C_Mem_Write(&hi2c4,MMC3680KJ_I2C_ADDR,addr_val[i][0],1,&addr_val[i][1],1,1000);if(HAL_OK!=hi2c2_status){printf("mmc3680kj comp_matrix addr(0X%02X) error\r\n",addr_val[i][0]);return 1;}}uint8_t reg_data[2] = { 0 };hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,MMC3680KJ_I2C_ADDR,addr_val[4][0],1,reg_data,2,1000);if(HAL_OK!=hi2c2_status){printf("mmc3680kj comp_matrix addr(0X%02X) error\r\n",addr_val[4][0]);return 1;}hi2c2_status = HAL_I2C_Mem_Write(&hi2c4,MMC3680KJ_I2C_ADDR,addr_val[5][0],1,&addr_val[5][1],1,1000);if(HAL_OK!=hi2c2_status){printf("mmc3680kj comp_matrix addr(0X%02X) error\r\n",addr_val[5][0]);return 1;}g_otp_matrix[0] = 1000000;g_otp_matrix[1] = OTP_CONVERT(reg_data[0] & 0x3f) * 1000 + 1000000;g_otp_matrix[2] = (OTP_CONVERT((reg_data[1] & 0x0f) << 2 | (reg_data[0] & 0xc0) >> 6) + 1000) * 1350;return 0;
}uint8_t mmc3680kj_set_pulse_width()
{HAL_StatusTypeDef hi2c2_status = 0x00;/*first*/uint8_t addr_val[3][2] = {{MMC3680KJ_REG_CTRL2,MMC3680KJ_CMD_OTP_NACT},{MMC3680KJ_REG_PASSWORD,MMC3680KJ_CMD_PASSWORD},{MMC3680KJ_REG_SR_PWIDTH,0X00}};for(uint8_t i=0; i<2; i++){hi2c2_status = HAL_I2C_Mem_Write(&hi2c4,MMC3680KJ_I2C_ADDR,addr_val[i][0],1,&addr_val[i][1],1,1000);if(HAL_OK!=hi2c2_status){printf("mmc3680kj set pulse_width addr(0X%02X) error\r\n",addr_val[i][0]);return 1;}}hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,MMC3680KJ_I2C_ADDR,addr_val[2][0],1,&addr_val[2][1],1,1000);if(HAL_OK!=hi2c2_status){printf("mmc3680kj set pulse_width addr(0X%02X) error\r\n",addr_val[2][0]);return 1;}addr_val[2][1] &= 0xe7;hi2c2_status = HAL_I2C_Mem_Write(&hi2c4,MMC3680KJ_I2C_ADDR,addr_val[2][0],1,&addr_val[2][1],1,1000);if(HAL_OK!=hi2c2_status){printf("mmc3680kj set pulse_width addr(0X%02X) error\r\n",addr_val[2][0]);return 1;}printf("successfully mmc3680kj set pulse_width\r\n");return 0;
}uint8_t mmc3680kj_set_output_resolution()
{//MMC3680KJ_CMD_100HZHAL_StatusTypeDef hi2c2_status = 0x00;uint8_t addr_val[2] = {MMC3680KJ_REG_CTRL1,MMC3680KJ_CMD_100HZ};hi2c2_status = HAL_I2C_Mem_Write(&hi2c4,MMC3680KJ_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);if(HAL_OK!=hi2c2_status){printf("mmc3680kj set output_resolution addr(0X%02X) error\r\n",addr_val[0]);return 1;}printf("successfully mmc3680kj set pulse_width\r\n");return 0;
}uint8_t mmc3680kj_set()
{HAL_StatusTypeDef hi2c2_status = 0x00;uint8_t addr_val[2] = {MMC3680KJ_REG_CTRL0,MMC3680KJ_CMD_SET};hi2c2_status = HAL_I2C_Mem_Write(&hi2c4,MMC3680KJ_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);if(HAL_OK!=hi2c2_status){printf("mmc3680kj set addr(0X%02X) error\r\n",addr_val[0]);return 1;}printf("successfully mmc3680kj set\r\n");return 0;
}uint8_t mmc3680kj_enable(FLAG_INIT_BIT flag)
{HAL_StatusTypeDef hi2c2_status = 0x00;if (flag == FLAG_INIT_MAG) {uint8_t addr_val[2] = {MMC3680KJ_REG_CTRL0,MMC3680KJ_CMD_TM_M};hi2c2_status = HAL_I2C_Mem_Write(&hi2c4,MMC3680KJ_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);if(HAL_OK!=hi2c2_status){printf("mmc3680kj enable addr(0X%02X) error\r\n",addr_val[0]);return 1;}uint8_t value = 0;do{HAL_Delay(10);hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,MMC3680KJ_I2C_ADDR,MMC3680KJ_REG_STATUS,1,&value,1,1000);if(HAL_OK!=hi2c2_status){printf("mmc3680kj enable addr(0X%02X) error\r\n",MMC3680KJ_REG_STATUS);return 1;}}while ((value & 0x01) != 0x01);}else if(flag==FLAG_INIT_TEMP){uint8_t addr_val[2] = {MMC3680KJ_REG_CTRL0,MMC3680KJ_CMD_TM_T};hi2c2_status = HAL_I2C_Mem_Write(&hi2c4,MMC3680KJ_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);if(HAL_OK!=hi2c2_status){printf("mmc3680kj enable addr(0X%02X) error\r\n",addr_val[0]);return 1;}uint8_t value = 0;do{HAL_Delay(10);hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,MMC3680KJ_I2C_ADDR,MMC3680KJ_REG_STATUS,1,&value,1,1000);if(HAL_OK!=hi2c2_status){printf("mmc3680kj enable addr(0X%02X) error\r\n",MMC3680KJ_REG_STATUS);return 1;}}while ((value & 0x02) != 0x02);}else{return 1;}printf("successfully mmc3680kj enable\r\n");return 0;
}static int mmc3680kj_tick()
{static uint32_t last_time = 0;uint32_t        now_time  = 0;now_time = HAL_GetTick();if (now_time - last_time > 5000) {last_time = now_time;return 1;}return 0;
}uint8_t mmc3680kj_read_temp_memsic(int32_t *temperature)
{uint8_t ret = mmc3680kj_enable(FLAG_INIT_TEMP);if (ret>0) {return ret;}uint8_t reg_raw = 0;HAL_StatusTypeDef hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,MMC3680KJ_I2C_ADDR,MMC3680KJ_REG_TEMP,1,&reg_raw,1,1000);if(HAL_OK!=hi2c2_status){printf("mmc3680kj read_mag_memsic addr(0X%02X) error\r\n",MMC3680KJ_REG_STATUS);return 1;}printf("mmc3680kj_read_temp org:%02X\r\n",reg_raw);*temperature = ((int32_t)reg_raw) * MMC3680KJ_T_SENSITIVITY / 100 + MMC3680KJ_T_ZERO;printf("mmc3680kj_read_temp:%ld\r\n",*temperature);return 0;
}uint8_t mmc3680kj_read_mag_memsic(int32_t *xval, int32_t *yval, int32_t *zval)
{uint8_t ret = 0;if (mmc3680kj_tick()) {ret = mmc3680kj_set();if (ret>0) {return ret;}}ret = mmc3680kj_enable(FLAG_INIT_MAG);if (ret>0) {return ret;}uint8_t reg_raw[MMC3680KJ_MAG_DATA_SIZE] = { 0 };HAL_StatusTypeDef hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,MMC3680KJ_I2C_ADDR,MMC3680KJ_REG_DATA,1,reg_raw,MMC3680KJ_MAG_DATA_SIZE,1000);if(HAL_OK!=hi2c2_status){printf("mmc3680kj read_mag_memsic addr(0X%02X) error\r\n",MMC3680KJ_REG_STATUS);return 1;}uint16_t    data_raw[3] = { 0 };uint32_t    mag_raw[3]  = { 0 };data_raw[0] = (uint16_t)(reg_raw[1] << 8 | reg_raw[0]);data_raw[1] = (uint16_t)(reg_raw[3] << 8 | reg_raw[2]);data_raw[2] = (uint16_t)(reg_raw[5] << 8 | reg_raw[4]);mag_raw[0]  = (uint32_t)(data_raw[0]);mag_raw[1]  = (uint32_t)(data_raw[1] - data_raw[2] + MMC3680KJ_OFFSET);mag_raw[2]  = (uint32_t)(data_raw[1] + data_raw[2] - MMC3680KJ_OFFSET);*xval = (int32_t)(mag_raw[0] - MMC3680KJ_OFFSET) * g_otp_matrix[0] / MMC3680KJ_SENSITIVITY;*yval = (int32_t)(mag_raw[1] - MMC3680KJ_OFFSET) * g_otp_matrix[1] / MMC3680KJ_SENSITIVITY;*zval = (int32_t)(mag_raw[2] - MMC3680KJ_OFFSET) * g_otp_matrix[2] / MMC3680KJ_SENSITIVITY;printf("mmc3680kj_read_mag:%ld,%ld,%ld\r\n",*xval,*yval,*zval);return 0;
}void mmc3680kj_temp_memsic_init()
{if(mmc3680kj_check_otp()>0)return ;if(mmc3680kj_id_check()>0)return ;printf("successfully mmc3680kj temp_memsic_init\r\n");
}void mmc3680kj_mag_memsic_init()
{if(mmc3680kj_check_otp()>0)return ;if(mmc3680kj_id_check()>0)return ;if(mmc3680kj_set_comp_matrix()>0)return ;if(mmc3680kj_set_pulse_width()>0)return ;if(mmc3680kj_set_output_resolution()>0)return ;printf("successfully mmc3680kj mag_memsic_init\r\n");
}

十、驱动代码调用及数据采集与展示

在main.c函数中,调用各个传感器驱动的头文件及调试、oled显示的头文件

/* USER CODE BEGIN Includes */
#include "../../ICore/key/key.h"
#include "../../ICore/led/led.h"
#include "../../ICore/print/print.h"
#include "../../ICore/usart/usart.h"
#include "../../ICore/oled/oled.h"
#include "../../ICore/SHTC1/SHTC1.h"
#include "../../ICore/LTR-553ALS-WA/LTR-553ALS-WA.h"
#include "../../ICore/bmp280/bmp280.h"
#include "../../ICore/LSM6DSL/LSM6DSL.h"
#include "../../ICore/MMC3680KJ/MMC3680KJ.h"
/* USER CODE END Includes */

在主函数中,逐个初始化各个传感器及相关接口,并将OLED设置为蓝色背景显示。

  /* USER CODE BEGIN 1 */float humidity, temperature;uint32_t als_data,ps_data;uint32_t comp_temp,comp_baro;int32_t acc_x,acc_y,acc_z;int32_t gyro_x,gyro_y,gyro_z;int32_t mmc_temp,mmc_aval,mmc_bval,mmc_cval;/* USER CODE END 1 */
.........................................../* USER CODE BEGIN 2 */ResetPrintInit(&hlpuart1);HAL_UART_Receive_IT(&hlpuart1,(uint8_t *)&HLPUSART_NewData, 1); //再开启接收中断HLPUSART_RX_STA = 0;//oledOLED_init();//shtc1humidity = temperature = 0.0;als_data = ps_data = 0;shtc1_init();//ltr553LTR_ALS_init();ltr553_als_open();LTR_PS_init();ltr553_ps_open();//bmp280BMP280_init();bmp280_open();comp_temp = comp_baro = 0;//mmc3680mmc3680kj_temp_memsic_init();mmc3680kj_mag_memsic_init();//LSM6DSL_init();LSM6DSL_acc_st_open();LSM6DSL_gyro_st_open();acc_x = acc_y = acc_z = 0;gyro_x = gyro_y = gyro_z = 0;mmc_temp = mmc_aval = mmc_bval = mmc_cval =0;uint8_t menu = 0;//设置OLED蓝色背景显示BSP_LCD_Clear_DMA(LCD_DISP_BLUE);printf("OLED_Clear_DMA\r\n");/* USER CODE END 2 */

在主函数循环中,加入对各个传感器数据读取以及显示输出,设置了一个菜单标识menu,按键可以改变它:按键KEY0清屏,按键KEY1实现I2C2接口读取(stch1、ltr553、bmp280)数据及显示;按键KEY2实现I2C4接口读取(LSM6DSL、MMC3680KJ)数据及显示。

 /* USER CODE BEGIN WHILE */while (1){if(HLPUSART_RX_STA&0xC000){//溢出或换行,重新开始//printf("%.*s\r\n",HLPUSART_RX_STA&0X0FFF, HLPUSART_RX_BUF);OLED_printf(10,10,"%.*s",HLPUSART_RX_STA&0X0FFF, HLPUSART_RX_BUF);HLPUSART_RX_STA=0;//接收错误,重新开始HAL_Delay(100);//等待}if(KEY_0()){BSP_LCD_Clear_DMA(LCD_DISP_BLUE);printf("OLED_Clear_DMA\r\n");}if(KEY_1()){if(menu&0x02)BSP_LCD_Clear_DMA(LCD_DISP_BLUE);if(menu&0x01)menu &= 0XFE;  //取消I2C2数据刷新elsemenu |= 0X01; //开启I2C2数据刷新menu &= 0XFD; //取消I2C4数据刷新}if(KEY_2()){if(menu&0x01)BSP_LCD_Clear_DMA(LCD_DISP_BLUE);if(menu&0x02)menu &= 0XFD; //取消I2C4数据刷新elsemenu |= 0X02; //开启I2C4数据刷新menu &= 0XFE;  //取消I2C2数据刷新}if(menu&0x01){/* 读取温湿度数据 */read_ht(&humidity,&temperature);//oledOLED_printf(10,10,"humidity   : %d.%d",(int)humidity, (int)(humidity * 100) % 100);if( temperature >= 0 )OLED_printf(10,26,"temperature: %d.%d",(int)temperature, (int)(temperature * 100) % 100);elseOLED_printf(10,26,"temperature: %d.%d",(int)temperature, (int)(-temperature * 100) % 100);read_als(&als_data);read_ps(&ps_data);//OLED_printf(10,42,"light_data : %d.%d",(int)als_data, (int)(als_data * 100) % 100);OLED_printf(10,58,"proximity  : %d.%d",(int)ps_data, (int)(ps_data * 100) % 100);//read_bmp280_temp(&comp_temp);read_bmp280_baro(&comp_baro);OLED_printf(10,74,"comp_DegC  : %d.%d",(int)comp_temp/100,(int)comp_temp%100);OLED_printf(10,90,"comp_baro  : %d.%d",(int)comp_baro/100,(int)comp_baro%100);}if(menu&0x02){LSM6DSL_acc_read(&acc_x,&acc_y,&acc_z);LSM6DSL_gyro_read(&gyro_x,&gyro_y,&gyro_z);if(acc_x>0)OLED_printf(10,10,"st_acc_x   : %d.%d    ",(acc_x*98)/10000,((acc_x*98)%10000)/100);elseOLED_printf(10,10,"st_acc_x   : %d.%d    ",(acc_x*98)/10000,((-acc_x*98)%10000)/100);if(acc_y>0)OLED_printf(10,26,"st_acc_y   : %d.%d    ",(acc_y*98)/10000,((acc_y*98)%10000)/100);elseOLED_printf(10,26,"st_acc_y   : %d.%d    ",(acc_y*98)/10000,((-acc_y*98)%10000)/100);if(acc_z>0)OLED_printf(10,42,"st_acc_z   : %d.%d    ",(acc_z*98)/10000,((acc_z*98)%10000)/100);elseOLED_printf(10,42,"st_acc_z   : %d.%d    ",(acc_z*98)/10000,((-acc_z*98)%10000)/100);if(gyro_x>0)OLED_printf(10,58,"st_gyro_x  : %d.%d    ",(gyro_x)/1000,((gyro_x)%1000)/10);elseOLED_printf(10,58,"st_gyro_x  : %d.%d    ",(gyro_x)/1000,((-gyro_x)%1000)/10);if(gyro_y>0)OLED_printf(10,74,"st_gyro_y  : %d.%d    ",(gyro_y)/1000,((gyro_y)%1000)/10);elseOLED_printf(10,74,"st_gyro_y  : %d.%d    ",(gyro_y)/1000,((-gyro_y)%1000)/10);if(gyro_z>0)OLED_printf(10,90,"st_gyro_z  : %d.%d    ",(gyro_z)/1000,((gyro_z)%1000)/10);elseOLED_printf(10,90,"st_gyro_z  : %d.%d    ",(gyro_z)/1000,((-gyro_z)%1000)/10);mmc3680kj_read_temp_memsic(&mmc_temp);mmc3680kj_read_mag_memsic(&mmc_aval,&mmc_bval,&mmc_cval);OLED_printf(10,106,"mmc_temp   : %d.%d    ",mmc_temp,0);OLED_printf(10,122,"mmc_aval   : %d.%d    ",mmc_aval,0);OLED_printf(10,138,"mmc_bval   : %d.%d    ",mmc_bval,0);OLED_printf(10,154,"mmc_cval   : %d.%d    ",mmc_cval,0);}Toggle_led0();/* USER CODE END WHILE */

程序编译及下载

初始化打印输出

以及oled屏幕显示I2C2读取数据,按键KEY1,将不断刷新,再按一次KEY1将停止刷新

以及OLED屏幕显示I2C4读取数据 ,按键KEY2,将不断刷新,再按一次KEY2将停止刷新

十一、附件

本文已经提供了全部源码及传感器涉及的主要参数资料,读者如果想自行调整及更深层次应用开发,请参考附件资料:

传感器数据手册:https://download.csdn.net/download/py8105/87229821

传感器驱动源文件:https://download.csdn.net/download/py8105/87229808

本人以后博文只要含有源码的,只对粉丝开放,不再公开发布,请CSDN的读友谅解。

STM32CubeIDE开发(十六),I2C协议采集传感器数据(SHTC1、LTR-553ALS、BMP280、LSM6DSL、MMC3680KJ)相关推荐

  1. 【正点原子MP157连载】第二十六章 DS18B20数字温度传感器实验-摘自【正点原子】STM32MP1 M4裸机CubeIDE开发指南

    1)实验平台:正点原子STM32MP157开发板 2)购买链接:https://item.taobao.com/item.htm?&id=629270721801 3)全套实验源码+手册+视频 ...

  2. STC8H开发(十六): GPIO驱动XL2400无线模块

    目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...

  3. vb6编写dll读取dat文件_【STM32Cube_15】使用硬件I2C读取温湿度传感器数据(SHT30)...

    寻求更好的阅读体验,请移步Mculover666的个人博客: [STM32Cube_15]使用硬件I2C读取温湿度传感器数据(SHT30)​www.mculover666.cn 本篇详细的记录了如何使 ...

  4. 【ANDROID游戏开发十六】ANDROID GESTURE之【触摸屏手势识别】操作!利用触摸屏手势实现一个简单切换图片的功能!...

    本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/android-game/337.html - ...

  5. 通过IoT-Fast平台使用Modbus协议采集电表数据并快速完成组态场景搭建

    导读:IoT-Fast是一款全流程低代码物联网平台,提供了丰富的设备采集控制协议(Modbus RTU 串口.Modbus TCP 网口.通用 OpcUa 通讯协议.西门子 S7 通讯协议.三菱 Fx ...

  6. [carla入门教程]-3 在carla中遥控汽车并采集传感器数据(一个简单Demo,附代码)

    本专栏教程将记录从安装carla到调用carla的pythonAPI进行车辆操控并采集数据的全流程,带领大家从安装carla开始,到最终能够熟练使用carla仿真环境进行传感器数据采集和车辆控制. 第 ...

  7. 【Android游戏开发十二】(保存游戏数据 [上文])详解SharedPreference 与 FIleInputStream/FileOutputStream将数据存储到SD卡中!

     李华明Himi 原创,转载务必在明显处注明: 转载自 [黑米GameDev街区] 原文链接:  http://www.himigame.com/android-game/327.html 很多童鞋说 ...

  8. java 传感器_JAVA串口采集传感器数据

    [实例简介] JAVA调用底层库实现采集串口数据和返回数据 JAVA调用底层库实现采集串口数据和返回数据 [实例截图] [核心代码] JAVA串口采集数据 └── JAVA串口采集数据 ├── JAV ...

  9. AD7656六通道同步采集出现数据串通道的问题处理

    1.首先是,AD初始化和数据读取时序程序,如下: 2.以上时序没问题的话,6通道同步采集发生数据串通道是因为缓存数组的遍历标号没有在中断内归零,发生数组越界.

最新文章

  1. Kafka解析之topic创建(2)
  2. 现实地形导入UE4全流程
  3. 观察者模式(Head First设计模式学习2)
  4. 不加密,DES加密 RSA加密图
  5. 纠结也好,蛋疼也罢,既然创业了,就把路走好。
  6. L2-006 树的遍历 (25 point(s))
  7. 关于Initializing Spring root WebApplicationContext解决方法
  8. 没有密码怎样删除officescan
  9. 创建win10介质进度为0_win10介质创建工具(media creation tool)下载_win10介质创建工具(media creation tool)官方下载-太平洋下载中心...
  10. linux关闭3389端口,如何修改云服务器(Windows、Linux)的默认3389远程端口?
  11. Unknown label type: ‘continuous
  12. css3 打车软件等车动画,简单一个渐变放大消失水波加载动画
  13. 传奇人物《周兴和》书连载30 成功背后的陷阱
  14. Android studio下载插件失败问题
  15. 一个猜拳写了一晚上 麻痹……
  16. 2023最新红色风格电脑手机数码商城系统网站源码+仿华为商城UI开发
  17. 【计算机网络】第一章:计算机网络概述
  18. 从开发转到安全渗透工程师,是我做的最对的决定
  19. IFS认证|国际食品IFS认证优势与审核标准
  20. SQL Server多语句表值函数

热门文章

  1. 计算机科学与物流工程国际学术会议,第一届通信工程与物流管理国际会议
  2. JAVA-Swing技术
  3. C# DirectoryInfo GetFiles()获得的文件列表与本机下文件顺序一致
  4. @Around对静态方法不生效问题
  5. 圆角 border-radius
  6. 华为云计算HCIE学习笔记-FusionStorage
  7. 更多字根例字 -- 字根 (2)
  8. 企业管理中,商业智能BI主要做哪些事情?
  9. java excel单元格数据格式_POI实战-java开发excel详解之单元格各类型数据读取
  10. 共射极放大电路静态工作点自动调整分析