你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32CubeIDE I2C协议采集数据经验分享

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

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

da5da8b4846a42e39d99ee8fc8c30231.png

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

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

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

3090a9a70c4447c7981012200dc5a75d.png

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

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

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

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


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

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

804a453636334246acf1f2e4834eb7f7.png

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

f03126e25ee045b28a2c5d026dc4dc88.png

         我们再看HLA标准库提供I2C接口API,也支持这两种方式:
  1. //从机地址+CMD
  2. HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,
  3.                                           uint16_t Size, uint32_t Timeout);
  4. HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData,

  5. //从机地址+寄存器地址
  6. HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress,
  7.                                     uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout);
  8. HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress,
  9.                                    uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout);
复制代码

        PS:I2C在写入和读取时,从机地址是不同的,例如一般“读取从机地址=写入从机地址+1”,在实际使用HAL标准库已经做了内部处理,所以我们就不管读还是写操作,只传入写地址即可,HAL库的读写函数会调用I2C_TransferConfig来完成相关配置,包括从机地址问题,开始条件问题、时钟问题等。
  1. /**
  2.   * @brief  Handles I2Cx communication when starting transfer or during transfer (TC or TCR flag are set).
  3.   * @param  hi2c I2C handle.
  4.   * @param  DevAddress Specifies the slave address to be programmed.
  5.   * @param  Size Specifies the number of bytes to be programmed.
  6.   *   This parameter must be a value between 0 and 255.
  7.   * @param  Mode New state of the I2C START condition generation.
  8.   *   This parameter can be one of the following values:
  9.   *     @arg @ref I2C_RELOAD_MODE Enable Reload mode .
  10.   *     @arg @ref I2C_AUTOEND_MODE Enable Automatic end mode.
  11.   *     @arg @ref I2C_SOFTEND_MODE Enable Software end mode.
  12.   * @param  Request New state of the I2C START condition generation.
  13.   *   This parameter can be one of the following values:
  14.   *     @arg @ref I2C_NO_STARTSTOP Don't Generate stop and start condition.
  15.   *     @arg @ref I2C_GENERATE_STOP Generate stop condition (Size should be set to 0).
  16.   *     @arg @ref I2C_GENERATE_START_READ Generate Restart for read request.
  17.   *     @arg @ref I2C_GENERATE_START_WRITE Generate Restart for write request.
  18.   * @retval None
  19.   */
  20. static void I2C_TransferConfig(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t Size, uint32_t Mode,
  21.                                uint32_t Request)
复制代码

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

401e7506bed647d6916e9193c2e29cbb.png

         这些传感器的硬件原理图如下:
        1)SHTC1温湿度传感器

ebf61b6dd470406aab6e699d7e460164.png

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

0ce1e411a3dd485287a6264b7d854cd3.png

         3)BMP280气压传感器

cf7e61caba7c4bf6a2b5421368342d7d.png

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

c3c8cdc80cc34eb2ad97f86446142619.png

        5) MMC3680KJ三轴磁传感器

e4bc8d4c14d24271a90842414dd4cccf.png

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

25025137dfa844c3863f89fc2be43874.png

5f79efe205bd4e7094d43232984d4212.png

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

2093865e29f94a4f925e5165471ef0e6.png


四、工程创建及引脚配置
        本文新建了一个STM32L496VGTX_I2C工程,并移植了前面已经实现过的串口调试输出及OLED屏幕输出文字的源码

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

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

30c1d952bceb406d81cc7aa1e4c4b56c.png

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

3e71bc0b3d324a888d4f23f05761f6f0.png

205a1b6398624b6da16a5a6fa1f96a54.png

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

d194a00b8f7d47cdb63ed6fef0f1ad7a.png

         I2C4的DMA及中断功能

a37d5e4ee030497981caf81d1e850e24.png

1d9110a0665a4bc9a66951200c9d7032.png

        4) I2C2、I2C4引脚参数配置

ee267eaff44c45ab9b0a645d685d1f6e.png

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

f8f5ec86ff7a404a9bba2bbc7a6c3c12.png

6183c3549a8d40e8bb2c41610a23cdb4.png

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

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

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

275a89b433924dcabc4606c9bef30d68.png

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

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

2f71d5ee73054035a2bc0dfd3bb347f4.png

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

23bf69d1b5104304892d8b46bab37d20.png


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

b4078ceb2fbe4ee896e45b72fb092c4b.png

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

d8dd3d8e38ee484da1e1313975996fd4.png

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

ad848f59ff6f4ac2a742f2c29bd4cdd9.png

         6)伪代码设计:
  1. init:
  2. write 0xef 0xc8 to 0XE0
  3. read  两字节Data     from 0XE0
  4. 取出 Data的0~5位数据与0X07比较完成ID识别
  5. write 0X80, 0X5D to 0XE0 完成重置

  6. read data
  7. write 读取方式指令,例如0X7C 0XA2 to 0XE0
  8. read 六字节Data from 0XE0
  9. Data 1、2字节为温度原始数据,经换算公式获得实际温度值
  10. Data 3、4字节为湿度原始数据,经换算公式获得实际湿度值
复制代码

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

        STCH1.h
  1. #ifndef SHTC1_SHTC1_H_
  2. #define SHTC1_SHTC1_H_

  3. #include "main.h"

  4. void shtc1_init();
  5. uint8_t read_ht(float *cur_humi,float *cur_temp);

  6. #endif /* SHTC1_SHTC1_H_ */
复制代码

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

  3. extern I2C_HandleTypeDef hi2c2;

  4. #define SHTC1_I2C_SLAVE_ADDR 0x70

  5. #define SHTC1_ADDR_TRANS(n) ((n) << 1)
  6. #define SHTC1_I2C_ADDR SHTC1_ADDR_TRANS(SHTC1_I2C_SLAVE_ADDR)

  7. /* delays for non-blocking i2c commands, both in ms */
  8. #define SHTC1_NONBLOCKING_WAIT_TIME_HPM 15
  9. #define SHTC1_NONBLOCKING_WAIT_TIME_LPM 1

  10. #define SHTC1_CHIP_ID_VAL 0x07
  11. #define SHTC1_ID_REG_MASK 0x1f

  12. #define SHTC1_CMD_LENGTH 2
  13. #define SHTC1_RESPONSE_LENGTH 6

  14. #define SHTC1_DATA_READ_MIN_INTERVAL 200 /* in millisecond */

  15. typedef enum
  16. {
  17.     FLAG_INIT_TEMP = 0,
  18.     FLAG_INIT_HUMI,
  19. } FLAG_INIT_BIT;

  20. typedef enum
  21. {
  22.     SHTC1_CMD_read_id_reg,
  23.     SHTC1_CMD_measure_blocking_hpm,
  24.     SHTC1_CMD_measure_nonblocking_hpm,
  25.     SHTC1_CMD_measure_blocking_lpm,
  26.     SHTC1_CMD_measure_nonblocking_lpm,
  27.     SHTC1_CMD_END
  28. } CMD_SHTC1_ENUM;

  29. uint8_t SHTC1_id_check()
  30. {
  31.         HAL_StatusTypeDef hi2c2_status = 0x00;
  32.         uint8_t data[SHTC1_CMD_LENGTH] = { 0xef, 0xc8 };
  33.         hi2c2_status = HAL_I2C_Master_Transmit(&hi2c2,SHTC1_I2C_ADDR,data,SHTC1_CMD_LENGTH,1000);
  34.         if(HAL_OK!=hi2c2_status){
  35.                 printf("set SHTC1_id error\r\n");
  36.                 return 1;
  37.         }
  38.         uint8_t value[2] = { 0 };
  39.         hi2c2_status = HAL_I2C_Master_Receive(&hi2c2,SHTC1_I2C_ADDR,value,2,1000);
  40.         if(HAL_OK!=hi2c2_status){
  41.                 printf("get SHTC1_id error\r\n");
  42.                 return 1;
  43.         }
  44.         printf("SHTC1_id:0X%02X%02X\r\n",value[0],value[1]);
  45.         //SHTC1_ID_REG_MASK=0X1F,SHTC1_CHIP_ID_VAL=0X07
  46.         if ((value[1] & SHTC1_ID_REG_MASK) != SHTC1_CHIP_ID_VAL) {
  47.         return 1;
  48.     }
  49.         printf("SHTC1_id check successfully\r\n");
  50.         return 0;
  51. }
  52. //软重置
  53. void reSet()
  54. {
  55.         HAL_StatusTypeDef hi2c2_status = 0x00;
  56.     uint8_t temp[2] = {0X80, 0X5D};
  57.     hi2c2_status = HAL_I2C_Master_Transmit(&hi2c2,SHTC1_I2C_ADDR,temp,2,1000);
  58.     if(HAL_OK!=hi2c2_status){
  59.                 printf("SHTC1 reset error\r\n");
  60.                 return;
  61.         }
  62.     printf("SHTC1 reSet successfully\r\n");
  63. }

  64. /*SHTC1提供了定义测量期间的传感器行为以及测量结果的传输序列的可能性。
  65. *每个测量命令都会同时触发温度测量和湿度测量。
  66. *bool enabled时钟是否启用,bool humi是否在前*/
  67. void clock_set(uint8_t enabled,uint8_t humi)
  68. {
  69.     uint8_t temp[2] = {0, 0};
  70.     if(enabled){
  71.         /*时钟拉伸 已启用*/
  72.         if(humi){
  73.             /*湿度、温度*/
  74.             temp[0] = 0x5C;
  75.             temp[1] = 0x24;
  76.         }else{
  77.             /*温度、湿度*/
  78.             temp[0] = 0x7C;
  79.             temp[1] = 0xA2;
  80.         }
  81.     }else{
  82.         /*时钟拉伸 丧失能力的*/
  83.         if(humi){
  84.             /*湿度、温度*/
  85.             temp[0] = 0x58;
  86.             temp[1] = 0xE0;
  87.         }else{
  88.             /*温度、湿度*/
  89.             temp[0] = 0x78;
  90.             temp[1] = 0x66;
  91.         }
  92.     }
  93.     printf("out model:");
  94.     for(uint8_t i=0; i<2; i++ )
  95.     {
  96.         printf("%02X ", temp[i]);
  97.     }
  98.     printf("\n");
  99.     HAL_I2C_Master_Transmit(&hi2c2,SHTC1_I2C_ADDR,temp,2,1000);
  100. }

  101. void shtc1_init()
  102. {
  103.         SHTC1_id_check();
  104.     reSet();
  105.     HAL_Delay(1000);
  106.     /*温度在前*/
  107.     clock_set(1,0);
  108.     HAL_Delay(1000);
  109. }

  110. uint8_t read_ht(float *cur_humi,float *cur_temp)
  111. {
  112.         /* 1、先发送要读取确认 */
  113.         clock_set(1,0);/*时钟拉伸 已启用 && 温度、湿度->0X7C 0XA2*/
  114.         /* 2、读取数据 */;
  115.         HAL_StatusTypeDef hi2c2_status = 0x00;
  116.         uint8_t retval[SHTC1_RESPONSE_LENGTH] = {0x00};
  117.         hi2c2_status = HAL_I2C_Master_Receive(&hi2c2, SHTC1_I2C_ADDR, retval, 6, 1000);
  118.         if(HAL_OK!=hi2c2_status)
  119.                 return 1;
  120.         else{
  121.             uint32_t val01 = (retval[0] << 8 | retval[1]);
  122.             uint32_t val02 = (retval[3] << 8 | retval[4]);
  123.             printf("val01:%d,val02:%d\n",(int)val01,(int)val02);
  124.             /* 温度数据转换 */
  125.             *cur_temp =  val01 * 175.0 / (1 << 16) - 45;
  126.             //*cur_temp = (int32_t)((21875 * val01) >> 13) - 45000;//千位表示
  127.             /* 湿度数据转换 */
  128.             *cur_humi = val02 * 100.0 / (1 << 16);
  129.             //*cur_humi = (uint32_t)((12500 * val02) >> 13);
  130.             //lpusart
  131.             printf("\nread shtc1 sensor humidity   : %d.%d\n", (int)(*cur_humi), (int)((*cur_humi) * 100) % 100);
  132.             if( (*cur_temp) >= 0 )
  133.                 {
  134.                     printf("read shtc1 sensor temperature: %d.%d\n", (int)(*cur_temp), (int)((*cur_temp) * 100) % 100);
  135.                 }else{
  136.                         printf("read shtc1 sensor temperature: %d.%d\n", (int)(*cur_temp), (int)(-(*cur_temp) * 100) % 100);
  137.             }
  138.                 return 0;
  139.         }
  140. }
复制代码

六、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),显然开发板做了调整:

8c8b7287ff6d4dbe961c275013f38282.png

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

052932afb9f04274a0267bab8666421c.png

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

0bdee956626e4c7c823cb1d87aebb2eb.png
1cc1bd9f2aae40bbbe4d8aa5fc400f0f.png

         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数值存储地址。

c05a3028a1844744bac9f405885cfa5d.png

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

c8a48a7548a44609af3798d87874eed3.png

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

708e022e76ca48628e376fe482ff3938.png

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

ba09502e9bf54dca979fedf8a3f7ecae.png

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



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

0aab3728925b40cabd09fd67482f7818.png

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

0dbd4e6457074aa08e0f26b3f7f8559b.png

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

353623b684a44a8689dcdc1814af79be.png

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

60e90e31c94448e8911c6d1676eb6c44.png

         8)读取ALS(光感应)、PS(接近感应)数据伪代码实现:
  1. 从机地址是0x46
  2. Init:
  3. read data1 from 从机0x46 寄存地址 0X86
  4. read data2 from 从机0x46 寄存地址 0X87
  5. 确保data1=0x92,data2=0x05

  6. ALS init
  7. write 设值 to 从机0x46 寄存地址 0X85 设置Measure Time and Rate
  8. write 设值 to 从机0x46 寄存地址 0X80 设置 Active

  9. PS init
  10. write 设值 to 从机0x46 寄存地址 0X84 设置Measure Rate
  11. write 设值 to 从机0x46 寄存地址 0X81 设置 Active

  12. 读取数据

  13. ALS read 前提确保0X80 设置 Active开启
  14. read data1~4 from 从机0x46 寄存地址 0X88 0X89 0X8A 0X8B
  15. 对data1~4数据进行换算处理

  16. PS read 前提确保0X81 设置 Active开启
  17. read data1~2 from 从机0x46 寄存地址 0X8D 0X8E
  18. 对data1~2数据进行换算处理
复制代码

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

  3. #include "main.h"

  4. void LTR_ALS_init();
  5. void LTR_PS_init();

  6. uint8_t ltr553_als_open();
  7. uint8_t ltr553_als_close();

  8. uint8_t ltr553_ps_open();
  9. uint8_t ltr553_ps_close();

  10. uint8_t read_als(uint32_t *als_data);
  11. uint8_t read_ps(uint32_t *ps_data);

  12. #endif /* LTR_553ALS_WA_LTR_553ALS_WA_H_ */
复制代码

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

  3. #define WAIT_FOREVER 0xffffffffu

  4. extern I2C_HandleTypeDef hi2c2;

  5. #define LTR553_ALS_CONTR 0x80 /* ALS operation mode, SW reset */
  6. #define LTR553_PS_CONTR 0x81  /* PS operation mode */
  7. #define LTR553_PS_LED 0x82    /* LED pulse freq, current duty, peak current */
  8. #define LTR553_PS_MEAS_RATE 0x84  /* measurement rate*/
  9. #define LTR553_ALS_MEAS_RATE 0x85 /* ALS integ time, measurement rate*/
  10. #define LTR553_PART_ID 0x86
  11. #define LTR553_MANUFAC_ID 0x87
  12. #define LTR553_ALS_DATA1_L 0x88
  13. #define LTR553_ALS_DATA1_H 0x89
  14. #define LTR553_ALS_DATA0_L 0x8a
  15. #define LTR553_ALS_DATA0_H 0x8b
  16. #define LTR553_ALS_PS_STATUS 0x8c
  17. #define LTR553_PS_DATA_L 0x8d
  18. #define LTR553_PS_DATA_H 0x8e
  19. #define LTR553_INTR 0x8f           /* output mode, polarity, mode */
  20. #define LTR553_PS_THRESH_UP 0x90   /* 11 bit, ps upper threshold */
  21. #define LTR553_PS_THRESH_LOW 0x92  /* 11 bit, ps lower threshold */
  22. #define LTR553_ALS_THRESH_UP 0x97  /* 16 bit, ALS upper threshold */
  23. #define LTR553_ALS_THRESH_LOW 0x99 /* 16 bit, ALS lower threshold */
  24. #define LTR553_INTR_PRST 0x9e      /* ps thresh, als thresh */
  25. #define LTR553_MAX_REG 0x9f

  26. #define LTR553_I2C_SLAVE_ADDR 0x23

  27. #define LTR553_ADDR_TRANS(n) ((n) << 1)
  28. #define LTR553_I2C_ADDR LTR553_ADDR_TRANS(LTR553_I2C_SLAVE_ADDR)
  29. #define LTR553_PART_ID_VAL 0x92
  30. #define LTR553_MANUFAC_ID_VAL 0x05

  31. #define LTR553_ALS_CONTR_REG_ALS_GAIN__POS (2)
  32. #define LTR553_ALS_CONTR_REG_ALS_GAIN__MSK (0x1c)
  33. #define LTR553_ALS_CONTR_REG_ALS_GAIN__REG (LTR553_ALS_CONTR)

  34. #define LTR553_ALS_CONTR_REG_ALS_MODE__POS (0)
  35. #define LTR553_ALS_CONTR_REG_ALS_MODE__MSK (0x01)
  36. #define LTR553_ALS_CONTR_REG_ALS_MODE__REG (LTR553_ALS_CONTR)

  37. #define LTR553_ALS_MEAS_RATE_REG_INTEG_TIME__POS (3)
  38. #define LTR553_ALS_MEAS_RATE_REG_INTEG_TIME__MSK (0x38)
  39. #define LTR553_ALS_MEAS_RATE_REG_INTEG_TIME__REG (LTR553_ALS_MEAS_RATE)

  40. #define LTR553_ALS_MEAS_RATE_REG_MEAS_RATE__POS (0)
  41. #define LTR553_ALS_MEAS_RATE_REG_MEAS_RATE__MSK (0x07)
  42. #define LTR553_ALS_MEAS_RATE_REG_MEAS_RATE__REG (LTR553_ALS_MEAS_RATE)

  43. #define LTR553_ALS_PS_STATUS_REG_ALS_STATUS__POS (2)
  44. #define LTR553_ALS_PS_STATUS_REG_ALS_STATUS__MSK (0x04)
  45. #define LTR553_ALS_PS_STATUS_REG_ALS_STATUS__REG (LTR553_ALS_PS_STATUS)

  46. #define LTR553_PS_CONTR_REG_PS_GAIN__POS (2)
  47. #define LTR553_PS_CONTR_REG_PS_GAIN__MSK (0x0c)
  48. #define LTR553_PS_CONTR_REG_PS_GAIN__REG (LTR553_PS_CONTR)

  49. #define LTR553_PS_CONTR_REG_PS_MODE__POS (0)
  50. #define LTR553_PS_CONTR_REG_PS_MODE__MSK (0x03)
  51. #define LTR553_PS_CONTR_REG_PS_MODE__REG (LTR553_PS_CONTR)

  52. #define LTR553_PS_LED_REG_PLUSE_FREQ__POS (5)
  53. #define LTR553_PS_LED_REG_PLUSE_FREQ__MSK (0xe0)
  54. #define LTR553_PS_LED_REG_PLUSE_FREQ__REG (LTR553_PS_LED)

  55. #define LTR553_PS_LED_REG_CURRENT_DUTY__POS (3)
  56. #define LTR553_PS_LED_REG_CURRENT_DUTY__MSK (0x18)
  57. #define LTR553_PS_LED_REG_CURRENT_DUTY__REG (LTR553_PS_LED)

  58. #define LTR553_PS_LED_REG_CURRENT__POS (0)
  59. #define LTR553_PS_LED_REG_CURRENT__MSK (0x07)
  60. #define LTR553_PS_LED_REG_CURRENT__REG (LTR553_PS_LED)

  61. #define LTR553_PS_MEAS_RATE_REG_MEAS_RATE__POS (0)
  62. #define LTR553_PS_MEAS_RATE_REG_MEAS_RATE__MSK (0x0F)
  63. #define LTR553_PS_MEAS_RATE_REG_MEAS_RATE__REG (LTR553_PS_MEAS_RATE)

  64. #define LTR553_ALS_PS_STATUS_REG_PS_STATUS__POS (0)
  65. #define LTR553_ALS_PS_STATUS_REG_PS_STATUS__MSK (0x01)
  66. #define LTR553_ALS_PS_STATUS_REG_PS_STATUS__REG (LTR553_ALS_PS_STATUS)

  67. #define LTR553_GET_BITSLICE(regvar, bitname) \
  68.     ((regvar & bitname##__MSK) >> bitname##__POS)
  69. #define LTR553_SET_BITSLICE(regvar, bitname, val) \
  70.     ((regvar & ~bitname##__MSK) | ((val << bitname##__POS) & bitname##__MSK))

  71. #define LTR553_WAIT_TIME_PER_CHECK (10)
  72. #define LTR553_WAIT_TIME_TOTAL (1000)

  73. typedef enum
  74. {
  75.     AG_GAIN_1X  = 0x0, /* 1 lux to 64k lux (default) */
  76.     AG_GAIN_2X  = 0x1, /* 0.5 lux to 32k lux */
  77.     AG_GAIN_4X  = 0x2, /* 0.25 lux to 16k lux */
  78.     AG_GAIN_8X  = 0x3, /* 0.125 lux to 8k lux */
  79.     AG_GAIN_48X = 0x6, /* 0.02 lux to 1.3k lux */
  80.     AG_GAIN_96X = 0x7, /* 0.01 lux to 600 lux */
  81. } CFG_ALS_Gain;

  82. typedef enum
  83. {
  84.     PG_GAIN_X16 = 0x0, /* X16 (default) */
  85.     PG_GAIN_X32 = 0x2, /* X32 */
  86.     PG_GAIN_X64 = 0x3, /* X64 */
  87. } CFG_PS_Gain;

  88. typedef enum
  89. {
  90.     LPMF_PERIOD_30K  = 0x0, /* LED pulse period = 30kHz */
  91.     LPMF_PERIOD_40K  = 0x1, /* LED pulse period = 40kHz */
  92.     LPMF_PERIOD_50K  = 0x2, /* LED pulse period = 50kHz */
  93.     LPMF_PERIOD_60K  = 0x3, /* LED pulse period = 60kHz(default) */
  94.     LPMF_PERIOD_70K  = 0x4, /* LED pulse period = 70kHz */
  95.     LPMF_PERIOD_80K  = 0x5, /* LED pulse period = 80kHz */
  96.     LPMF_PERIOD_90K  = 0x6, /* LED pulse period = 90kHz */
  97.     LPMF_PERIOD_100K = 0x7, /* LED pulse period = 100kHz */
  98. } CFG_LED_pulse_Modulation_Frequency;

  99. typedef enum
  100. {
  101.     LCD_PER_25  = 0x0, /* DUTY = 25% */
  102.     LCD_PER_50  = 0x1, /* DUTY = 50% */
  103.     LCD_PER_75  = 0x2, /* DUTY = 75% */
  104.     LCD_PER_100 = 0x3, /* DUTY = 100%(default) */
  105. } CFG_LED_Current_DUTY;

  106. typedef enum
  107. {
  108.     LC_LEVEL_5   = 0x0, /* LED pulse current level = 5mA */
  109.     LC_LEVEL_10  = 0x1, /* LED pulse current level = 10mA */
  110.     LC_LEVEL_20  = 0x2, /* LED pulse current level = 20mA */
  111.     LC_LEVEL_50  = 0x3, /* LED pulse current level = 50mA */
  112.     LC_LEVEL_100 = 0x4, /* LED pulse current level = 100mA(default) */
  113. } CFG_LED_Current;

  114. typedef enum
  115. {
  116.     PMR_RATE_50   = 0x0, /* PS Measurement Repeat Rate = 50ms */
  117.     PMR_RATE_70   = 0x1, /* PS Measurement Repeat Rate = 70ms */
  118.     PMR_RATE_100  = 0x2, /* PS Measurement Repeat Rate = 100ms(default) */
  119.     PMR_RATE_200  = 0x3, /* PS Measurement Repeat Rate = 200ms */
  120.     PMR_RATE_500  = 0x4, /* PS Measurement Repeat Rate = 500ms */
  121.     PMR_RATE_1000 = 0x5, /* PS Measurement Repeat Rate = 1000ms */
  122.     PMR_RATE_2000 = 0x6, /* PS Measurement Repeat Rate = 2000ms */
  123.     PMR_RATE_10   = 0x8, /* PS Measurement Repeat Rate = 10ms */
  124. } CFG_PS_measurement_rate;

  125. typedef enum
  126. {
  127.     AIT_TIME_100 = 0x0, /* ALS integration_time = 100ms(default) */
  128.     AIT_TIME_50  = 0x1, /* ALS integration_time = 50ms */
  129.     AIT_TIME_200 = 0x2, /* ALS integration_time = 200ms */
  130.     AIT_TIME_400 = 0x3, /* ALS integration_time = 400ms */
  131.     AIT_TIME_150 = 0x4, /* ALS integration_time = 150ms */
  132.     AIT_TIME_250 = 0x5, /* ALS integration_time = 250ms */
  133.     AIT_TIME_300 = 0x6, /* ALS integration_time = 300ms */
  134.     AIT_TIME_350 = 0x7, /* ALS integration_time = 350ms */
  135. } CFG_ALS_integration_time;

  136. typedef enum
  137. {
  138.     AMR_RATE_50   = 0x0, /* ALS Measurement Repeat Rate = 50ms */
  139.     AMR_RATE_100  = 0x1, /* ALS Measurement Repeat Rate = 100ms */
  140.     AMR_RATE_200  = 0x2, /* ALS Measurement Repeat Rate = 200ms */
  141.     AMR_RATE_500  = 0x3, /* ALS Measurement Repeat Rate = 500ms(default) */
  142.     AMR_RATE_1000 = 0x4, /* ALS Measurement Repeat Rate = 1000ms */
  143.     AMR_RATE_2000 = 0x5, /* ALS Measurement Repeat Rate = 2000ms */
  144. } CFG_ALS_measurement_rate;

  145. typedef enum
  146. {
  147.     PM_MODE_STANDBY = 0,
  148.     PM_MODE_ACTIVE  = 3,
  149. } CFG_PS_mode;

  150. typedef enum
  151. {
  152.     AM_MODE_STANDBY = 0,
  153.     AM_MODE_ACTIVE  = 1,
  154. } CFG_ALS_mode;

  155. typedef enum
  156. {
  157.     ADS_STATUS_OLD = 0,
  158.     ADS_STATUS_NEW = 1,
  159. } CFG_ALS_data_status;

  160. typedef enum
  161. {
  162.     PDS_STATUS_OLD = 0,
  163.     PDS_STATUS_NEW = 1,
  164. } CFG_PS_data_status;

  165. typedef enum
  166. {
  167.     FLAG_INIT_ALS = 0,
  168.     FLAG_INIT_PS,
  169. } FLAG_INIT_BIT;

  170. typedef enum {
  171.     DEV_POWER_OFF = 0,
  172.     DEV_POWER_ON,
  173.     DEV_SLEEP,
  174.     DEV_SUSPEND,
  175.     DEV_DEEP_SUSPEND,
  176. } LTR_power_mode;

  177. uint8_t LTR553_id_check()
  178. {
  179.         HAL_StatusTypeDef hi2c2_status = 0x00;
  180.         /*ID check*/
  181.         //LTR553_PART_ID=0X86,LTR553_MANUFAC_ID=0X87
  182.         //LTR553_PART_ID_VAL=0X92,LTR553_MANUFAC_ID_VAL=0X05
  183.         uint8_t id_addr_val[6] = {LTR553_PART_ID,LTR553_PART_ID_VAL,0x00,LTR553_MANUFAC_ID,LTR553_MANUFAC_ID_VAL,0x00};
  184.         hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,LTR553_I2C_ADDR,id_addr_val[0],1,&id_addr_val[2],1,1000);
  185.         if(HAL_OK!=hi2c2_status){
  186.                 printf("get part_id error\r\n");
  187.                 return 1;
  188.         }
  189.         hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,LTR553_I2C_ADDR,id_addr_val[3],1,&id_addr_val[5],1,1000);
  190.         if(HAL_OK!=hi2c2_status){
  191.                 printf("get manufac_id error\r\n");
  192.                 return 1;
  193.         }
  194.         if(id_addr_val[1]!=id_addr_val[2]||id_addr_val[4]!=id_addr_val[5]){
  195.                 printf("drv_als_ps_liteon_ltr553_validate_id is error\r\n");
  196.                 return 1;
  197.         }
  198.         printf("part_id:%02X,manufac_id:%02X\r\n",id_addr_val[2],id_addr_val[5]);
  199.         return 0;
  200. }

  201. uint8_t ltr553_als_set_power_mode(LTR_power_mode mode)
  202. {
  203.         HAL_StatusTypeDef hi2c2_status = 0x00;
  204.         uint8_t dev_mode  = 0;
  205.         uint8_t value     = 0;

  206.         hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,LTR553_I2C_ADDR,LTR553_ALS_CONTR,1,&value,1,WAIT_FOREVER);
  207.         if(HAL_OK!=hi2c2_status){
  208.                 printf("get als_contr error\r\n");
  209.                 return 1;
  210.         }
  211.         printf("ALS_CONTR old:%02X\r\n",value);
  212.     switch (mode) {
  213.         case DEV_POWER_OFF:
  214.         case DEV_SLEEP:
  215.             dev_mode = LTR553_SET_BITSLICE(dev_mode, LTR553_ALS_CONTR_REG_ALS_MODE, AM_MODE_STANDBY);
  216.             break;
  217.         case DEV_POWER_ON:
  218.             dev_mode = LTR553_SET_BITSLICE(dev_mode, LTR553_ALS_CONTR_REG_ALS_MODE, AM_MODE_ACTIVE);
  219.             break;
  220.         default:
  221.             return 1;
  222.     }
  223.     printf("ALS_CONTR new:%02X\r\n",dev_mode);
  224.         hi2c2_status = HAL_I2C_Mem_Write(&hi2c2,LTR553_I2C_ADDR,LTR553_ALS_CONTR,1,&dev_mode,1,WAIT_FOREVER);
  225.         if(HAL_OK!=hi2c2_status){
  226.                 printf("set ALS_CONTR error\r\n");
  227.                 return 1;
  228.         }
  229.         printf("successfully LTR553_ALS set_power_mode!\r\n");
  230.     return 0;
  231. }

  232. uint8_t ltr553_ps_set_power_mode(LTR_power_mode mode)
  233. {
  234.         HAL_StatusTypeDef hi2c2_status = 0x00;
  235.         uint8_t dev_mode  = 0;
  236.         uint8_t value     = 0;

  237.         hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,LTR553_I2C_ADDR,LTR553_PS_CONTR,1,&value,1,WAIT_FOREVER);
  238.         if(HAL_OK!=hi2c2_status){
  239.                 printf("get ps_contr error\r\n");
  240.                 return 1;
  241.         }
  242.         printf("PS_CONTR old:%02X\r\n",value);
  243.     switch (mode) {
  244.         case DEV_POWER_OFF:
  245.         case DEV_SLEEP:
  246.             dev_mode = LTR553_SET_BITSLICE(value, LTR553_PS_CONTR_REG_PS_MODE,PM_MODE_STANDBY);
  247.             break;
  248.         case DEV_POWER_ON:
  249.             dev_mode = LTR553_SET_BITSLICE(value, LTR553_PS_CONTR_REG_PS_MODE,PM_MODE_ACTIVE);
  250.             break;
  251.         default:
  252.             return 1;
  253.     }
  254.     printf("ALS_CONTR new:%02X\r\n",dev_mode);
  255.         hi2c2_status = HAL_I2C_Mem_Write(&hi2c2,LTR553_I2C_ADDR,LTR553_PS_CONTR,1,&dev_mode,1,WAIT_FOREVER);
  256.         if(HAL_OK!=hi2c2_status){
  257.                 printf("set PS_CONTR error\r\n");
  258.                 return 1;
  259.         }
  260.         printf("successfully LTR553_PS set_power_mode!\r\n");
  261.     return 0;
  262. }

  263. uint8_t ltr553_als_is_ready()
  264. {
  265.         HAL_StatusTypeDef hi2c2_status = 0x00;
  266.         uint8_t value = 0;
  267.         hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,LTR553_I2C_ADDR,LTR553_ALS_PS_STATUS,1,&value,1,WAIT_FOREVER);
  268.         if(HAL_OK!=hi2c2_status){
  269.                 printf("get ps_contr error\r\n");
  270.                 return 0;
  271.         }
  272. //        printf("PS_CONTR old:%02X\r\n",value);
  273.         uint8_t ret = (LTR553_GET_BITSLICE(value, LTR553_ALS_PS_STATUS_REG_ALS_STATUS) == ADS_STATUS_NEW)? 1 : 0;
  274.         return ret;
  275. }

  276. uint8_t ltr553_ps_is_ready()
  277. {
  278.         HAL_StatusTypeDef hi2c2_status = 0x00;
  279.         uint8_t value = 0;
  280.         hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,LTR553_I2C_ADDR,LTR553_ALS_PS_STATUS,1,&value,1,WAIT_FOREVER);
  281.         if(HAL_OK!=hi2c2_status){
  282.                 printf("get ps_contr error\r\n");
  283.                 return 0;
  284.         }
  285. //        printf("PS_CONTR old:%02X\r\n",value);
  286.         uint8_t ret = (LTR553_GET_BITSLICE(value, LTR553_ALS_PS_STATUS_REG_PS_STATUS) == PDS_STATUS_NEW)? 1 : 0;
  287.         return ret;
  288. }

  289. uint8_t ltr553_als_set_default_config()
  290. {
  291.         HAL_StatusTypeDef hi2c2_status = 0x00;
  292.         uint8_t value = 0;
  293.         value = LTR553_SET_BITSLICE(value, LTR553_ALS_MEAS_RATE_REG_INTEG_TIME,AIT_TIME_100);
  294.         value = LTR553_SET_BITSLICE(value, LTR553_ALS_MEAS_RATE_REG_MEAS_RATE,AMR_RATE_100);
  295.         printf("ALS_MEAS_RATE:%02X\r\n",value);
  296.         hi2c2_status = HAL_I2C_Mem_Write(&hi2c2,LTR553_I2C_ADDR,LTR553_ALS_MEAS_RATE,1,&value,1,WAIT_FOREVER);
  297.         if(HAL_OK!=hi2c2_status){
  298.                 printf("set ALS_MEAS_RATE error\r\n");
  299.                 return 1;
  300.         }
  301.         hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,LTR553_I2C_ADDR,LTR553_ALS_CONTR,1,&value,1,WAIT_FOREVER);
  302.         if(HAL_OK!=hi2c2_status){
  303.                 printf("get als_contr error\r\n");
  304.                 return 1;
  305.         }
  306.         printf("ALS_CONTR old:%02X\r\n",value);
  307.         value =        LTR553_SET_BITSLICE(value, LTR553_ALS_CONTR_REG_ALS_GAIN, AG_GAIN_1X);
  308.         printf("ALS_CONTR new:%02X\r\n",value);
  309.         hi2c2_status = HAL_I2C_Mem_Write(&hi2c2,LTR553_I2C_ADDR,LTR553_ALS_CONTR,1,&value,1,WAIT_FOREVER);
  310.         if(HAL_OK!=hi2c2_status){
  311.                 printf("get ALS_CONTR error\r\n");
  312.                 return 1;
  313.         }
  314.         printf("successfully LTR553_ALS_default_config!\r\n");
  315.         return 0;
  316. }

  317. uint8_t ltr553_ps_set_default_config()
  318. {
  319.         HAL_StatusTypeDef hi2c2_status = 0x00;
  320.         //LTR553_PS_MEAS_RATE=0X84,LTR553_PS_LED=0X82,LTR553_PS_CONTR=0X81
  321.         uint8_t value = 0;
  322.         value = LTR553_SET_BITSLICE(value, LTR553_PS_MEAS_RATE_REG_MEAS_RATE,PMR_RATE_100);
  323.         printf("PS_MEAS_RATE:%02X\r\n",value);
  324.         hi2c2_status = HAL_I2C_Mem_Write(&hi2c2,LTR553_I2C_ADDR,LTR553_PS_MEAS_RATE,1,&value,1,1000);
  325.         if(HAL_OK!=hi2c2_status){
  326.                 printf("set PS_MEAS_RATE error\r\n");
  327.                 return 1;
  328.         }
  329.         //value default 0X7F
  330.         value = LTR553_SET_BITSLICE(value, LTR553_PS_LED_REG_PLUSE_FREQ, LPMF_PERIOD_60K);
  331.         value = LTR553_SET_BITSLICE(value, LTR553_PS_LED_REG_CURRENT_DUTY, LCD_PER_100);
  332.         value = LTR553_SET_BITSLICE(value, LTR553_PS_LED_REG_CURRENT, LC_LEVEL_100);
  333.         printf("PS_LED:%02X\r\n",value);
  334.         hi2c2_status = HAL_I2C_Mem_Write(&hi2c2,LTR553_I2C_ADDR,LTR553_PS_MEAS_RATE,1,&value,1,1000);
  335.         if(HAL_OK!=hi2c2_status){
  336.                 printf("get PS_LED error\r\n");
  337.                 return 1;
  338.         }
  339.         //check
  340.         hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,LTR553_I2C_ADDR,LTR553_PS_CONTR,1,&value,1,WAIT_FOREVER);
  341.         if(HAL_OK!=hi2c2_status){
  342.                 printf("get ps_contr error\r\n");
  343.                 return 1;
  344.         }
  345.         printf("PS_CONTR old:%02X\r\n",value);
  346.         value = LTR553_SET_BITSLICE(value, LTR553_PS_CONTR_REG_PS_GAIN, PG_GAIN_X16);
  347.         printf("PS_CONTR new:%02X\r\n",value);
  348.         //
  349.         hi2c2_status = HAL_I2C_Mem_Write(&hi2c2,LTR553_I2C_ADDR,LTR553_PS_CONTR,1,&value,1,1000);
  350.         if(HAL_OK!=hi2c2_status){
  351.                 printf("get PS_CONTR error\r\n");
  352.                 return 1;
  353.         }
  354.         printf("successfully LTR553_PS default_config!\r\n");
  355.         return 0;
  356. }

  357. uint8_t ltr553_als_open()
  358. {
  359.         uint8_t ret = 0;

  360.         ret = ltr553_als_set_power_mode(DEV_POWER_ON);
  361.     if (ret>0) {
  362.         return 1;
  363.     }
  364.     printf("successfully LTR553_ALS Open!\r\n");
  365.     return 0;
  366. }

  367. uint8_t ltr553_als_close()
  368. {
  369.         uint8_t ret = 0;

  370.         ret = ltr553_als_set_power_mode(DEV_POWER_OFF);
  371.     if (ret>0) {
  372.         return 1;
  373.     }
  374.     printf("successfully LTR553_ALS Close!\r\n");
  375.     return 0;
  376. }

  377. uint8_t ltr553_ps_open()
  378. {
  379.         uint8_t ret = 0;

  380.         ret = ltr553_ps_set_power_mode(DEV_POWER_ON);
  381.     if (ret>0) {
  382.         return 1;
  383.     }
  384.     printf("successfully LTR553_ALS Open!\r\n");
  385.     return 0;
  386. }

  387. uint8_t ltr553_ps_close()
  388. {
  389.         uint8_t ret = 0;

  390.         ret = ltr553_ps_set_power_mode(DEV_POWER_OFF);
  391.     if (ret>0) {
  392.         return 1;
  393.     }
  394.     printf("successfully LTR553_ALS Close!\r\n");
  395.     return 0;
  396. }

  397. void LTR_ALS_init()
  398. {
  399.         /*ID check*/
  400.         if(LTR553_id_check()>0){
  401.                 return;
  402.         }
  403.         if(ltr553_als_set_default_config()>0)
  404.                 return;
  405.         printf("successfully LTR553_ALS_init!\r\n");
  406. }

  407. void LTR_PS_init()
  408. {
  409.         /*ID check*/
  410.         if(LTR553_id_check()){
  411.                 return;
  412.         }
  413.         /*PS check*/
  414.         if(ltr553_ps_set_default_config()>0)
  415.                 return;
  416.         printf("successfully LTR553_PS_init!\r\n");
  417. }

  418. uint8_t read_als(uint32_t *als_data)
  419. {
  420.         HAL_StatusTypeDef hi2c2_status = 0x00;
  421.         /*
  422.          * LTR553_ALS_DATA1_L=0X88,LTR553_ALS_DATA1_H=0X89
  423.          * LTR553_ALS_DATA0_L=0X8A,LTR553_ALS_DATA0_H=0X8B
  424.          */
  425.         uint8_t ALS_addr[4] = {LTR553_ALS_DATA1_L,LTR553_ALS_DATA1_H
  426.                         ,LTR553_ALS_DATA0_L,LTR553_ALS_DATA0_H};
  427.         uint8_t ALS_data[4] = {0x00};
  428.         for(uint8_t i=0; i<4; i++){
  429.                 hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,LTR553_I2C_ADDR,ALS_addr[i],1,&ALS_data[i],1,1000);
  430.                 if(HAL_OK!=hi2c2_status){
  431.                                 return 1;
  432.                 }
  433.         }
  434.         uint32_t val01 = ALS_data[0]|(ALS_data[1]<<8);
  435.     uint32_t val02 = ALS_data[2]|(ALS_data[3]<<8);
  436.     printf("val01:%lu,val02:%lu\n",val01,val01);
  437.     *als_data =  (uint32_t)((val01 + val02) >> 1);
  438.     printf("als_data: %lu\r\n",*als_data);
  439.     return 0;
  440. }

  441. uint8_t read_ps(uint32_t *ps_data)
  442. {
  443.         HAL_StatusTypeDef hi2c2_status = 0x00;
  444.         /*
  445.          * LTR553_PS_DATA_L=0X8D,LTR553_PS_DATA_H=0X8E
  446.          */
  447.     uint8_t PS_addr[2] = {LTR553_PS_DATA_L,LTR553_PS_DATA_H};
  448.     uint8_t PS_data[2] = {0x00};
  449.     for(uint8_t i=0; i<2; i++){
  450.                 hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,LTR553_I2C_ADDR,PS_addr[i],1,&PS_data[i],1,1000);
  451.                 if(HAL_OK!=hi2c2_status){
  452.                                 return 1;
  453.                 }
  454.         }
  455.     uint32_t val03 = PS_data[0]|(PS_data[1]<<8);
  456.     printf("val03:%lu\n",val03);
  457.     *ps_data = val03;
  458.     printf("ps_data: %lu\r\n",*ps_data);
  459.     return 0;
  460. }
复制代码

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

74f6fd3d0e7a4517a5bb79b509a6b2b1.png

        1)I2C读写通信设计如下

ad1fca78c2194d52b84959127c53b741.png

3fbe006a91a24437b47869e5dcda1044.png

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

8de58caea465444688733403a358af08.png

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

f9111f328f404014a910ce94bc0e5cf8.png

66929cf672094ac5a0284cc48494a1ba.png

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

232f98f958884fc2a59c8f3989b31065.png

cfaae6539eff4b08ba3cda4367825a98.png


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

ca5a19d5ffb7425a8d6ba9bab17fc902.png

3d42145639cf48519c80f71cb2a96dd8.png

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

26bfbf7e4cb64ea0a8700df1ad3ef384.png

16737cecdc1742e8aa7fe1a60a34caba.png

         7)至此可设计出BMP280的伪代码
  1. bmp280从机地址0XEE
  2. init:
  3. read data1 from 从机地址0XEE 寄存器地址 0XD0
  4. 确保data1==0X58
  5. write 0XB6 to 从机地址0XEE 寄存器地址 0XE0 完成软重置
  6. write val1 to 从机地址0XEE 寄存器地址 0XF4 完成设备模式设置
  7. write val2 to 从机地址0XEE 寄存器地址 0XF5 完成设备参数设置
  8. read conf1~24 from 从机地址0XEE 寄存器地址 0X88~0XA1 获取数据换算微调参数

  9. 读取数据:
  10. 确保设备为正常模式,例如write 0X03 to 从机地址0XEE 寄存器地址 0XF4 完成设备模式设置
  11. read P1~3 from 从机地址0XEE 寄存器地址 0XF7~F9
  12. 将P1~3与conf4~24进行换算处理得到实际数据
  13. read t1~3 from 从机地址0XEE 寄存器地址 0XFA~FC
  14. 将t1~3与conf1~3进行换算处理得到实际数据
复制代码

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

        bmp280.h
  1. #ifndef _BMP280_H_
  2. #define _BMP280_H_

  3. #include "main.h"

  4. void BMP280_init();
  5. uint8_t bmp280_open(void);
  6. uint8_t bmp280_close(void);
  7. uint8_t read_bmp280_temp(uint32_t *comp_temp);
  8. uint8_t read_bmp280_baro(uint32_t *comp_baro);
  9. #endif /* BMP280_BMP280_H_ */
复制代码

         bmp280.c
  1. #include <stdio.h>
  2. #include "bmp280.h"

  3. extern I2C_HandleTypeDef hi2c2;

  4. #define BMP280_TEMPERATURE_CALIB_DIG_T1_LSB_REG (0x88)
  5. #define BMP280_TEMPERATURE_CALIB_DIG_T1_MSB_REG (0x89)
  6. #define BMP280_TEMPERATURE_CALIB_DIG_T2_LSB_REG (0x8A)
  7. #define BMP280_TEMPERATURE_CALIB_DIG_T2_MSB_REG (0x8B)
  8. #define BMP280_TEMPERATURE_CALIB_DIG_T3_LSB_REG (0x8C)
  9. #define BMP280_TEMPERATURE_CALIB_DIG_T3_MSB_REG (0x8D)
  10. #define BMP280_PRESSURE_CALIB_DIG_P1_LSB_REG (0x8E)
  11. #define BMP280_PRESSURE_CALIB_DIG_P1_MSB_REG (0x8F)
  12. #define BMP280_PRESSURE_CALIB_DIG_P2_LSB_REG (0x90)
  13. #define BMP280_PRESSURE_CALIB_DIG_P2_MSB_REG (0x91)
  14. #define BMP280_PRESSURE_CALIB_DIG_P3_LSB_REG (0x92)
  15. #define BMP280_PRESSURE_CALIB_DIG_P3_MSB_REG (0x93)
  16. #define BMP280_PRESSURE_CALIB_DIG_P4_LSB_REG (0x94)
  17. #define BMP280_PRESSURE_CALIB_DIG_P4_MSB_REG (0x95)
  18. #define BMP280_PRESSURE_CALIB_DIG_P5_LSB_REG (0x96)
  19. #define BMP280_PRESSURE_CALIB_DIG_P5_MSB_REG (0x97)
  20. #define BMP280_PRESSURE_CALIB_DIG_P6_LSB_REG (0x98)
  21. #define BMP280_PRESSURE_CALIB_DIG_P6_MSB_REG (0x99)
  22. #define BMP280_PRESSURE_CALIB_DIG_P7_LSB_REG (0x9A)
  23. #define BMP280_PRESSURE_CALIB_DIG_P7_MSB_REG (0x9B)
  24. #define BMP280_PRESSURE_CALIB_DIG_P8_LSB_REG (0x9C)
  25. #define BMP280_PRESSURE_CALIB_DIG_P8_MSB_REG (0x9D)
  26. #define BMP280_PRESSURE_CALIB_DIG_P9_LSB_REG (0x9E)
  27. #define BMP280_PRESSURE_CALIB_DIG_P9_MSB_REG (0x9F)


  28. #define BMP280_CHIP_ID_REG (0xD0)
  29. #define BMP280_RST_REG (0xE0)
  30. #define BMP280_STAT_REG (0xF3)
  31. #define BMP280_CTRL_MEAS_REG (0xF4)
  32. #define BMP280_CONFIG_REG (0xF5)
  33. #define BMP280_PRESSURE_MSB_REG (0xF7)
  34. #define BMP280_PRESSURE_LSB_REG (0xF8)
  35. #define BMP280_PRESSURE_XLSB_REG (0xF9)
  36. #define BMP280_TEMPERATURE_MSB_REG (0xFA)
  37. #define BMP280_TEMPERATURE_LSB_REG (0xFB)
  38. #define BMP280_TEMPERATURE_XLSB_REG (0xFC)


  39. #define BMP280_SHIFT_BY_01_BIT (1)
  40. #define BMP280_SHIFT_BY_02_BITS (2)
  41. #define BMP280_SHIFT_BY_03_BITS (3)
  42. #define BMP280_SHIFT_BY_04_BITS (4)
  43. #define BMP280_SHIFT_BY_05_BITS (5)
  44. #define BMP280_SHIFT_BY_08_BITS (8)
  45. #define BMP280_SHIFT_BY_11_BITS (11)
  46. #define BMP280_SHIFT_BY_12_BITS (12)
  47. #define BMP280_SHIFT_BY_13_BITS (13)
  48. #define BMP280_SHIFT_BY_14_BITS (14)
  49. #define BMP280_SHIFT_BY_15_BITS (15)
  50. #define BMP280_SHIFT_BY_16_BITS (16)
  51. #define BMP280_SHIFT_BY_17_BITS (17)
  52. #define BMP280_SHIFT_BY_18_BITS (18)
  53. #define BMP280_SHIFT_BY_19_BITS (19)
  54. #define BMP280_SHIFT_BY_25_BITS (25)
  55. #define BMP280_SHIFT_BY_31_BITS (31)
  56. #define BMP280_SHIFT_BY_33_BITS (33)
  57. #define BMP280_SHIFT_BY_35_BITS (35)
  58. #define BMP280_SHIFT_BY_47_BITS (47)


  59. #define BMP280_PRESSURE_TEMPERATURE_CALIB_DATA_LENGTH (24)
  60. #define BMP280_GEN_READ_WRITE_DATA_LENGTH (1)
  61. #define BMP280_REGISTER_READ_DELAY (1)
  62. #define BMP280_TEMPERATURE_DATA_LENGTH (3)
  63. #define BMP280_PRESSURE_DATA_LENGTH (3)
  64. #define BMP280_ALL_DATA_FRAME_LENGTH (6)
  65. #define BMP280_INIT_VALUE (0)
  66. #define BMP280_CHIP_ID_READ_COUNT (5)
  67. #define BMP280_CHIP_ID_READ_SUCCESS (0)
  68. #define BMP280_CHIP_ID_READ_FAIL ((int8_t)-1)
  69. #define BMP280_INVALID_DATA (0)


  70. #define BMP280_TEMPERATURE_DATA_SIZE (3)
  71. #define BMP280_PRESSURE_DATA_SIZE (3)
  72. #define BMP280_DATA_FRAME_SIZE (6)
  73. #define BMP280_CALIB_DATA_SIZE (24)

  74. #define BMP280_TEMPERATURE_MSB_DATA (0)
  75. #define BMP280_TEMPERATURE_LSB_DATA (1)
  76. #define BMP280_TEMPERATURE_XLSB_DATA (2)


  77. #define BMP280_I2C_ADDRESS1 (0x76)
  78. #define BMP280_I2C_ADDRESS2 (0x77)


  79. #define BMP280_SLEEP_MODE (0x00)
  80. #define BMP280_FORCED_MODE (0x01)
  81. #define BMP280_NORMAL_MODE (0x03)
  82. #define BMP280_SOFT_RESET_CODE (0xB6)


  83. #define BMP280_STANDBY_TIME_1_MS (0x00)
  84. #define BMP280_STANDBY_TIME_63_MS (0x01)
  85. #define BMP280_STANDBY_TIME_125_MS (0x02)
  86. #define BMP280_STANDBY_TIME_250_MS (0x03)
  87. #define BMP280_STANDBY_TIME_500_MS (0x04)
  88. #define BMP280_STANDBY_TIME_1000_MS (0x05)
  89. #define BMP280_STANDBY_TIME_2000_MS (0x06)
  90. #define BMP280_STANDBY_TIME_4000_MS (0x07)


  91. #define BMP280_OVERSAMP_SKIPPED (0x00)
  92. #define BMP280_OVERSAMP_1X (0x01)
  93. #define BMP280_OVERSAMP_2X (0x02)
  94. #define BMP280_OVERSAMP_4X (0x03)
  95. #define BMP280_OVERSAMP_8X (0x04)
  96. #define BMP280_OVERSAMP_16X (0x05)

  97. #define BMP280_FILTER_COEFF_OFF (0x00)
  98. #define BMP280_FILTER_COEFF_2 (0x01)
  99. #define BMP280_FILTER_COEFF_4 (0x02)
  100. #define BMP280_FILTER_COEFF_8 (0x03)
  101. #define BMP280_FILTER_COEFF_16 (0x04)


  102. #define BMP280_ULTRA_LOW_POWER_MODE (0x00)
  103. #define BMP280_LOW_POWER_MODE (0x01)
  104. #define BMP280_STANDARD_RESOLUTION_MODE (0x02)
  105. #define BMP280_HIGH_RESOLUTION_MODE (0x03)
  106. #define BMP280_ULTRA_HIGH_RESOLUTION_MODE (0x04)

  107. #define BMP280_ULTRALOWPOWER_OVERSAMP_PRESSURE BMP280_OVERSAMP_1X
  108. #define BMP280_ULTRALOWPOWER_OVERSAMP_TEMPERATURE BMP280_OVERSAMP_1X

  109. #define BMP280_LOWPOWER_OVERSAMP_PRESSURE BMP280_OVERSAMP_2X
  110. #define BMP280_LOWPOWER_OVERSAMP_TEMPERATURE BMP280_OVERSAMP_1X

  111. #define BMP280_STANDARDRESOLUTION_OVERSAMP_PRESSURE BMP280_OVERSAMP_4X
  112. #define BMP280_STANDARDRESOLUTION_OVERSAMP_TEMPERATURE BMP280_OVERSAMP_1X

  113. #define BMP280_HIGHRESOLUTION_OVERSAMP_PRESSURE BMP280_OVERSAMP_8X
  114. #define BMP280_HIGHRESOLUTION_OVERSAMP_TEMPERATURE BMP280_OVERSAMP_1X

  115. #define BMP280_ULTRAHIGHRESOLUTION_OVERSAMP_PRESSURE BMP280_OVERSAMP_16X
  116. #define BMP280_ULTRAHIGHRESOLUTION_OVERSAMP_TEMPERATURE BMP280_OVERSAMP_2X


  117. #define BMP280_STATUS_REG_MEASURING__POS (3)
  118. #define BMP280_STATUS_REG_MEASURING__MSK (0x08)
  119. #define BMP280_STATUS_REG_MEASURING__LEN (1)
  120. #define BMP280_STATUS_REG_MEASURING__REG (BMP280_STAT_REG)

  121. #define BMP280_STATUS_REG_IM_UPDATE__POS (0)
  122. #define BMP280_STATUS_REG_IM_UPDATE__MSK (0x01)
  123. #define BMP280_STATUS_REG_IM_UPDATE__LEN (1)
  124. #define BMP280_STATUS_REG_IM_UPDATE__REG (BMP280_STAT_REG)


  125. #define BMP280_CTRL_MEAS_REG_OVERSAMP_TEMPERATURE__POS (5)
  126. #define BMP280_CTRL_MEAS_REG_OVERSAMP_TEMPERATURE__MSK (0xE0)
  127. #define BMP280_CTRL_MEAS_REG_OVERSAMP_TEMPERATURE__LEN (3)
  128. #define BMP280_CTRL_MEAS_REG_OVERSAMP_TEMPERATURE__REG (BMP280_CTRL_MEAS_REG)


  129. #define BMP280_CTRL_MEAS_REG_OVERSAMP_PRESSURE__POS (2)
  130. #define BMP280_CTRL_MEAS_REG_OVERSAMP_PRESSURE__MSK (0x1C)
  131. #define BMP280_CTRL_MEAS_REG_OVERSAMP_PRESSURE__LEN (3)
  132. #define BMP280_CTRL_MEAS_REG_OVERSAMP_PRESSURE__REG (BMP280_CTRL_MEAS_REG)

  133. #define BMP280_CTRL_MEAS_REG_POWER_MODE__POS (0)
  134. #define BMP280_CTRL_MEAS_REG_POWER_MODE__MSK (0x03)
  135. #define BMP280_CTRL_MEAS_REG_POWER_MODE__LEN (2)
  136. #define BMP280_CTRL_MEAS_REG_POWER_MODE__REG (BMP280_CTRL_MEAS_REG)


  137. #define BMP280_CONFIG_REG_STANDBY_DURN__POS (5)
  138. #define BMP280_CONFIG_REG_STANDBY_DURN__MSK (0xE0)
  139. #define BMP280_CONFIG_REG_STANDBY_DURN__LEN (3)
  140. #define BMP280_CONFIG_REG_STANDBY_DURN__REG (BMP280_CONFIG_REG)

  141. #define BMP280_CONFIG_REG_FILTER__POS (2)
  142. #define BMP280_CONFIG_REG_FILTER__MSK (0x1C)
  143. #define BMP280_CONFIG_REG_FILTER__LEN (3)
  144. #define BMP280_CONFIG_REG_FILTER__REG (BMP280_CONFIG_REG)


  145. #define BMP280_CONFIG_REG_SPI3_ENABLE__POS (0)
  146. #define BMP280_CONFIG_REG_SPI3_ENABLE__MSK (0x01)
  147. #define BMP280_CONFIG_REG_SPI3_ENABLE__LEN (1)
  148. #define BMP280_CONFIG_REG_SPI3_ENABLE__REG (BMP280_CONFIG_REG)


  149. #define BMP280_PRESSURE_XLSB_REG_DATA__POS (4)
  150. #define BMP280_PRESSURE_XLSB_REG_DATA__MSK (0xF0)
  151. #define BMP280_PRESSURE_XLSB_REG_DATA__LEN (4)
  152. #define BMP280_PRESSURE_XLSB_REG_DATA__REG (BMP280_PRESSURE_XLSB_REG)

  153. #define BMP280_TEMPERATURE_XLSB_REG_DATA__POS (4)
  154. #define BMP280_TEMPERATURE_XLSB_REG_DATA__MSK (0xF0)
  155. #define BMP280_TEMPERATURE_XLSB_REG_DATA__LEN (4)
  156. #define BMP280_TEMPERATURE_XLSB_REG_DATA__REG (BMP280_TEMPERATURE_XLSB_REG)

  157. #define BMP280_TEMPERATURE_MSB_DATA (0)
  158. #define BMP280_TEMPERATURE_LSB_DATA (1)
  159. #define BMP280_TEMPERATURE_XLSB_DATA (2)

  160. #define BMP280_PRESSURE_MSB_DATA (0)
  161. #define BMP280_PRESSURE_LSB_DATA (1)
  162. #define BMP280_PRESSURE_XLSB_DATA (2)

  163. #define BMP280_DATA_FRAME_PRESSURE_MSB_BYTE (0)
  164. #define BMP280_DATA_FRAME_PRESSURE_LSB_BYTE (1)
  165. #define BMP280_DATA_FRAME_PRESSURE_XLSB_BYTE (2)
  166. #define BMP280_DATA_FRAME_TEMPERATURE_MSB_BYTE (3)
  167. #define BMP280_DATA_FRAME_TEMPERATURE_LSB_BYTE (4)
  168. #define BMP280_DATA_FRAME_TEMPERATURE_XLSB_BYTE (5)

  169. #define BMP280_TEMPERATURE_CALIB_DIG_T1_LSB (0)
  170. #define BMP280_TEMPERATURE_CALIB_DIG_T1_MSB (1)
  171. #define BMP280_TEMPERATURE_CALIB_DIG_T2_LSB (2)
  172. #define BMP280_TEMPERATURE_CALIB_DIG_T2_MSB (3)
  173. #define BMP280_TEMPERATURE_CALIB_DIG_T3_LSB (4)
  174. #define BMP280_TEMPERATURE_CALIB_DIG_T3_MSB (5)
  175. #define BMP280_PRESSURE_CALIB_DIG_P1_LSB (6)
  176. #define BMP280_PRESSURE_CALIB_DIG_P1_MSB (7)
  177. #define BMP280_PRESSURE_CALIB_DIG_P2_LSB (8)
  178. #define BMP280_PRESSURE_CALIB_DIG_P2_MSB (9)
  179. #define BMP280_PRESSURE_CALIB_DIG_P3_LSB (10)
  180. #define BMP280_PRESSURE_CALIB_DIG_P3_MSB (11)
  181. #define BMP280_PRESSURE_CALIB_DIG_P4_LSB (12)
  182. #define BMP280_PRESSURE_CALIB_DIG_P4_MSB (13)
  183. #define BMP280_PRESSURE_CALIB_DIG_P5_LSB (14)
  184. #define BMP280_PRESSURE_CALIB_DIG_P5_MSB (15)
  185. #define BMP280_PRESSURE_CALIB_DIG_P6_LSB (16)
  186. #define BMP280_PRESSURE_CALIB_DIG_P6_MSB (17)
  187. #define BMP280_PRESSURE_CALIB_DIG_P7_LSB (18)
  188. #define BMP280_PRESSURE_CALIB_DIG_P7_MSB (19)
  189. #define BMP280_PRESSURE_CALIB_DIG_P8_LSB (20)
  190. #define BMP280_PRESSURE_CALIB_DIG_P8_MSB (21)
  191. #define BMP280_PRESSURE_CALIB_DIG_P9_LSB (22)
  192. #define BMP280_PRESSURE_CALIB_DIG_P9_MSB (23)

  193. #define BMP280_SOFT_RESRT_VALUE (0XB6)

  194. #define BMP280_I2C_SLAVE_ADDR_LOW (0X76)
  195. #define BMP280_I2C_SLAVE_ADDR_HIGH (0X77)

  196. #define BMP280_DEFAULT_ODR_1HZ (1)

  197. #define BMP280_BIT(x) ((uint8_t)(x))
  198. #define BMP280_CHIP_ID_VAL BMP280_BIT(0X58)
  199. #define BMP280_I2C_ADDR_TRANS(n) ((n) << 1)
  200. #define BMP280_I2C_ADDR BMP280_I2C_ADDR_TRANS(BMP280_I2C_SLAVE_ADDR_HIGH)


  201. #define BMP280_GET_BITSLICE(regvar, bitname) \
  202.     ((regvar & bitname##__MSK) >> bitname##__POS)
  203. #define BMP280_SET_BITSLICE(regvar, bitname, val) \
  204.     ((regvar & ~bitname##__MSK) | ((val << bitname##__POS) & bitname##__MSK))

  205. typedef struct bmp280_calib_param_t
  206. {
  207.     uint16_t dig_T1;
  208.     int16_t  dig_T2;
  209.     int16_t  dig_T3;
  210.     uint16_t dig_P1;
  211.     int16_t  dig_P2;
  212.     int16_t  dig_P3;
  213.     int16_t  dig_P4;
  214.     int16_t  dig_P5;
  215.     int16_t  dig_P6;
  216.     int16_t  dig_P7;
  217.     int16_t  dig_P8;
  218.     int16_t  dig_P9;
  219.     int      t_fine;
  220. } bmp280_calib_param_t;

  221. typedef struct bmp280_device_cfg_t
  222. {
  223.     uint8_t odr;
  224.     uint8_t mode_filter;
  225.     uint8_t mode_baro;
  226.     uint8_t mode_temp;
  227.     uint8_t mode_power;
  228.     uint8_t oversamp_temp;
  229.     uint8_t oversamp_baro;
  230. } bmp280_device_cfg_t;

  231. typedef enum {
  232.     DEV_POWER_OFF = 0,
  233.     DEV_POWER_ON,
  234.     DEV_SLEEP,
  235.     DEV_SUSPEND,
  236.     DEV_DEEP_SUSPEND,
  237. } bmp280_power_mode;

  238. typedef enum {
  239.     SENSOR_IOCTL_ODR_SET = 1,
  240.     SENSOR_IOCTL_RANGE_SET,
  241.     SENSOR_IOCTL_SET_POWER,
  242.     SENSOR_IOCTL_GET_INFO,
  243.     SENSOR_IOCTL_MAX
  244. } cmd_type;

  245. static bmp280_calib_param_t g_bmp280_calib_table;


  246. uint8_t bmp280_id_check()
  247. {
  248.         HAL_StatusTypeDef hi2c2_status = 0x00;
  249.         /*ID check*/
  250.         //BMP280_CHIP_ID_REG = 0XD0,BMP280_CHIP_ID_VAL = 0X58
  251.         uint8_t id_addr_val[3] = {0xD0,0x58,0x00};
  252.         hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,BMP280_I2C_ADDR,id_addr_val[0],1,&id_addr_val[2],1,1000);
  253.         if(HAL_OK!=hi2c2_status){
  254.                 printf("get part_id error\r\n");
  255.                 return 1;
  256.         }
  257.         if(id_addr_val[1]!=id_addr_val[2]){
  258.                 printf("bmp280_validate_id is error\r\n");
  259.                 return 1;
  260.         }
  261.         printf("bmp280_id:%02X\r\n",id_addr_val[2]);
  262.         return 0;
  263. }

  264. uint8_t bmp280_reset()
  265. {
  266.         HAL_StatusTypeDef hi2c2_status = 0x00;
  267.         /*reset*/
  268.         //BMP280_RST_REG = 0XE0,BMP280_SOFT_RESRT_VALUE=0XB6
  269.         uint8_t addr_val[2] = {BMP280_RST_REG,BMP280_SOFT_RESRT_VALUE};
  270.         hi2c2_status = HAL_I2C_Mem_Write(&hi2c2,BMP280_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);
  271.         if(HAL_OK!=hi2c2_status){
  272.                 printf("bmp280_reset error\r\n");
  273.                 return 1;
  274.         }
  275.         return 0;
  276. }

  277. uint8_t bmp280_set_power_mode(bmp280_power_mode mode)
  278. {
  279.         uint8_t dev_mode = 0x00;
  280.     switch (mode) {
  281.         case DEV_POWER_OFF:
  282.         case DEV_SLEEP: {
  283.             dev_mode = (uint8_t)BMP280_SLEEP_MODE;
  284.             break;
  285.         }
  286.         case DEV_POWER_ON: {
  287.             dev_mode = (uint8_t)BMP280_NORMAL_MODE;
  288.             break;
  289.         }
  290.         default:
  291.             return 1;
  292.     }
  293.         HAL_StatusTypeDef hi2c2_status = 0x00;
  294.         //BMP280_CTRL_MEAS_REG=0XF4
  295.         uint8_t mode_addr_val[3] = {BMP280_CTRL_MEAS_REG,0x00,dev_mode};
  296.         hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,BMP280_I2C_ADDR,mode_addr_val[0],1,&mode_addr_val[1],1,1000);
  297.         if(HAL_OK!=hi2c2_status){
  298.                 printf("get bmp280_power_mode error\r\n");
  299.                 return 1;
  300.         }
  301.         printf("bmp280 mode_val[1]:%02X\r\n",mode_addr_val[1]);
  302.         mode_addr_val[1] = BMP280_SET_BITSLICE(mode_addr_val[1], BMP280_CTRL_MEAS_REG_POWER_MODE, mode_addr_val[2]);
  303.         printf("bmp280 mode_val[1]:%02X\r\n",mode_addr_val[1]);
  304.         /*reset*/
  305.         hi2c2_status = HAL_I2C_Mem_Write(&hi2c2,BMP280_I2C_ADDR,mode_addr_val[0],1,&mode_addr_val[1],1,1000);
  306.         if(HAL_OK!=hi2c2_status){
  307.                 printf("bmp280_set_power_mode error\r\n");
  308.                 return 1;
  309.         }
  310.         return 0;
  311. }
  312. uint8_t bmp280_set_odr(uint8_t odr)
  313. {
  314.         HAL_StatusTypeDef hi2c2_status = 0x00;
  315.         //BMP280_CONFIG_REG_STANDBY_DURN__REG=0XF5
  316.         uint8_t odr_addr_val[2] = {BMP280_CONFIG_REG_STANDBY_DURN__REG,0x00};
  317.         hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,BMP280_I2C_ADDR,odr_addr_val[0],1,&odr_addr_val[1],1,1000);
  318.         if(HAL_OK!=hi2c2_status){
  319.                 printf("get bmp280_odr error\r\n");
  320.                 return 1;
  321.         }
  322.         printf("bmp280 odr_val[1]:%02X\r\n",odr_addr_val[1]);
  323.         //BMP280_DEFAULT_ODR_1HZ = 0X01
  324.         odr_addr_val[1] = BMP280_SET_BITSLICE(odr_addr_val[1], BMP280_CONFIG_REG_STANDBY_DURN, odr);
  325.         printf("bmp280 odr_val[1]:%02X\r\n",odr_addr_val[1]);
  326.         /*reset*/
  327.         hi2c2_status = HAL_I2C_Mem_Write(&hi2c2,BMP280_I2C_ADDR,odr_addr_val[0],1,&odr_addr_val[1],1,1000);
  328.         if(HAL_OK!=hi2c2_status){
  329.                 printf("bmp280_set_odr error\r\n");
  330.                 return 1;
  331.         }
  332.         return 0;
  333. }

  334. static uint8_t bmp280_hz2odr(int hz)
  335. {
  336.     if (hz > 80) {
  337.         return BMP280_STANDBY_TIME_1_MS;
  338.     } else if (hz > 13) {
  339.         return BMP280_STANDBY_TIME_63_MS;
  340.     } else if (hz > 7) {
  341.         return BMP280_STANDBY_TIME_125_MS;
  342.     } else if (hz > 3) {
  343.         return BMP280_STANDBY_TIME_250_MS;
  344.     } else {
  345.         return BMP280_STANDBY_TIME_500_MS;
  346.     }
  347. }


  348. uint8_t bmp280_ioctl(cmd_type cmd,uint32_t arg)
  349. {
  350.         uint8_t ret = 0;
  351.     switch (cmd) {
  352.         case SENSOR_IOCTL_ODR_SET: {
  353.             uint8_t odr = bmp280_hz2odr(arg);
  354.             ret         = bmp280_set_odr( odr);
  355.             if (ret>0) {
  356.                 return 1;
  357.             }
  358.         } break;
  359.         case SENSOR_IOCTL_SET_POWER: {
  360.             ret = bmp280_set_power_mode(arg);
  361.             if (ret>0) {
  362.                 return 1;
  363.             }
  364.         } break;
  365.         case SENSOR_IOCTL_GET_INFO: {

  366.         } break;

  367.         default:
  368.             break;
  369.     }
  370.     return 0;
  371. }

  372. uint8_t bmp280_set_default_config()
  373. {
  374.         uint8_t ret = bmp280_set_power_mode(DEV_SLEEP);
  375.         if(ret>0)
  376.                 return 1;
  377.         ret = bmp280_set_odr(BMP280_DEFAULT_ODR_1HZ);
  378.         if(ret>0)
  379.                 return 1;
  380.         return 0;
  381. }

  382. uint8_t bmp280_get_calib_param()
  383. {
  384.         HAL_StatusTypeDef hi2c2_status = 0x00;
  385.         uint8_t data_u8[BMP280_CALIB_DATA_SIZE] = { 0x00 };
  386.         hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,BMP280_I2C_ADDR,BMP280_TEMPERATURE_CALIB_DIG_T1_LSB_REG
  387.                         ,1,data_u8,BMP280_PRESSURE_TEMPERATURE_CALIB_DATA_LENGTH,1000);
  388.         if(HAL_OK!=hi2c2_status){
  389.                 printf("get bmp280_calib_param error\r\n");
  390.                 return 1;
  391.         }
  392.         g_bmp280_calib_table.dig_T1 = (uint16_t)(
  393.                         (((uint16_t)((uint8_t)data_u8[BMP280_TEMPERATURE_CALIB_DIG_T1_MSB])) << BMP280_SHIFT_BY_08_BITS)
  394.                         | data_u8[BMP280_TEMPERATURE_CALIB_DIG_T1_LSB]);
  395.         g_bmp280_calib_table.dig_T2 = (int16_t)(
  396.               (((int16_t)((int8_t)data_u8[BMP280_TEMPERATURE_CALIB_DIG_T2_MSB])) << BMP280_SHIFT_BY_08_BITS)
  397.                    | data_u8[BMP280_TEMPERATURE_CALIB_DIG_T2_LSB]);
  398.         g_bmp280_calib_table.dig_T3 = (int16_t)(
  399.               (((int16_t)((int8_t)data_u8[BMP280_TEMPERATURE_CALIB_DIG_T3_MSB])) << BMP280_SHIFT_BY_08_BITS)
  400.                   | data_u8[BMP280_TEMPERATURE_CALIB_DIG_T3_LSB]);
  401.         g_bmp280_calib_table.dig_P1 = (uint16_t)(
  402.               (((uint16_t)((uint8_t)data_u8[BMP280_PRESSURE_CALIB_DIG_P1_MSB])) << BMP280_SHIFT_BY_08_BITS)
  403.                   | data_u8[BMP280_PRESSURE_CALIB_DIG_P1_LSB]);
  404.         g_bmp280_calib_table.dig_P2 = (int16_t)(
  405.               (((int16_t)((int8_t)data_u8[BMP280_PRESSURE_CALIB_DIG_P2_MSB])) << BMP280_SHIFT_BY_08_BITS)
  406.                   | data_u8[BMP280_PRESSURE_CALIB_DIG_P2_LSB]);
  407.         g_bmp280_calib_table.dig_P3 = (int16_t)(
  408.               (((int16_t)((int8_t)data_u8[BMP280_PRESSURE_CALIB_DIG_P3_MSB])) << BMP280_SHIFT_BY_08_BITS)
  409.                   | data_u8[BMP280_PRESSURE_CALIB_DIG_P3_LSB]);
  410.         g_bmp280_calib_table.dig_P4 = (int16_t)(
  411.               (((int16_t)((int8_t)data_u8[BMP280_PRESSURE_CALIB_DIG_P4_MSB])) << BMP280_SHIFT_BY_08_BITS)
  412.                   | data_u8[BMP280_PRESSURE_CALIB_DIG_P4_LSB]);
  413.         g_bmp280_calib_table.dig_P5 = (int16_t)(
  414.               (((int16_t)((int8_t)data_u8[BMP280_PRESSURE_CALIB_DIG_P5_MSB])) << BMP280_SHIFT_BY_08_BITS)
  415.                   | data_u8[BMP280_PRESSURE_CALIB_DIG_P5_LSB]);
  416.         g_bmp280_calib_table.dig_P6 = (int16_t)(
  417.               (((int16_t)((int8_t)data_u8[BMP280_PRESSURE_CALIB_DIG_P6_MSB])) << BMP280_SHIFT_BY_08_BITS)
  418.                   | data_u8[BMP280_PRESSURE_CALIB_DIG_P6_LSB]);
  419.         g_bmp280_calib_table.dig_P7 = (int16_t)(
  420.               (((int16_t)((int8_t)data_u8[BMP280_PRESSURE_CALIB_DIG_P7_MSB])) << BMP280_SHIFT_BY_08_BITS)
  421.                   | data_u8[BMP280_PRESSURE_CALIB_DIG_P7_LSB]);
  422.         g_bmp280_calib_table.dig_P8 = (int16_t)(
  423.               (((int16_t)((int8_t)data_u8[BMP280_PRESSURE_CALIB_DIG_P8_MSB])) << BMP280_SHIFT_BY_08_BITS)
  424.                   | data_u8[BMP280_PRESSURE_CALIB_DIG_P8_LSB]);
  425.         g_bmp280_calib_table.dig_P9 = (int16_t)(
  426.               (((int16_t)((int8_t)data_u8[BMP280_PRESSURE_CALIB_DIG_P9_MSB])) << BMP280_SHIFT_BY_08_BITS)
  427.                   | data_u8[BMP280_PRESSURE_CALIB_DIG_P9_LSB]);
  428.         return 0;
  429. }

  430. uint8_t bmp280_set_baro_work_mode(uint8_t mode)
  431. {
  432.     uint8_t value = 0;
  433.     uint8_t temp  = 0;
  434.     uint8_t baro  = 0;

  435.     switch (mode) {
  436.     case BMP280_ULTRA_LOW_POWER_MODE:
  437.         temp = BMP280_OVERSAMP_1X;
  438.         baro = BMP280_OVERSAMP_1X;
  439.         break;

  440.     case BMP280_LOW_POWER_MODE:
  441.         temp = BMP280_OVERSAMP_2X;
  442.         baro = BMP280_OVERSAMP_2X;
  443.         break;

  444.     case BMP280_STANDARD_RESOLUTION_MODE:
  445.         temp = BMP280_OVERSAMP_4X;
  446.         baro = BMP280_OVERSAMP_4X;
  447.         break;

  448.     case BMP280_HIGH_RESOLUTION_MODE:
  449.         temp = BMP280_OVERSAMP_8X;
  450.         baro = BMP280_OVERSAMP_8X;
  451.         break;

  452.     case BMP280_ULTRA_HIGH_RESOLUTION_MODE:
  453.         temp = BMP280_OVERSAMP_16X;
  454.         baro = BMP280_OVERSAMP_16X;
  455.         break;

  456.     default:
  457.         return 1;
  458.     }
  459.     HAL_StatusTypeDef hi2c2_status = 0x00;

  460.         hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,BMP280_I2C_ADDR,BMP280_CTRL_MEAS_REG
  461.                         ,1,&value,1,1000);
  462.         if(HAL_OK!=hi2c2_status){
  463.                 printf("get bmp280_calib_param error\r\n");
  464.                 return 1;
  465.         }
  466.         value =        BMP280_SET_BITSLICE(value, BMP280_CTRL_MEAS_REG_OVERSAMP_PRESSURE, baro);
  467.         value = BMP280_SET_BITSLICE(value, BMP280_CTRL_MEAS_REG_OVERSAMP_TEMPERATURE, temp);
  468.         hi2c2_status = HAL_I2C_Mem_Write(&hi2c2,BMP280_I2C_ADDR,BMP280_CTRL_MEAS_REG,1,&value,1,1000);
  469.         if(HAL_OK!=hi2c2_status){
  470.                 printf("bmp280_set_power_mode error\r\n");
  471.                 return 1;
  472.         }
  473.         printf("successfully BMP280 set  baro_work_mode \r\n");
  474.         return 0;
  475. }

  476. uint8_t bmp280_open(void)
  477. {
  478.         uint8_t ret = bmp280_set_baro_work_mode(BMP280_ULTRA_LOW_POWER_MODE);
  479.         if(ret>0)
  480.                 return 1;
  481.         ret = bmp280_set_power_mode(DEV_POWER_ON);
  482.         if(ret>0)
  483.                 return 1;
  484.         return 0;
  485. }

  486. uint8_t bmp280_close(void)
  487. {
  488.         uint8_t ret = bmp280_set_power_mode(DEV_POWER_OFF);
  489.         if(ret>0)
  490.                 return 1;
  491.         return 0;
  492. }

  493. void BMP280_init()
  494. {
  495.         if(bmp280_id_check()>0)
  496.                 return;
  497.         if(bmp280_reset()>0)
  498.                 return;
  499.         if(bmp280_set_default_config()>0)
  500.                 return;
  501.         if(bmp280_get_calib_param()>0)
  502.                 return;
  503.         printf("successfully BMP280 init\r\n");
  504. }

  505. uint8_t read_bmp280_temp(uint32_t *comp_temp)
  506. {
  507.         *comp_temp = 0;
  508.         uint8_t data_u8[BMP280_TEMPERATURE_DATA_SIZE] = { 0 };
  509.         int32_t temp;
  510.         HAL_StatusTypeDef hi2c2_status = 0x00;

  511.         hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,BMP280_I2C_ADDR,BMP280_TEMPERATURE_MSB_REG
  512.                         ,1,data_u8,BMP280_TEMPERATURE_DATA_SIZE,1000);
  513.         if(HAL_OK!=hi2c2_status){
  514.                 printf("get bmp280_calib_param error\r\n");
  515.                 return 1;
  516.         }
  517.         temp = (int)((((uint32_t)(data_u8[BMP280_TEMPERATURE_MSB_DATA]))
  518.                         << BMP280_SHIFT_BY_12_BITS) | (((uint32_t)(data_u8[BMP280_TEMPERATURE_LSB_DATA]))
  519.                         << BMP280_SHIFT_BY_04_BITS) | ((uint32_t)data_u8[BMP280_TEMPERATURE_XLSB_DATA]
  520.                         >> BMP280_SHIFT_BY_04_BITS));
  521.         //
  522.     int v_x1_u32r = 0;
  523.     int v_x2_u32r = 0;
  524.     v_x1_u32r = ((((temp >> BMP280_SHIFT_BY_03_BITS) -
  525.                     ((int)g_bmp280_calib_table.dig_T1 << BMP280_SHIFT_BY_01_BIT))) *
  526.                     ((int)g_bmp280_calib_table.dig_T2)) >> BMP280_SHIFT_BY_11_BITS;

  527.     v_x2_u32r = (((((temp >> BMP280_SHIFT_BY_04_BITS) -
  528.                     ((int)g_bmp280_calib_table.dig_T1)) *
  529.                    ((temp >> BMP280_SHIFT_BY_04_BITS) -
  530.                     ((int)g_bmp280_calib_table.dig_T1))) >>
  531.                   BMP280_SHIFT_BY_12_BITS) *
  532.                  ((int)g_bmp280_calib_table.dig_T3)) >>
  533.                 BMP280_SHIFT_BY_14_BITS;

  534.     g_bmp280_calib_table.t_fine = v_x1_u32r + v_x2_u32r;

  535.     temp = (g_bmp280_calib_table.t_fine * 5 + 128) >> BMP280_SHIFT_BY_08_BITS;
  536.     printf("comp_temp: %d.%d\n", (int)temp/100, (int)(temp % 100));
  537.     *comp_temp = temp;
  538.     return 0;
  539. }

  540. uint8_t read_bmp280_baro(uint32_t *comp_baro)
  541. {
  542.         *comp_baro = 0;
  543.         uint8_t data_u8[BMP280_PRESSURE_DATA_SIZE] = { 0 };
  544.         int32_t temp;
  545.         HAL_StatusTypeDef hi2c2_status = 0x00;
  546.         //BMP280_PRESSURE_MSB_REG=0XF7,BMP280_PRESSURE_DATA_SIZE=0X03
  547.         hi2c2_status = HAL_I2C_Mem_Read(&hi2c2,BMP280_I2C_ADDR,BMP280_PRESSURE_MSB_REG
  548.                                 ,1,data_u8,BMP280_PRESSURE_DATA_SIZE,1000);
  549.         if(HAL_OK!=hi2c2_status){
  550.                 printf("get bmp280_calib_param error\r\n");
  551.                 return 1;
  552.         }
  553.         temp = (int)(
  554.                         (((uint32_t)(data_u8[BMP280_PRESSURE_MSB_DATA])) << BMP280_SHIFT_BY_12_BITS)
  555.                         | (((uint32_t)(data_u8[BMP280_PRESSURE_LSB_DATA])) << BMP280_SHIFT_BY_04_BITS)
  556.                         | ((uint32_t)data_u8[BMP280_PRESSURE_XLSB_DATA]        >> BMP280_SHIFT_BY_04_BITS)
  557.                         );
  558.         //
  559.         int      v_x1_u32r = 0;
  560.         int      v_x2_u32r = 0;

  561.         v_x1_u32r = (((int)g_bmp280_calib_table.t_fine) >> BMP280_SHIFT_BY_01_BIT) - (int)64000;
  562.         v_x2_u32r = (((v_x1_u32r >> BMP280_SHIFT_BY_02_BITS) * (v_x1_u32r >> BMP280_SHIFT_BY_02_BITS)) >>
  563.                          BMP280_SHIFT_BY_11_BITS) * ((int)g_bmp280_calib_table.dig_P6);
  564.         v_x2_u32r = v_x2_u32r + ((v_x1_u32r * ((int)g_bmp280_calib_table.dig_P5)) << BMP280_SHIFT_BY_01_BIT);
  565.         v_x2_u32r = (v_x2_u32r >> BMP280_SHIFT_BY_02_BITS) + (((int)g_bmp280_calib_table.dig_P4) << BMP280_SHIFT_BY_16_BITS);
  566.         v_x1_u32r = (((g_bmp280_calib_table.dig_P3 *  (((v_x1_u32r >> BMP280_SHIFT_BY_02_BITS) *
  567.                         (v_x1_u32r >> BMP280_SHIFT_BY_02_BITS)) >> BMP280_SHIFT_BY_13_BITS)) >> BMP280_SHIFT_BY_03_BITS) +
  568.                 ((((int)g_bmp280_calib_table.dig_P2) * v_x1_u32r) >> BMP280_SHIFT_BY_01_BIT)) >> BMP280_SHIFT_BY_18_BITS;
  569.         v_x1_u32r = ((((32768 + v_x1_u32r)) * ((int)g_bmp280_calib_table.dig_P1)) >> BMP280_SHIFT_BY_15_BITS);
  570.         if (v_x1_u32r == 0)
  571.         {
  572.                 return 1; // avoid exception caused by division by zero
  573.         }
  574.         //
  575.         uint32_t val_baro = 0;
  576.         val_baro = (((uint32_t)(((int)1048576) - temp) - (v_x2_u32r >> BMP280_SHIFT_BY_12_BITS))) * 3125;

  577.         if (val_baro < 0x80000000) {
  578.                 if (v_x1_u32r != 0) {
  579.                         val_baro =        (val_baro << BMP280_SHIFT_BY_01_BIT) / ((uint32_t)v_x1_u32r);
  580.                 } else {
  581.                         return 1;
  582.                 }
  583.         } else if (v_x1_u32r != 0) {
  584.                 val_baro = (val_baro / (uint32_t)v_x1_u32r) * 2;
  585.         } else {
  586.                 return 1;
  587.         }
  588.         v_x1_u32r = (((int)g_bmp280_calib_table.dig_P9) * ((int)(((val_baro >> BMP280_SHIFT_BY_03_BITS) *
  589.                             (val_baro >> BMP280_SHIFT_BY_03_BITS)) >> BMP280_SHIFT_BY_13_BITS))) >> BMP280_SHIFT_BY_12_BITS;

  590.         v_x2_u32r = (((int)(val_baro >> BMP280_SHIFT_BY_02_BITS)) * ((int)g_bmp280_calib_table.dig_P8)) >>        BMP280_SHIFT_BY_13_BITS;

  591.         val_baro = (uint32_t)((int)val_baro +
  592.                             ((v_x1_u32r + v_x2_u32r + g_bmp280_calib_table.dig_P7) >> BMP280_SHIFT_BY_04_BITS));

  593.         printf("comp_baro:%d.%d\r\n",(int)val_baro/100, (int)(val_baro % 100));
  594.         *comp_baro = val_baro;
  595.         return 0;
  596. }
复制代码

八、LSM6DSL传感器(加速度及角速度)
在ICore源码目录下,创建LSM6DSL文件夹,再在该目录下创建LSM6DSL.h和LSM6DSL.c源文件。

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

b79d278928b94a6fb6776e439825294f.png


        但中间这段文字描述翻译如下: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。

eaf902deb827438d8fc4ac3cbc41e7c0.png


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

9004193c9ad342b5a46ebb96a818e0ba.png


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


f75814ebae5d49babb35f8d634ed803e.png

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

d27f24f1f76d44388f88564c0185cf65.png

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

fcd753afc14b4bbbad014f47882a8d90.png

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

590d66c447ff4f9f9754adcfdd85c1a0.png

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

409cb62768154012b9ec5c47f9a002a4.png

         6)按以上分析,给出LSM6DSl传感器的伪代码
  1. LSM6DSL从机地址是0XD6
  2. init:
  3. read id from 从机地址是0XD6 寄存器地址0X0F
  4. 确定id==0X6A
  5. write myconf|0X01 to 从机地址是0XD6 寄存器地址0X12 软重置设备
  6. write mymode to 从机地址是0XD6 寄存器地址0X10 设置设备ACC模式
  7. write mymode to 从机地址是0XD6 寄存器地址0X11 设置设备GYRO模式

  8. 读取数据
  9. acc 读取数据前确保设置了相关参数,如power mode,range,频宽等,在寄存器地址0X10 设置
  10. read acc1~6 from 从机地址是0XD6 寄存器地址0X28,0X29,0X2A,0X2B,0X2C,0X2D
  11. acc1~6进行换算处理得到acc数值

  12. acc 读取数据前确保设置了相关参数,如power mode,range,频宽等,寄存器地址0X11设置
  13. read gyro1~6 from 从机地址是0XD6 寄存器地址0X22,0X23,0X24,0X25,0X26,0X27
  14. gyro1~6进行换算处理得到gyro数值
复制代码

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

        LSM6DSL.h
  1. #ifndef _LSM6DSL_H_
  2. #define _LSM6DSL_H_

  3. #include "main.h"

  4. void LSM6DSL_init();
  5. uint8_t LSM6DSL_acc_st_open(void);
  6. uint8_t LSM6DSL_acc_st_close(void);

  7. uint8_t LSM6DSL_gyro_st_open(void);
  8. uint8_t LSM6DSL_gyro_st_close(void);

  9. uint8_t LSM6DSL_acc_read(int32_t *x_data,int32_t *y_data,int32_t *z_data);
  10. uint8_t LSM6DSL_gyro_read(int32_t *x_data,int32_t *y_data,int32_t *z_data);

  11. #endif /* LSM6DSL_LSM6DSL_H_ */
复制代码

         LSM6DSL.c
  1. #include <stdio.h>
  2. #include "LSM6DSL.h"

  3. extern I2C_HandleTypeDef hi2c4;

  4. #define LSM6DSL_I2C_ADDR1 (0x6A)
  5. #define LSM6DSL_I2C_ADDR2 (0x6B)
  6. #define LSM6DSL_I2C_ADDR_TRANS(n) ((n) << 1)
  7. #define LSM6DSL_I2C_ADDR LSM6DSL_I2C_ADDR_TRANS(LSM6DSL_I2C_ADDR2)

  8. #define LSM6DSL_ACC_GYRO_FUNC_CFG_ACCESS 0x01
  9. #define LSM6DSL_ACC_GYRO_SENSOR_SYNC_TIME 0x04
  10. #define LSM6DSL_ACC_GYRO_SENSOR_RES_RATIO 0x05
  11. #define LSM6DSL_ACC_GYRO_FIFO_CTRL1 0x06
  12. #define LSM6DSL_ACC_GYRO_FIFO_CTRL2 0x07
  13. #define LSM6DSL_ACC_GYRO_FIFO_CTRL3 0x08
  14. #define LSM6DSL_ACC_GYRO_FIFO_CTRL4 0x09
  15. #define LSM6DSL_ACC_GYRO_FIFO_CTRL5 0x0A
  16. #define LSM6DSL_ACC_GYRO_DRDY_PULSE_CFG_G 0x0B
  17. #define LSM6DSL_ACC_GYRO_INT1_CTRL 0x0D
  18. #define LSM6DSL_ACC_GYRO_INT2_CTRL 0x0E
  19. #define LSM6DSL_ACC_GYRO_WHO_AM_I_REG 0x0F
  20. #define LSM6DSL_ACC_GYRO_CTRL1_XL 0x10
  21. #define LSM6DSL_ACC_GYRO_CTRL2_G 0x11
  22. #define LSM6DSL_ACC_GYRO_CTRL3_C 0x12
  23. #define LSM6DSL_ACC_GYRO_CTRL4_C 0x13
  24. #define LSM6DSL_ACC_GYRO_CTRL5_C 0x14
  25. #define LSM6DSL_ACC_GYRO_CTRL6_C 0x15
  26. #define LSM6DSL_ACC_GYRO_CTRL7_G 0x16
  27. #define LSM6DSL_ACC_GYRO_CTRL8_XL 0x17
  28. #define LSM6DSL_ACC_GYRO_CTRL9_XL 0x18
  29. #define LSM6DSL_ACC_GYRO_CTRL10_C 0x19


  30. #define LSM6DSL_ACC_GYRO_MASTER_CONFIG 0x1A
  31. #define LSM6DSL_ACC_GYRO_WAKE_UP_SRC 0x1B
  32. #define LSM6DSL_ACC_GYRO_TAP_SRC 0x1C
  33. #define LSM6DSL_ACC_GYRO_D6D_SRC 0x1D
  34. #define LSM6DSL_ACC_GYRO_STATUS_REG 0x1E

  35. #define LSM6DSL_ACC_GYRO_OUT_TEMP_L 0x20
  36. #define LSM6DSL_ACC_GYRO_OUT_TEMP_H 0x21
  37. #define LSM6DSL_ACC_GYRO_OUTX_L_G 0x22
  38. #define LSM6DSL_ACC_GYRO_OUTX_H_G 0x23
  39. #define LSM6DSL_ACC_GYRO_OUTY_L_G 0x24
  40. #define LSM6DSL_ACC_GYRO_OUTY_H_G 0x25
  41. #define LSM6DSL_ACC_GYRO_OUTZ_L_G 0x26
  42. #define LSM6DSL_ACC_GYRO_OUTZ_H_G 0x27
  43. #define LSM6DSL_ACC_GYRO_OUTX_L_XL 0x28
  44. #define LSM6DSL_ACC_GYRO_OUTX_H_XL 0x29
  45. #define LSM6DSL_ACC_GYRO_OUTY_L_XL 0x2A
  46. #define LSM6DSL_ACC_GYRO_OUTY_H_XL 0x2B
  47. #define LSM6DSL_ACC_GYRO_OUTZ_L_XL 0x2C
  48. #define LSM6DSL_ACC_GYRO_OUTZ_H_XL 0x2D
  49. #define LSM6DSL_ACC_GYRO_SENSORHUB1_REG 0x2E
  50. #define LSM6DSL_ACC_GYRO_SENSORHUB2_REG 0x2F
  51. #define LSM6DSL_ACC_GYRO_SENSORHUB3_REG 0x30
  52. #define LSM6DSL_ACC_GYRO_SENSORHUB4_REG 0x31
  53. #define LSM6DSL_ACC_GYRO_SENSORHUB5_REG 0x32
  54. #define LSM6DSL_ACC_GYRO_SENSORHUB6_REG 0x33
  55. #define LSM6DSL_ACC_GYRO_SENSORHUB7_REG 0x34
  56. #define LSM6DSL_ACC_GYRO_SENSORHUB8_REG 0x35
  57. #define LSM6DSL_ACC_GYRO_SENSORHUB9_REG 0x36
  58. #define LSM6DSL_ACC_GYRO_SENSORHUB10_REG 0x37
  59. #define LSM6DSL_ACC_GYRO_SENSORHUB11_REG 0x38
  60. #define LSM6DSL_ACC_GYRO_SENSORHUB12_REG 0x39
  61. #define LSM6DSL_ACC_GYRO_FIFO_STATUS1 0x3A
  62. #define LSM6DSL_ACC_GYRO_FIFO_STATUS2 0x3B
  63. #define LSM6DSL_ACC_GYRO_FIFO_STATUS3 0x3C
  64. #define LSM6DSL_ACC_GYRO_FIFO_STATUS4 0x3D
  65. #define LSM6DSL_ACC_GYRO_FIFO_DATA_OUT_L 0x3E
  66. #define LSM6DSL_ACC_GYRO_FIFO_DATA_OUT_H 0x3F
  67. #define LSM6DSL_ACC_GYRO_TIMESTAMP0_REG 0x40
  68. #define LSM6DSL_ACC_GYRO_TIMESTAMP1_REG 0x41
  69. #define LSM6DSL_ACC_GYRO_TIMESTAMP2_REG 0x42

  70. #define LSM6DSL_ACC_GYRO_TIMESTAMP_L 0x49
  71. #define LSM6DSL_ACC_GYRO_TIMESTAMP_H 0x4A

  72. #define LSM6DSL_ACC_GYRO_STEP_COUNTER_L 0x4B
  73. #define LSM6DSL_ACC_GYRO_STEP_COUNTER_H 0x4C

  74. #define LSM6DSL_ACC_GYRO_SENSORHUB13_REG 0x4D
  75. #define LSM6DSL_ACC_GYRO_SENSORHUB14_REG 0x4E
  76. #define LSM6DSL_ACC_GYRO_SENSORHUB15_REG 0x4F
  77. #define LSM6DSL_ACC_GYRO_SENSORHUB16_REG 0x50
  78. #define LSM6DSL_ACC_GYRO_SENSORHUB17_REG 0x51
  79. #define LSM6DSL_ACC_GYRO_SENSORHUB18_REG 0x52

  80. #define LSM6DSL_ACC_GYRO_FUNC_SRC 0x53
  81. #define LSM6DSL_ACC_GYRO_TAP_CFG1 0x58
  82. #define LSM6DSL_ACC_GYRO_TAP_THS_6D 0x59
  83. #define LSM6DSL_ACC_GYRO_INT_DUR2 0x5A
  84. #define LSM6DSL_ACC_GYRO_WAKE_UP_THS 0x5B
  85. #define LSM6DSL_ACC_GYRO_WAKE_UP_DUR 0x5C
  86. #define LSM6DSL_ACC_GYRO_FREE_FALL 0x5D
  87. #define LSM6DSL_ACC_GYRO_MD1_CFG 0x5E
  88. #define LSM6DSL_ACC_GYRO_MD2_CFG 0x5F

  89. #define LSM6DSL_ACC_GYRO_OUT_MAG_RAW_X_L 0x66
  90. #define LSM6DSL_ACC_GYRO_OUT_MAG_RAW_X_H 0x67
  91. #define LSM6DSL_ACC_GYRO_OUT_MAG_RAW_Y_L 0x68
  92. #define LSM6DSL_ACC_GYRO_OUT_MAG_RAW_Y_H 0x69
  93. #define LSM6DSL_ACC_GYRO_OUT_MAG_RAW_Z_L 0x6A
  94. #define LSM6DSL_ACC_GYRO_OUT_MAG_RAW_Z_H 0x6B

  95. #define LSM6DSL_ACC_GYRO_X_OFS_USR 0x73
  96. #define LSM6DSL_ACC_GYRO_Y_OFS_USR 0x74
  97. #define LSM6DSL_ACC_GYRO_Z_OFS_USR 0x75

  98. #define LSM6DSL_CHIP_ID_VALUE (0x6A)

  99. #define LSM6DSL_RESET_VALUE (0x1)
  100. #define LSM6DSL_RESET_MSK (0X1)
  101. #define LSM6DSL_RESET_POS (0)

  102. #define LSM6DSL_ACC_ODR_POWER_DOWN (0X00)
  103. #define LSM6DSL_ACC_ODR_1_6_HZ (0X0B)
  104. #define LSM6DSL_ACC_ODR_12_5_HZ (0x01)
  105. #define LSM6DSL_ACC_ODR_26_HZ (0x02)
  106. #define LSM6DSL_ACC_ODR_52_HZ (0x03)
  107. #define LSM6DSL_ACC_ODR_104_HZ (0x04)
  108. #define LSM6DSL_ACC_ODR_208_HZ (0x05)
  109. #define LSM6DSL_ACC_ODR_416_HZ (0x06)
  110. #define LSM6DSL_ACC_ODR_833_HZ (0x07)
  111. #define LSM6DSL_ACC_ODR_1_66_KHZ (0x08)
  112. #define LSM6DSL_ACC_ODR_3_33_KHZ (0x09)
  113. #define LSM6DSL_ACC_ODR_6_66_KHZ (0x0A)
  114. #define LSM6DSL_ACC_ODR_MSK (0XF0)
  115. #define LSM6DSL_ACC_ODR_POS (4)

  116. #define LSM6DSL_GYRO_ODR_POWER_DOWN (0X00)
  117. #define LSM6DSL_GYRO_ODR_12_5_HZ (0x01)
  118. #define LSM6DSL_GYRO_ODR_26_HZ (0x02)
  119. #define LSM6DSL_GYRO_ODR_52_HZ (0x03)
  120. #define LSM6DSL_GYRO_ODR_104_HZ (0x04)
  121. #define LSM6DSL_GYRO_ODR_208_HZ (0x05)
  122. #define LSM6DSL_GYRO_ODR_416_HZ (0x06)
  123. #define LSM6DSL_GYRO_ODR_833_HZ (0x07)
  124. #define LSM6DSL_GYRO_ODR_1_66_KHZ (0x08)
  125. #define LSM6DSL_GYRO_ODR_3_33_KHZ (0x09)
  126. #define LSM6DSL_GYRO_ODR_6_66_KHZ (0x0A)
  127. #define LSM6DSL_GYRO_ODR_MSK (0XF0)
  128. #define LSM6DSL_GYRO_ODR_POS (4)

  129. #define LSM6DSL_ACC_RANGE_2G (0x0)
  130. #define LSM6DSL_ACC_RANGE_4G (0x2)
  131. #define LSM6DSL_ACC_RANGE_8G (0x3)
  132. #define LSM6DSL_ACC_RANGE_16G (0x1)
  133. #define LSM6DSL_ACC_RANGE_MSK (0X0C)
  134. #define LSM6DSL_ACC_RANGE_POS (2)

  135. #define LSM6DSL_ACC_SENSITIVITY_2G (61)
  136. #define LSM6DSL_ACC_SENSITIVITY_4G (122)
  137. #define LSM6DSL_ACC_SENSITIVITY_8G (244)
  138. #define LSM6DSL_ACC_SENSITIVITY_16G (488)

  139. #define LSM6DSL_GYRO_RANGE_245 (0x0)
  140. #define LSM6DSL_GYRO_RANGE_500 (0x1)
  141. #define LSM6DSL_GYRO_RANGE_1000 (0x2)
  142. #define LSM6DSL_GYRO_RANGE_2000 (0x3)
  143. #define LSM6DSL_GYRO_RANGE_MSK (0X0C)
  144. #define LSM6DSL_GYRO_RANGE_POS (2)

  145. #define LSM6DSL_GYRO_SENSITIVITY_245DPS (8750)
  146. #define LSM6DSL_GYRO_SENSITIVITY_500DPS (17500)
  147. #define LSM6DSL_GYRO_SENSITIVITY_1000DPS (35000)
  148. #define LSM6DSL_GYRO_SENSITIVITY_2000DPS (70000)

  149. #define LSM6DSL_SHIFT_EIGHT_BITS (8)
  150. #define LSM6DSL_16_BIT_SHIFT (0xFF)
  151. #define LSM6DSL_ACC_MUL (1000)
  152. #define LSM6DSL_GYRO_MUL (1)

  153. #define LSM6DSL_ACC_DEFAULT_ODR_100HZ (100)
  154. #define LSM6DSL_GYRO_DEFAULT_ODR_100HZ (100)

  155. #define LSM6DSL_GET_BITSLICE(regvar, bitname) \
  156.     ((regvar & bitname##_MSK) >> bitname##_POS)

  157. #define LSM6DSL_SET_BITSLICE(regvar, bitname, val) \
  158.     ((regvar & ~bitname##_MSK) | ((val << bitname##_POS) & bitname##_MSK))

  159. typedef enum {
  160.     ACC_RANGE_2G,
  161.     ACC_RANGE_4G,
  162.     ACC_RANGE_8G,
  163.     ACC_RANGE_16G,
  164.     ACC_RANGE_6G,
  165.     ACC_RANGE_12G,
  166.     ACC_RANGE_24G,
  167.     ACC_RANGE_100G,
  168.     ACC_RANGE_200G,
  169.     ACC_RANGE_400G,
  170.     ACC_RANGE_MAX
  171. } acc_range_e;

  172. typedef enum {
  173.     GYRO_RANGE_125DPS,
  174.     GYRO_RANGE_250DPS,
  175.     GYRO_RANGE_500DPS,
  176.     GYRO_RANGE_1000DPS,
  177.     GYRO_RANGE_2000DPS,
  178.     GYRO_RANGE_MAX
  179. } gyro_range_e;

  180. static int32_t lsm6dsl_acc_factor[ACC_RANGE_MAX] = {
  181.     LSM6DSL_ACC_SENSITIVITY_2G, LSM6DSL_ACC_SENSITIVITY_4G,
  182.     LSM6DSL_ACC_SENSITIVITY_8G, LSM6DSL_ACC_SENSITIVITY_16G
  183. };
  184. static int32_t lsm6dsl_gyro_factor[GYRO_RANGE_MAX] = {
  185.     0, LSM6DSL_GYRO_SENSITIVITY_245DPS, LSM6DSL_GYRO_SENSITIVITY_500DPS,
  186.     LSM6DSL_GYRO_SENSITIVITY_1000DPS, LSM6DSL_GYRO_SENSITIVITY_2000DPS
  187. };

  188. typedef enum {
  189.     DEV_POWER_OFF = 0,
  190.     DEV_POWER_ON,
  191.     DEV_SLEEP,
  192.     DEV_SUSPEND,
  193.     DEV_DEEP_SUSPEND,
  194. } LSM6DSL_power_mode;

  195. static int32_t cur_acc_factor  = 0;
  196. static int32_t cur_gyro_factor = 0;

  197. uint8_t LSM6DSL_ID_check()
  198. {
  199.         HAL_StatusTypeDef hi2c2_status = 0x00;
  200.         uint8_t addr_val[3] = {LSM6DSL_ACC_GYRO_WHO_AM_I_REG,0x00,LSM6DSL_CHIP_ID_VALUE};
  201.         hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,LSM6DSL_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);
  202.         if(HAL_OK!=hi2c2_status){
  203.                 printf("get LSM6DSL ID error\r\n");
  204.                 return 1;
  205.         }
  206.         if(addr_val[1]!=addr_val[2]){
  207.                 printf("LSM6DSL validate_id is error\r\n");
  208.                 return 1;
  209.         }
  210.         printf("LSM6DSL_id:%02X\r\n",addr_val[1]);
  211.         return 0;
  212. }

  213. uint8_t LSM6DSL_soft_reset()
  214. {
  215.         HAL_StatusTypeDef hi2c2_status = 0x00;
  216.         /*first read*/
  217.         uint8_t addr_val[2] = {LSM6DSL_ACC_GYRO_CTRL3_C,0x00};
  218.         hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,LSM6DSL_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);
  219.         if(HAL_OK!=hi2c2_status){
  220.                 printf("get LSM6DSL ACC_GYRO_CTRL3_C error\r\n");
  221.                 return 1;
  222.         }
  223.         printf("LSM6DSL ACC_GYRO_CTRL3_C old:%02X\r\n",addr_val[1]);
  224.         addr_val[1] |= LSM6DSL_RESET_VALUE;
  225.         printf("LSM6DSL ACC_GYRO_CTRL3_C new:%02X\r\n",addr_val[1]);
  226.         hi2c2_status = HAL_I2C_Mem_Write(&hi2c4,LSM6DSL_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);
  227.         if(HAL_OK!=hi2c2_status){
  228.                 printf("set LSM6DSL ACC_GYRO_CTRL3_C error\r\n");
  229.                 return 1;
  230.         }
  231.         printf("successfully LSM6DSL soft reset\r\n");
  232.         return 0;
  233. }
  234. /*
  235. * 以正数为例,最大可到32767,如果是Accelerometer数据,量程为2g的情况下,
  236. * 32768个刻度,一个刻度代表:2g/32768 = 2000mg/32767 = 0.061035mg
  237. * 例如:如果读出数据为16384,则加速度:16384x0.061035mg = 1000mg = 1g
  238. */
  239. uint8_t LSM6DSL_acc_set_range(uint32_t range)
  240. {
  241.         HAL_StatusTypeDef hi2c2_status = 0x00;
  242.         /*first read*/
  243.         uint8_t addr_val[2] = {LSM6DSL_ACC_GYRO_CTRL1_XL,0x00};
  244.         hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,LSM6DSL_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);
  245.         if(HAL_OK!=hi2c2_status){
  246.                 printf("get LSM6DSL acc range error\r\n");
  247.                 return 1;
  248.         }
  249.         uint8_t tmp   = 0;
  250.     switch (range) {
  251.             case ACC_RANGE_2G: {
  252.             tmp = LSM6DSL_ACC_RANGE_2G;
  253.         } break;

  254.         case ACC_RANGE_4G: {
  255.             tmp = LSM6DSL_ACC_RANGE_4G;
  256.         } break;

  257.         case ACC_RANGE_8G: {
  258.             tmp = LSM6DSL_ACC_RANGE_8G;
  259.         } break;

  260.         case ACC_RANGE_16G: {
  261.             tmp = LSM6DSL_ACC_RANGE_16G;
  262.         } break;

  263.         default:
  264.             break;
  265.     }
  266.     addr_val[1] = LSM6DSL_SET_BITSLICE(addr_val[1], LSM6DSL_ACC_RANGE, tmp);
  267.     hi2c2_status = HAL_I2C_Mem_Write(&hi2c4,LSM6DSL_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);
  268.         if(HAL_OK!=hi2c2_status){
  269.                 printf("set LSM6DSL acc range error\r\n");
  270.                 return 1;
  271.         }
  272.         if (range <= ACC_RANGE_16G) {
  273.         cur_acc_factor = lsm6dsl_acc_factor[range];
  274.     }
  275.         printf("successfully LSM6DSL set acc range\r\n");
  276.         return 0;
  277. }

  278. static uint8_t acc_st_lsm6dsl_hz2odr(uint32_t hz)
  279. {
  280.     if (hz > 3330)
  281.         return LSM6DSL_ACC_ODR_6_66_KHZ;
  282.     else if (hz > 1660)
  283.         return LSM6DSL_ACC_ODR_3_33_KHZ;
  284.     else if (hz > 833)
  285.         return LSM6DSL_ACC_ODR_1_66_KHZ;
  286.     else if (hz > 416)
  287.         return LSM6DSL_ACC_ODR_833_HZ;
  288.     else if (hz > 208)
  289.         return LSM6DSL_ACC_ODR_416_HZ;
  290.     else if (hz > 104)
  291.         return LSM6DSL_ACC_ODR_208_HZ;
  292.     else if (hz > 52)
  293.         return LSM6DSL_ACC_ODR_104_HZ;
  294.     else if (hz > 26)
  295.         return LSM6DSL_ACC_ODR_52_HZ;
  296.     else if (hz > 13)
  297.         return LSM6DSL_ACC_ODR_26_HZ;
  298.     else if (hz >= 2)
  299.         return LSM6DSL_ACC_ODR_12_5_HZ;
  300.     else
  301.         return LSM6DSL_ACC_ODR_1_6_HZ;
  302. }

  303. uint8_t LSM6DSL_acc_set_odr(uint32_t hz)
  304. {
  305.         HAL_StatusTypeDef hi2c2_status = 0x00;
  306.         /*first read*/
  307.         uint8_t addr_val[2] = {LSM6DSL_ACC_GYRO_CTRL1_XL,0x00};
  308.         hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,LSM6DSL_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);
  309.         if(HAL_OK!=hi2c2_status){
  310.                 printf("get LSM6DSL acc odr error\r\n");
  311.                 return 1;
  312.         }
  313.         uint8_t odr   = acc_st_lsm6dsl_hz2odr(hz);
  314.         addr_val[1] = LSM6DSL_SET_BITSLICE(addr_val[1], LSM6DSL_ACC_ODR, odr);
  315.         hi2c2_status = HAL_I2C_Mem_Write(&hi2c4,LSM6DSL_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);
  316.         if(HAL_OK!=hi2c2_status){
  317.                 printf("set LSM6DSL acc odr error\r\n");
  318.                 return 1;
  319.         }
  320.         printf("successfully LSM6DSL set acc odr\r\n");
  321.         return 0;
  322. }

  323. uint8_t LSM6DSL_acc_power_mode(LSM6DSL_power_mode mode)
  324. {
  325.         HAL_StatusTypeDef hi2c2_status = 0x00;
  326.         /*first read*/
  327.         uint8_t addr_val[2] = {LSM6DSL_ACC_GYRO_CTRL1_XL,0x00};
  328.         hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,LSM6DSL_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);
  329.         if(HAL_OK!=hi2c2_status){
  330.                 printf("get LSM6DSL acc power_mode error\r\n");
  331.                 return 1;
  332.         }
  333.         switch (mode) {
  334.                 case DEV_POWER_ON: {
  335.                         addr_val[1] = LSM6DSL_SET_BITSLICE(addr_val[1], LSM6DSL_ACC_ODR,LSM6DSL_ACC_ODR_12_5_HZ);
  336.                 }
  337.                 break;
  338.                 case DEV_POWER_OFF: {
  339.                         addr_val[1] = LSM6DSL_SET_BITSLICE(addr_val[1], LSM6DSL_ACC_ODR,LSM6DSL_ACC_ODR_POWER_DOWN);
  340.                 }
  341.                 break;
  342.                 case DEV_SLEEP: {
  343.                         addr_val[1] = LSM6DSL_SET_BITSLICE(addr_val[1], LSM6DSL_ACC_ODR,LSM6DSL_ACC_ODR_12_5_HZ);
  344.                 }
  345.                 break;
  346.                 default:
  347.                         break;
  348.         }
  349.         hi2c2_status = HAL_I2C_Mem_Write(&hi2c4,LSM6DSL_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);
  350.         if(HAL_OK!=hi2c2_status){
  351.                 printf("set LSM6DSL acc power_mode error\r\n");
  352.                 return 1;
  353.         }
  354.         printf("successfully LSM6DSL acc power_mode\r\n");
  355.         return 0;
  356. }

  357. uint8_t LSM6DSL_acc_st_open(void)
  358. {
  359.         uint8_t ret = 0;

  360.     ret = LSM6DSL_acc_power_mode( DEV_POWER_ON);
  361.     if (ret>0) {
  362.         return ret;
  363.     }

  364.     ret = LSM6DSL_acc_set_range(ACC_RANGE_8G);
  365.     if (ret>0) {
  366.         return ret;
  367.     }

  368.     ret = LSM6DSL_acc_set_odr(LSM6DSL_ACC_DEFAULT_ODR_100HZ);
  369.     if (ret>0) {
  370.         return ret;
  371.     }
  372.     printf("successfully LSM6DSL acc open\r\n");
  373.     return 0;
  374. }

  375. uint8_t LSM6DSL_acc_st_close(void)
  376. {
  377.         uint8_t ret = 0;
  378.     ret = LSM6DSL_acc_power_mode(DEV_POWER_OFF);
  379.     if (ret>0) {
  380.         return ret;
  381.     }
  382.     printf("successfully LSM6DSL acc close\r\n");
  383.     return 0;
  384. }

  385. uint8_t LSM6DSL_gyro_set_range(uint32_t range)
  386. {
  387.         HAL_StatusTypeDef hi2c2_status = 0x00;
  388.         /*first read*/
  389.         uint8_t addr_val[2] = {LSM6DSL_ACC_GYRO_CTRL2_G,0x00};
  390.         hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,LSM6DSL_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);
  391.         if(HAL_OK!=hi2c2_status){
  392.                 printf("get LSM6DSL gyro range error\r\n");
  393.                 return 1;
  394.         }
  395.         uint8_t tmp   = 0;
  396.         switch (range) {
  397.             case GYRO_RANGE_250DPS: {
  398.             tmp = LSM6DSL_GYRO_RANGE_245;
  399.         } break;

  400.         case GYRO_RANGE_500DPS: {
  401.             tmp = LSM6DSL_GYRO_RANGE_500;
  402.         } break;

  403.         case GYRO_RANGE_1000DPS: {
  404.             tmp = LSM6DSL_GYRO_RANGE_1000;
  405.         } break;

  406.         case GYRO_RANGE_2000DPS: {
  407.             tmp = LSM6DSL_GYRO_RANGE_2000;
  408.         } break;

  409.         default:
  410.             break;
  411.         }
  412.         addr_val[1] = LSM6DSL_SET_BITSLICE(addr_val[1], LSM6DSL_GYRO_RANGE, tmp);
  413.     hi2c2_status = HAL_I2C_Mem_Write(&hi2c4,LSM6DSL_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);
  414.         if(HAL_OK!=hi2c2_status){
  415.                 printf("set LSM6DSL gyro range error\r\n");
  416.                 return 1;
  417.         }
  418.         if ((range >= GYRO_RANGE_250DPS) && (range <= GYRO_RANGE_2000DPS)) {
  419.         cur_gyro_factor = lsm6dsl_gyro_factor[range];
  420.     }
  421.         printf("successfully LSM6DSL set gyro range\r\n");
  422.         return 0;
  423. }

  424. static uint8_t gyro_st_lsm6dsl_hz2odr(uint32_t hz)
  425. {
  426.     if (hz > 3330)
  427.         return LSM6DSL_GYRO_ODR_6_66_KHZ;
  428.     else if (hz > 1660)
  429.         return LSM6DSL_GYRO_ODR_3_33_KHZ;
  430.     else if (hz > 833)
  431.         return LSM6DSL_GYRO_ODR_1_66_KHZ;
  432.     else if (hz > 416)
  433.         return LSM6DSL_GYRO_ODR_833_HZ;
  434.     else if (hz > 208)
  435.         return LSM6DSL_GYRO_ODR_416_HZ;
  436.     else if (hz > 104)
  437.         return LSM6DSL_GYRO_ODR_208_HZ;
  438.     else if (hz > 52)
  439.         return LSM6DSL_GYRO_ODR_104_HZ;
  440.     else if (hz > 26)
  441.         return LSM6DSL_GYRO_ODR_52_HZ;
  442.     else if (hz > 13)
  443.         return LSM6DSL_GYRO_ODR_26_HZ;
  444.     else
  445.         return LSM6DSL_GYRO_ODR_12_5_HZ;
  446. }

  447. uint8_t LSM6DSL_gyro_set_odr(uint32_t hz)
  448. {
  449.         HAL_StatusTypeDef hi2c2_status = 0x00;
  450.         /*first read*/
  451.         uint8_t addr_val[2] = {LSM6DSL_ACC_GYRO_CTRL2_G,0x00};
  452.         hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,LSM6DSL_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);
  453.         if(HAL_OK!=hi2c2_status){
  454.                 printf("get LSM6DSL gyro odr error\r\n");
  455.                 return 1;
  456.         }
  457.         uint8_t odr = gyro_st_lsm6dsl_hz2odr(hz);
  458.         addr_val[1] = LSM6DSL_SET_BITSLICE(addr_val[1], LSM6DSL_GYRO_ODR, odr);
  459.         hi2c2_status = HAL_I2C_Mem_Write(&hi2c4,LSM6DSL_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);
  460.         if(HAL_OK!=hi2c2_status){
  461.                 printf("set LSM6DSL gyro odr error\r\n");
  462.                 return 1;
  463.         }
  464.         printf("successfully LSM6DSL set gyro odr\r\n");
  465.         return 0;
  466. }

  467. uint8_t LSM6DSL_gyro_power_mode(LSM6DSL_power_mode mode)
  468. {
  469.         HAL_StatusTypeDef hi2c2_status = 0x00;
  470.         /*first read*/
  471.         uint8_t addr_val[2] = {LSM6DSL_ACC_GYRO_CTRL2_G,0x00};
  472.         hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,LSM6DSL_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);
  473.         if(HAL_OK!=hi2c2_status){
  474.                 printf("get LSM6DSL gyro power_mode error\r\n");
  475.                 return 1;
  476.         }
  477.         switch (mode) {
  478.                 case DEV_POWER_ON: {
  479.                         addr_val[1] = LSM6DSL_SET_BITSLICE(addr_val[1], LSM6DSL_GYRO_ODR,LSM6DSL_GYRO_ODR_12_5_HZ);
  480.                         break;
  481.                 }
  482.                 case DEV_POWER_OFF: {
  483.                         addr_val[1] = LSM6DSL_SET_BITSLICE(addr_val[1], LSM6DSL_GYRO_ODR,LSM6DSL_GYRO_ODR_POWER_DOWN);
  484.                         break;
  485.                 }
  486.                 case DEV_SLEEP: {
  487.                         addr_val[1] = LSM6DSL_SET_BITSLICE(addr_val[1], LSM6DSL_GYRO_ODR,LSM6DSL_GYRO_ODR_12_5_HZ);
  488.                         break;
  489.                 }
  490.                 default:
  491.                         break;
  492.         }
  493.         hi2c2_status = HAL_I2C_Mem_Write(&hi2c4,LSM6DSL_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);
  494.         if(HAL_OK!=hi2c2_status){
  495.                 printf("set LSM6DSL gyro power_mode error\r\n");
  496.                 return 1;
  497.         }
  498.         printf("successfully LSM6DSL gyro power_mode\r\n");
  499.         return 0;
  500. }

  501. uint8_t LSM6DSL_gyro_st_open(void)
  502. {
  503.         uint8_t ret = 0;
  504.     ret        = LSM6DSL_gyro_power_mode(DEV_POWER_ON);
  505.     if (ret>0) {
  506.         return 1;
  507.     }

  508.     ret = LSM6DSL_gyro_set_range(GYRO_RANGE_1000DPS);
  509.     if (ret>0) {
  510.         return 1;
  511.     }

  512.     ret = LSM6DSL_gyro_set_odr(LSM6DSL_GYRO_DEFAULT_ODR_100HZ);
  513.     if (ret>0) {
  514.         return 1;
  515.     }
  516.     printf("successfully LSM6DSL gyro open\r\n");
  517.     return 0;
  518. }

  519. uint8_t LSM6DSL_gyro_st_close(void)
  520. {
  521.         uint8_t ret = 0;
  522.     ret        = LSM6DSL_gyro_power_mode(DEV_POWER_OFF);
  523.     if (ret>0) {
  524.         return 1;
  525.     }
  526.     printf("successfully LSM6DSL gyro close\r\n");
  527.     return 0;
  528. }

  529. void LSM6DSL_init()
  530. {
  531.         if(LSM6DSL_ID_check()>0)
  532.                 return;
  533.         if(LSM6DSL_soft_reset()>0)
  534.                 return;
  535.         if(LSM6DSL_acc_power_mode(DEV_POWER_OFF)>0)
  536.                 return;
  537.     if(LSM6DSL_gyro_power_mode(DEV_POWER_OFF)>0)
  538.                 return;
  539.         printf("successfully LSM6DSL init\r\n");
  540. }

  541. #define DATA_AXIS_X 0
  542. #define DATA_AXIS_Y 1
  543. #define DATA_AXIS_Z 2

  544. uint8_t LSM6DSL_acc_read(int32_t *x_data,int32_t *y_data,int32_t *z_data)
  545. {
  546.         HAL_StatusTypeDef hi2c2_status = 0x00;
  547.         /*read 0X28,0X29,0X2A,0X2B,0X2C,0X2D*/
  548.         uint8_t addr[6] = {LSM6DSL_ACC_GYRO_OUTX_L_XL,LSM6DSL_ACC_GYRO_OUTX_H_XL,
  549.                         LSM6DSL_ACC_GYRO_OUTY_L_XL,LSM6DSL_ACC_GYRO_OUTY_H_XL,
  550.                         LSM6DSL_ACC_GYRO_OUTZ_L_XL,LSM6DSL_ACC_GYRO_OUTZ_H_XL};
  551.         uint8_t val[6] = {0};
  552.         for(uint8_t i=0; i<6; i++){
  553.                 hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,LSM6DSL_I2C_ADDR,addr[i],1,&val[i],1,1000);
  554.                 if(HAL_OK!=hi2c2_status){
  555.                         printf("get LSM6DSL acc_read[0X%02X] error\r\n",addr[i]);
  556.                         return 1;
  557.                 }
  558.         }
  559.         printf("read acc reg_data 1:%02X, 2:%02X, 3:%02X, 4:%02X, 5:%02X ,6:%02X\r\n"
  560.                                     ,val[0],val[1],val[2],val[3],val[4],val[5]);
  561.         int32_t data[3] = {0};
  562.         data[DATA_AXIS_X] = (int16_t)((((int16_t)((int8_t)val[1])) << LSM6DSL_SHIFT_EIGHT_BITS) | (val[0]));
  563.         data[DATA_AXIS_Y] = (int16_t)((((int16_t)((int8_t)val[3])) << LSM6DSL_SHIFT_EIGHT_BITS) | (val[2]));
  564.         data[DATA_AXIS_Z] = (int16_t)((((int16_t)((int8_t)val[5])) << LSM6DSL_SHIFT_EIGHT_BITS) | (val[4]));
  565.     if (cur_acc_factor != 0)
  566.     {
  567.         data[DATA_AXIS_X] = (data[DATA_AXIS_X] * cur_acc_factor) / LSM6DSL_ACC_MUL;
  568.         data[DATA_AXIS_Y] = (data[DATA_AXIS_Y] * cur_acc_factor) / LSM6DSL_ACC_MUL;
  569.         data[DATA_AXIS_Z] = (data[DATA_AXIS_Z] * cur_acc_factor) / LSM6DSL_ACC_MUL;
  570.     }
  571.     printf("read acc cur_acc_factor:%ld, X:%ld,Y:%ld,Z:%ld\r\n"
  572.                     ,cur_acc_factor,data[0],data[1],data[2]);
  573.     *x_data = data[DATA_AXIS_X];
  574.     *y_data = data[DATA_AXIS_Y];
  575.     *z_data = data[DATA_AXIS_Z];
  576.         return 0;
  577. }

  578. uint8_t LSM6DSL_gyro_read(int32_t *x_data,int32_t *y_data,int32_t *z_data)
  579. {
  580.         HAL_StatusTypeDef hi2c2_status = 0x00;
  581.         /*read 0X22,0X23,0X24,0X25,0X26,0X27*/
  582.         uint8_t addr[6] = {LSM6DSL_ACC_GYRO_OUTX_L_G,LSM6DSL_ACC_GYRO_OUTX_H_G,
  583.                         LSM6DSL_ACC_GYRO_OUTY_L_G,LSM6DSL_ACC_GYRO_OUTY_H_G,
  584.                         LSM6DSL_ACC_GYRO_OUTZ_L_G,LSM6DSL_ACC_GYRO_OUTZ_H_G};
  585.         uint8_t val[6] = {0};
  586.         for(uint8_t i=0; i<6; i++){
  587.                 hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,LSM6DSL_I2C_ADDR,addr[i],1,&val[i],1,1000);
  588.                 if(HAL_OK!=hi2c2_status){
  589.                         printf("get LSM6DSL gyro_read[0X%02X] error\r\n",addr[i]);
  590.                         return 1;
  591.                 }
  592.         }
  593.         printf("read gyro reg_data 1:%02X, 2:%02X, 3:%02X, 4:%02X, 5:%02X ,6:%02X\r\n"
  594.                             ,val[0],val[1],val[2],val[3],val[4],val[5]);
  595.         int32_t data[3] = {0};
  596.         data[DATA_AXIS_X] = (int16_t)((((int32_t)((int8_t)val[1])) << LSM6DSL_SHIFT_EIGHT_BITS) | (val[0]));
  597.         data[DATA_AXIS_Y] = (int16_t)((((int32_t)((int8_t)val[3])) << LSM6DSL_SHIFT_EIGHT_BITS) | (val[2]));
  598.         data[DATA_AXIS_Z] = (int16_t)((((int32_t)((int8_t)val[5])) << LSM6DSL_SHIFT_EIGHT_BITS) | (val[4]));

  599.     if (cur_gyro_factor != 0) {
  600.         data[DATA_AXIS_X] = (data[DATA_AXIS_X] * cur_gyro_factor) / LSM6DSL_GYRO_MUL;
  601.         data[DATA_AXIS_Y] = (data[DATA_AXIS_Y] * cur_gyro_factor) / LSM6DSL_GYRO_MUL;
  602.         data[DATA_AXIS_Z] = (data[DATA_AXIS_Z] * cur_gyro_factor) / LSM6DSL_GYRO_MUL;
  603.     }
  604.     printf("read gyro cur_gyro_factor:%ld, X:%ld,Y:%ld,Z:%ld\r\n"
  605.                     ,cur_gyro_factor,data[0],data[1],data[2]);
  606.     *x_data = data[DATA_AXIS_X];
  607.     *y_data = data[DATA_AXIS_Y];
  608.     *z_data = data[DATA_AXIS_Z];
  609.         return 0;
  610. }
复制代码

九、MMC3680KJ传感器(三轴磁传感器)
        在ICore源目录下,创建MMC3680KJ文件夹,并在该目录下创建MMC3680KJ.h和MMC3680KJ.c源文件。

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

c5218cb2acb14de896da54db86b0ff52.png


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

981b4d85fc674003bf1e9521c17a4077.png

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

4ae3b022940047e0bc1650526aff5ba8.png

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

a37c720e239342ef8b1ef6e6d730d3de.png

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

f7a07b8796b2439ba434e513cb0bad3f.png

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

a21c9337abc94589bc015bb4d16b0954.png

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

c1da457cea3f40a8847b2084aa736264.png

f5d307e8392f49df873bc5f1f5f2cab2.png

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

2192a5344ddd44debb2b4727a4e73590.png

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

3fdf63f8b42346708a583f6ee3599ab4.png

         10)按以上分析,伪代码设计如下:
  1. MMC3680KJ从设备地址0x60
  2. init:
  3. read status from 从设备地址0x60 寄存器地址0X07
  4. read p_id from 从设备地址0x60 寄存器地址0X2F
  5. 确保p_id==0X0A
  6. 分别write myconf to 从设备地址0x60 寄存器地址0X08 0X09 0X0A ,完成频率、脉冲、启用等设置

  7. 读取数据
  8. 读取数据确保设备已经设置及启用,寄存器地址0X08,myconf|0X08|(0X01或 0X02)
  9. read data1~6 from 从设备地址0x60 寄存器地址0X00~0X05,共六字节数据
  10. 将data1~6 换算处理
  11. read temp from 从设备地址0x60 寄存器地址0X06,一个字节数据
  12. 将temp换算处理
复制代码

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

        MMC3680KJ.h
  1. #ifndef _MMC3680KJ_H_
  2. #define _MMC3680KJ_H_

  3. #include "main.h"

  4. void mmc3680kj_temp_memsic_init();
  5. void mmc3680kj_mag_memsic_init();

  6. uint8_t mmc3680kj_read_temp_memsic(int32_t *temperature);
  7. uint8_t mmc3680kj_read_mag_memsic(int32_t *xval, int32_t *yval, int32_t *zval);

  8. #endif /* MMC3680KJ_MMC3680KJ_H_ */
复制代码

        MMC3680KJ.c
  1. #include <stdio.h>
  2. #include "MMC3680KJ.h"

  3. extern I2C_HandleTypeDef hi2c4;

  4. #define MMC3680KJ_REG_DATA 0x00
  5. #define MMC3680KJ_REG_XL 0x00
  6. #define MMC3680KJ_REG_XH 0x01
  7. #define MMC3680KJ_REG_YL 0x02
  8. #define MMC3680KJ_REG_YH 0x03
  9. #define MMC3680KJ_REG_ZL 0x04
  10. #define MMC3680KJ_REG_ZH 0x05
  11. #define MMC3680KJ_REG_TEMP 0x06
  12. #define MMC3680KJ_REG_STATUS 0x07
  13. #define MMC3680KJ_REG_CTRL0 0x08
  14. #define MMC3680KJ_REG_CTRL1 0x09
  15. #define MMC3680KJ_REG_CTRL2 0x0a
  16. #define MMC3680KJ_REG_X_THD 0x0b
  17. #define MMC3680KJ_REG_Y_THD 0x0c
  18. #define MMC3680KJ_REG_Z_THD 0x0d
  19. #define MMC3680KJ_REG_SELFTEST 0x0e
  20. #define MMC3680KJ_REG_PASSWORD 0x0f
  21. #define MMC3680KJ_REG_OTPMODE 0x12
  22. #define MMC3680KJ_REG_TESTMODE 0x13
  23. #define MMC3680KJ_REG_SR_PWIDTH 0x20
  24. #define MMC3680KJ_REG_OTP 0x2a
  25. #define MMC3680KJ_REG_PRODUCTID 0x2f

  26. #define MMC3680KJ_CMD_REFILL 0x20
  27. #define MMC3680KJ_CMD_RESET 0x10
  28. #define MMC3680KJ_CMD_SET 0x08
  29. #define MMC3680KJ_CMD_TM_M 0x01
  30. #define MMC3680KJ_CMD_TM_T 0x02
  31. #define MMC3680KJ_CMD_START_MDT 0x04
  32. #define MMC3680KJ_CMD_100HZ 0x00
  33. #define MMC3680KJ_CMD_200HZ 0x01
  34. #define MMC3680KJ_CMD_400HZ 0x02
  35. #define MMC3680KJ_CMD_600HZ 0x03
  36. #define MMC3680KJ_CMD_CM_14HZ 0x01
  37. #define MMC3680KJ_CMD_CM_5HZ 0x02
  38. #define MMC3680KJ_CMD_CM_1HZ 0x04
  39. #define MMC3680KJ_CMD_SW_RST 0x80
  40. #define MMC3680KJ_CMD_PASSWORD 0xe1
  41. #define MMC3680KJ_CMD_OTP_OPER 0x11
  42. #define MMC3680KJ_CMD_OTP_MR 0x80
  43. #define MMC3680KJ_CMD_OTP_ACT 0x80
  44. #define MMC3680KJ_CMD_OTP_NACT 0x00
  45. #define MMC3680KJ_CMD_STSET_OPEN 0x02
  46. #define MMC3680KJ_CMD_STRST_OPEN 0x04
  47. #define MMC3680KJ_CMD_ST_CLOSE 0x00
  48. #define MMC3680KJ_CMD_INT_MD_EN 0x40
  49. #define MMC3680KJ_CMD_INT_MDT_EN 0x20

  50. #define MMC3680KJ_PRODUCT_ID 0x0a
  51. #define MMC3680KJ_OTP_READ_DONE_BIT 0x10
  52. #define MMC3680KJ_PUMP_ON_BIT 0x08
  53. #define MMC3680KJ_MDT_BIT 0x04
  54. #define MMC3680KJ_MEAS_T_DONE_BIT 0x02
  55. #define MMC3680KJ_MEAS_M_DONE_BIT 0x01

  56. #define MMC3680KJ_I2C_SLAVE_ADDR 0x30
  57. #define MMC3680KJ_ADDR_TRANS(n) ((n) << 1)
  58. #define MMC3680KJ_I2C_ADDR MMC3680KJ_ADDR_TRANS(MMC3680KJ_I2C_SLAVE_ADDR)

  59. #define MMC3680KJ_OFFSET 32768
  60. #define MMC3680KJ_SENSITIVITY 1024000
  61. #define MMC3680KJ_T_ZERO -75
  62. #define MMC3680KJ_T_SENSITIVITY 80

  63. #define MMC3680KJ_MAG_DATA_SIZE 6
  64. #define OTP_CONVERT(REG) (((REG) >= 32 ? (32 - (REG)) : (REG)) * 6)

  65. typedef enum
  66. {
  67.     FLAG_INIT_MAG = 0,
  68.     FLAG_INIT_TEMP,
  69. } FLAG_INIT_BIT;

  70. static int32_t g_otp_matrix[3] = { 1000000, 1000000, 1350000 };

  71. uint8_t mmc3680kj_check_otp()
  72. {
  73.         HAL_StatusTypeDef hi2c2_status = 0x00;
  74.         uint8_t addr_val[3] = {MMC3680KJ_REG_STATUS,0x00,MMC3680KJ_OTP_READ_DONE_BIT};
  75.         hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,MMC3680KJ_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);
  76.         if(HAL_OK!=hi2c2_status){
  77.                 printf("get mmc3680kj opt error\r\n");
  78.                 return 1;
  79.         }
  80.         if ((addr_val[1] & addr_val[2]) != addr_val[2]) {
  81.                 printf("mmc3680kj opt is error\r\n");
  82.         return 1;
  83.     }
  84.         printf("mmc3680kj opt:%02X\r\n",addr_val[1]);
  85.         return 0;
  86. }

  87. uint8_t mmc3680kj_id_check()
  88. {
  89.         HAL_StatusTypeDef hi2c2_status = 0x00;
  90.         uint8_t addr_val[3] = {MMC3680KJ_REG_PRODUCTID,0x00,MMC3680KJ_PRODUCT_ID};
  91.         hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,MMC3680KJ_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);
  92.         if(HAL_OK!=hi2c2_status){
  93.                 printf("get mmc3680kj ID error\r\n");
  94.                 return 1;
  95.         }
  96.         if(addr_val[1]!=addr_val[2]){
  97.                 printf("mmc3680kj validate_id is error\r\n");
  98.                 return 1;
  99.         }
  100.         printf("mmc3680kj_id:%02X\r\n",addr_val[1]);
  101.         return 0;
  102. }

  103. uint8_t mmc3680kj_set_comp_matrix()
  104. {
  105.         HAL_StatusTypeDef hi2c2_status = 0x00;
  106.         /*first*/
  107.         uint8_t addr_val[6][2] = {
  108.                         {MMC3680KJ_REG_PASSWORD,MMC3680KJ_CMD_PASSWORD},
  109.                         {MMC3680KJ_REG_OTPMODE,MMC3680KJ_CMD_OTP_OPER},
  110.                         {MMC3680KJ_REG_TESTMODE,MMC3680KJ_CMD_OTP_MR},
  111.                         {MMC3680KJ_REG_CTRL2,MMC3680KJ_CMD_OTP_ACT},
  112.                         {MMC3680KJ_REG_OTP,0X00},
  113.                         {MMC3680KJ_REG_CTRL2,MMC3680KJ_CMD_OTP_NACT}
  114.         };
  115.         for(uint8_t i=0; i<4; i++)
  116.         {
  117.                 hi2c2_status = HAL_I2C_Mem_Write(&hi2c4,MMC3680KJ_I2C_ADDR,addr_val[i][0],1,&addr_val[i][1],1,1000);
  118.                 if(HAL_OK!=hi2c2_status){
  119.                         printf("mmc3680kj comp_matrix addr(0X%02X) error\r\n",addr_val[i][0]);
  120.                         return 1;
  121.                 }
  122.         }
  123.         uint8_t reg_data[2] = { 0 };
  124.         hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,MMC3680KJ_I2C_ADDR,addr_val[4][0],1,reg_data,2,1000);
  125.         if(HAL_OK!=hi2c2_status){
  126.                 printf("mmc3680kj comp_matrix addr(0X%02X) error\r\n",addr_val[4][0]);
  127.                 return 1;
  128.         }
  129.         hi2c2_status = HAL_I2C_Mem_Write(&hi2c4,MMC3680KJ_I2C_ADDR,addr_val[5][0],1,&addr_val[5][1],1,1000);
  130.         if(HAL_OK!=hi2c2_status){
  131.                 printf("mmc3680kj comp_matrix addr(0X%02X) error\r\n",addr_val[5][0]);
  132.                 return 1;
  133.         }
  134.         g_otp_matrix[0] = 1000000;
  135.         g_otp_matrix[1] = OTP_CONVERT(reg_data[0] & 0x3f) * 1000 + 1000000;
  136.         g_otp_matrix[2] = (OTP_CONVERT((reg_data[1] & 0x0f) << 2 | (reg_data[0] & 0xc0) >> 6) +        1000) * 1350;
  137.         return 0;
  138. }

  139. uint8_t mmc3680kj_set_pulse_width()
  140. {
  141.         HAL_StatusTypeDef hi2c2_status = 0x00;
  142.         /*first*/
  143.         uint8_t addr_val[3][2] = {
  144.                         {MMC3680KJ_REG_CTRL2,MMC3680KJ_CMD_OTP_NACT},
  145.                         {MMC3680KJ_REG_PASSWORD,MMC3680KJ_CMD_PASSWORD},
  146.                         {MMC3680KJ_REG_SR_PWIDTH,0X00}
  147.                 };
  148.         for(uint8_t i=0; i<2; i++)
  149.         {
  150.                 hi2c2_status = HAL_I2C_Mem_Write(&hi2c4,MMC3680KJ_I2C_ADDR,addr_val[i][0],1,&addr_val[i][1],1,1000);
  151.                 if(HAL_OK!=hi2c2_status){
  152.                         printf("mmc3680kj set pulse_width addr(0X%02X) error\r\n",addr_val[i][0]);
  153.                         return 1;
  154.                 }
  155.         }
  156.         hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,MMC3680KJ_I2C_ADDR,addr_val[2][0],1,&addr_val[2][1],1,1000);
  157.         if(HAL_OK!=hi2c2_status){
  158.                 printf("mmc3680kj set pulse_width addr(0X%02X) error\r\n",addr_val[2][0]);
  159.                 return 1;
  160.         }
  161.         addr_val[2][1] &= 0xe7;
  162.         hi2c2_status = HAL_I2C_Mem_Write(&hi2c4,MMC3680KJ_I2C_ADDR,addr_val[2][0],1,&addr_val[2][1],1,1000);
  163.         if(HAL_OK!=hi2c2_status){
  164.                 printf("mmc3680kj set pulse_width addr(0X%02X) error\r\n",addr_val[2][0]);
  165.                 return 1;
  166.         }
  167.         printf("successfully mmc3680kj set pulse_width\r\n");
  168.         return 0;
  169. }

  170. uint8_t mmc3680kj_set_output_resolution()
  171. {
  172.         //MMC3680KJ_CMD_100HZ
  173.         HAL_StatusTypeDef hi2c2_status = 0x00;
  174.         uint8_t addr_val[2] = {MMC3680KJ_REG_CTRL1,MMC3680KJ_CMD_100HZ};
  175.         hi2c2_status = HAL_I2C_Mem_Write(&hi2c4,MMC3680KJ_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);
  176.         if(HAL_OK!=hi2c2_status){
  177.                 printf("mmc3680kj set output_resolution addr(0X%02X) error\r\n",addr_val[0]);
  178.                 return 1;
  179.         }
  180.         printf("successfully mmc3680kj set pulse_width\r\n");
  181.         return 0;
  182. }

  183. uint8_t mmc3680kj_set()
  184. {
  185.         HAL_StatusTypeDef hi2c2_status = 0x00;
  186.         uint8_t addr_val[2] = {MMC3680KJ_REG_CTRL0,MMC3680KJ_CMD_SET};
  187.         hi2c2_status = HAL_I2C_Mem_Write(&hi2c4,MMC3680KJ_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);
  188.         if(HAL_OK!=hi2c2_status){
  189.                 printf("mmc3680kj set addr(0X%02X) error\r\n",addr_val[0]);
  190.                 return 1;
  191.         }
  192.         printf("successfully mmc3680kj set\r\n");
  193.         return 0;
  194. }

  195. uint8_t mmc3680kj_enable(FLAG_INIT_BIT flag)
  196. {
  197.         HAL_StatusTypeDef hi2c2_status = 0x00;
  198.         if (flag == FLAG_INIT_MAG) {
  199.                 uint8_t addr_val[2] = {MMC3680KJ_REG_CTRL0,MMC3680KJ_CMD_TM_M};
  200.                 hi2c2_status = HAL_I2C_Mem_Write(&hi2c4,MMC3680KJ_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);
  201.                 if(HAL_OK!=hi2c2_status){
  202.                         printf("mmc3680kj enable addr(0X%02X) error\r\n",addr_val[0]);
  203.                         return 1;
  204.                 }
  205.                 uint8_t value = 0;
  206.                 do{
  207.                         HAL_Delay(10);
  208.                         hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,MMC3680KJ_I2C_ADDR,MMC3680KJ_REG_STATUS,1,&value,1,1000);
  209.                         if(HAL_OK!=hi2c2_status){
  210.                                 printf("mmc3680kj enable addr(0X%02X) error\r\n",MMC3680KJ_REG_STATUS);
  211.                                 return 1;
  212.                         }
  213.                 }while ((value & 0x01) != 0x01);
  214.         }else if(flag==FLAG_INIT_TEMP){
  215.                 uint8_t addr_val[2] = {MMC3680KJ_REG_CTRL0,MMC3680KJ_CMD_TM_T};
  216.                 hi2c2_status = HAL_I2C_Mem_Write(&hi2c4,MMC3680KJ_I2C_ADDR,addr_val[0],1,&addr_val[1],1,1000);
  217.                 if(HAL_OK!=hi2c2_status){
  218.                         printf("mmc3680kj enable addr(0X%02X) error\r\n",addr_val[0]);
  219.                         return 1;
  220.                 }
  221.                 uint8_t value = 0;
  222.                 do{
  223.                         HAL_Delay(10);
  224.                         hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,MMC3680KJ_I2C_ADDR,MMC3680KJ_REG_STATUS,1,&value,1,1000);
  225.                         if(HAL_OK!=hi2c2_status){
  226.                                 printf("mmc3680kj enable addr(0X%02X) error\r\n",MMC3680KJ_REG_STATUS);
  227.                                 return 1;
  228.                         }
  229.                 }while ((value & 0x02) != 0x02);
  230.         }else{
  231.                 return 1;
  232.         }
  233.         printf("successfully mmc3680kj enable\r\n");
  234.         return 0;
  235. }

  236. static int mmc3680kj_tick()
  237. {
  238.     static uint32_t last_time = 0;
  239.     uint32_t        now_time  = 0;

  240.     now_time = HAL_GetTick();
  241.     if (now_time - last_time > 5000) {
  242.         last_time = now_time;
  243.         return 1;
  244.     }

  245.     return 0;
  246. }

  247. uint8_t mmc3680kj_read_temp_memsic(int32_t *temperature)
  248. {
  249.         uint8_t ret = mmc3680kj_enable(FLAG_INIT_TEMP);
  250.         if (ret>0) {
  251.         return ret;
  252.     }
  253.         uint8_t reg_raw = 0;
  254.         HAL_StatusTypeDef hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,MMC3680KJ_I2C_ADDR
  255.                                 ,MMC3680KJ_REG_TEMP,1,®_raw,1,1000);
  256.         if(HAL_OK!=hi2c2_status){
  257.                 printf("mmc3680kj read_mag_memsic addr(0X%02X) error\r\n",MMC3680KJ_REG_STATUS);
  258.                 return 1;
  259.         }
  260.         printf("mmc3680kj_read_temp org:%02X\r\n",reg_raw);
  261.         *temperature = ((int32_t)reg_raw) * MMC3680KJ_T_SENSITIVITY / 100 + MMC3680KJ_T_ZERO;
  262.         printf("mmc3680kj_read_temp:%ld\r\n",*temperature);
  263.         return 0;
  264. }

  265. uint8_t mmc3680kj_read_mag_memsic(int32_t *xval, int32_t *yval, int32_t *zval)
  266. {
  267.         uint8_t ret = 0;
  268.         if (mmc3680kj_tick()) {
  269.         ret = mmc3680kj_set();
  270.         if (ret>0) {
  271.             return ret;
  272.         }
  273.     }
  274.         ret = mmc3680kj_enable(FLAG_INIT_MAG);
  275.         if (ret>0) {
  276.         return ret;
  277.     }
  278.         uint8_t reg_raw[MMC3680KJ_MAG_DATA_SIZE] = { 0 };
  279.         HAL_StatusTypeDef hi2c2_status = HAL_I2C_Mem_Read(&hi2c4,MMC3680KJ_I2C_ADDR
  280.                         ,MMC3680KJ_REG_DATA,1,reg_raw,MMC3680KJ_MAG_DATA_SIZE,1000);
  281.         if(HAL_OK!=hi2c2_status){
  282.                 printf("mmc3680kj read_mag_memsic addr(0X%02X) error\r\n",MMC3680KJ_REG_STATUS);
  283.                 return 1;
  284.         }
  285.     uint16_t    data_raw[3] = { 0 };
  286.     uint32_t    mag_raw[3]  = { 0 };
  287.     data_raw[0] = (uint16_t)(reg_raw[1] << 8 | reg_raw[0]);
  288.     data_raw[1] = (uint16_t)(reg_raw[3] << 8 | reg_raw[2]);
  289.     data_raw[2] = (uint16_t)(reg_raw[5] << 8 | reg_raw[4]);
  290.     mag_raw[0]  = (uint32_t)(data_raw[0]);
  291.     mag_raw[1]  = (uint32_t)(data_raw[1] - data_raw[2] + MMC3680KJ_OFFSET);
  292.     mag_raw[2]  = (uint32_t)(data_raw[1] + data_raw[2] - MMC3680KJ_OFFSET);

  293.     *xval = (int32_t)(mag_raw[0] - MMC3680KJ_OFFSET) * g_otp_matrix[0] / MMC3680KJ_SENSITIVITY;
  294.     *yval = (int32_t)(mag_raw[1] - MMC3680KJ_OFFSET) * g_otp_matrix[1] / MMC3680KJ_SENSITIVITY;
  295.     *zval = (int32_t)(mag_raw[2] - MMC3680KJ_OFFSET) * g_otp_matrix[2] / MMC3680KJ_SENSITIVITY;
  296.     printf("mmc3680kj_read_mag:%ld,%ld,%ld\r\n",*xval,*yval,*zval);
  297.         return 0;
  298. }

  299. void mmc3680kj_temp_memsic_init()
  300. {
  301.         if(mmc3680kj_check_otp()>0)
  302.                 return ;
  303.         if(mmc3680kj_id_check()>0)
  304.                 return ;
  305.         printf("successfully mmc3680kj temp_memsic_init\r\n");
  306. }

  307. void mmc3680kj_mag_memsic_init()
  308. {
  309.         if(mmc3680kj_check_otp()>0)
  310.                 return ;
  311.         if(mmc3680kj_id_check()>0)
  312.                 return ;
  313.         if(mmc3680kj_set_comp_matrix()>0)
  314.                 return ;
  315.         if(mmc3680kj_set_pulse_width()>0)
  316.                 return ;
  317.         if(mmc3680kj_set_output_resolution()>0)
  318.                 return ;
  319.         printf("successfully mmc3680kj mag_memsic_init\r\n");
  320. }
复制代码

十、驱动代码调用及数据采集与展示
        在main.c函数中,调用各个传感器驱动的头文件及调试、oled显示的头文件
  1. /* USER CODE BEGIN Includes */
  2. #include "../../ICore/key/key.h"
  3. #include "../../ICore/led/led.h"
  4. #include "../../ICore/print/print.h"
  5. #include "../../ICore/usart/usart.h"
  6. #include "../../ICore/oled/oled.h"
  7. #include "../../ICore/SHTC1/SHTC1.h"
  8. #include "../../ICore/LTR-553ALS-WA/LTR-553ALS-WA.h"
  9. #include "../../ICore/bmp280/bmp280.h"
  10. #include "../../ICore/LSM6DSL/LSM6DSL.h"
  11. #include "../../ICore/MMC3680KJ/MMC3680KJ.h"
  12. /* USER CODE END Includes */
复制代码

        在主函数中,逐个初始化各个传感器及相关接口,并将OLED设置为蓝色背景显示。
  1. /* USER CODE BEGIN 1 */
  2.     float humidity, temperature;
  3.     uint32_t als_data,ps_data;
  4.     uint32_t comp_temp,comp_baro;
  5.     int32_t acc_x,acc_y,acc_z;
  6.     int32_t gyro_x,gyro_y,gyro_z;
  7.     int32_t mmc_temp,mmc_aval,mmc_bval,mmc_cval;
  8.   /* USER CODE END 1 */
  9. ...........................................
  10.   /* USER CODE BEGIN 2 */
  11.   ResetPrintInit(&hlpuart1);
  12.   HAL_UART_Receive_IT(&hlpuart1,(uint8_t *)&HLPUSART_NewData, 1); //再开启接收中断
  13.   HLPUSART_RX_STA = 0;
  14.   //oled
  15.   OLED_init();
  16.   //shtc1
  17.   humidity = temperature = 0.0;
  18.   als_data = ps_data = 0;
  19.   shtc1_init();
  20.   //ltr553
  21.   LTR_ALS_init();
  22.   ltr553_als_open();
  23.   LTR_PS_init();
  24.   ltr553_ps_open();
  25.   //bmp280
  26.   BMP280_init();
  27.   bmp280_open();
  28.   comp_temp = comp_baro = 0;
  29.   //mmc3680
  30.   mmc3680kj_temp_memsic_init();
  31.   mmc3680kj_mag_memsic_init();
  32.   //
  33.   LSM6DSL_init();
  34.   LSM6DSL_acc_st_open();
  35.   LSM6DSL_gyro_st_open();
  36.   acc_x = acc_y = acc_z = 0;
  37.   gyro_x = gyro_y = gyro_z = 0;
  38.   mmc_temp = mmc_aval = mmc_bval = mmc_cval =0;
  39.   uint8_t menu = 0;
  40.   //设置OLED蓝色背景显示
  41.   BSP_LCD_Clear_DMA(LCD_DISP_BLUE);
  42.   printf("OLED_Clear_DMA\r\n");
  43.   /* USER CODE END 2 */
复制代码

        在主函数循环中,加入对各个传感器数据读取以及显示输出,设置了一个菜单标识menu,按键可以改变它:按键KEY0清屏,按键KEY1实现I2C2接口读取(stch1、ltr553、bmp280)数据及显示;按键KEY2实现I2C4接口读取(LSM6DSL、MMC3680KJ)数据及显示。
  1. /* USER CODE BEGIN WHILE */
  2.   while (1)
  3.   {
  4.           if(HLPUSART_RX_STA&0xC000){//溢出或换行,重新开始
  5.                     //printf("%.*s\r\n",HLPUSART_RX_STA&0X0FFF, HLPUSART_RX_BUF);
  6.                     OLED_printf(10,10,"%.*s",HLPUSART_RX_STA&0X0FFF, HLPUSART_RX_BUF);
  7.                     HLPUSART_RX_STA=0;//接收错误,重新开始
  8.                     HAL_Delay(100);//等待
  9.             }
  10.           if(KEY_0())
  11.           {
  12.                   BSP_LCD_Clear_DMA(LCD_DISP_BLUE);
  13.                   printf("OLED_Clear_DMA\r\n");
  14.           }
  15.           if(KEY_1())
  16.           {
  17.                   if(menu&0x02)
  18.                           BSP_LCD_Clear_DMA(LCD_DISP_BLUE);
  19.                   if(menu&0x01)
  20.                           menu &= 0XFE;        //取消I2C2数据刷新
  21.                   else
  22.                           menu |= 0X01; //开启I2C2数据刷新
  23.                   menu &= 0XFD; //取消I2C4数据刷新

  24.           }
  25.           if(KEY_2())
  26.           {
  27.                   if(menu&0x01)
  28.                           BSP_LCD_Clear_DMA(LCD_DISP_BLUE);

  29.                   if(menu&0x02)
  30.                           menu &= 0XFD; //取消I2C4数据刷新
  31.                   else
  32.                           menu |= 0X02; //开启I2C4数据刷新
  33.                   menu &= 0XFE;        //取消I2C2数据刷新

  34.           }
  35.           if(menu&0x01)
  36.             {
  37.                   /* 读取温湿度数据 */
  38.                     read_ht(&humidity,&temperature);
  39.                     //oled
  40.                     OLED_printf(10,10,"humidity   : %d.%d",(int)humidity, (int)(humidity * 100) % 100);
  41.                     if( temperature >= 0 )
  42.                             OLED_printf(10,26,"temperature: %d.%d",(int)temperature, (int)(temperature * 100) % 100);
  43.                     else
  44.                             OLED_printf(10,26,"temperature: %d.%d",(int)temperature, (int)(-temperature * 100) % 100);
  45.                   read_als(&als_data);
  46.                   read_ps(&ps_data);
  47.                   //
  48.                   OLED_printf(10,42,"light_data : %d.%d",(int)als_data, (int)(als_data * 100) % 100);
  49.                   OLED_printf(10,58,"proximity  : %d.%d",(int)ps_data, (int)(ps_data * 100) % 100);
  50.                   //
  51.                   read_bmp280_temp(&comp_temp);
  52.                   read_bmp280_baro(&comp_baro);
  53.                   OLED_printf(10,74,"comp_DegC  : %d.%d",(int)comp_temp/100,(int)comp_temp%100);
  54.                   OLED_printf(10,90,"comp_baro  : %d.%d",(int)comp_baro/100,(int)comp_baro%100);
  55.             }
  56.             if(menu&0x02)
  57.             {
  58.                   LSM6DSL_acc_read(&acc_x,&acc_y,&acc_z);
  59.                   LSM6DSL_gyro_read(&gyro_x,&gyro_y,&gyro_z);
  60.                   if(acc_x>0)
  61.                           OLED_printf(10,10,"st_acc_x   : %d.%d    ",(acc_x*98)/10000,((acc_x*98)%10000)/100);
  62.                   else
  63.                           OLED_printf(10,10,"st_acc_x   : %d.%d    ",(acc_x*98)/10000,((-acc_x*98)%10000)/100);
  64.                   if(acc_y>0)
  65.                           OLED_printf(10,26,"st_acc_y   : %d.%d    ",(acc_y*98)/10000,((acc_y*98)%10000)/100);
  66.                   else
  67.                           OLED_printf(10,26,"st_acc_y   : %d.%d    ",(acc_y*98)/10000,((-acc_y*98)%10000)/100);
  68.                   if(acc_z>0)
  69.                           OLED_printf(10,42,"st_acc_z   : %d.%d    ",(acc_z*98)/10000,((acc_z*98)%10000)/100);
  70.                   else
  71.                           OLED_printf(10,42,"st_acc_z   : %d.%d    ",(acc_z*98)/10000,((-acc_z*98)%10000)/100);
  72.                   if(gyro_x>0)
  73.                           OLED_printf(10,58,"st_gyro_x  : %d.%d    ",(gyro_x)/1000,((gyro_x)%1000)/10);
  74.                   else
  75.                           OLED_printf(10,58,"st_gyro_x  : %d.%d    ",(gyro_x)/1000,((-gyro_x)%1000)/10);
  76.                   if(gyro_y>0)
  77.                           OLED_printf(10,74,"st_gyro_y  : %d.%d    ",(gyro_y)/1000,((gyro_y)%1000)/10);
  78.                   else
  79.                           OLED_printf(10,74,"st_gyro_y  : %d.%d    ",(gyro_y)/1000,((-gyro_y)%1000)/10);
  80.                   if(gyro_z>0)
  81.                           OLED_printf(10,90,"st_gyro_z  : %d.%d    ",(gyro_z)/1000,((gyro_z)%1000)/10);
  82.                   else
  83.                           OLED_printf(10,90,"st_gyro_z  : %d.%d    ",(gyro_z)/1000,((-gyro_z)%1000)/10);
  84.                   mmc3680kj_read_temp_memsic(&mmc_temp);
  85.                   mmc3680kj_read_mag_memsic(&mmc_aval,&mmc_bval,&mmc_cval);
  86.                 OLED_printf(10,106,"mmc_temp   : %d.%d    ",mmc_temp,0);
  87.                 OLED_printf(10,122,"mmc_aval   : %d.%d    ",mmc_aval,0);
  88.                 OLED_printf(10,138,"mmc_bval   : %d.%d    ",mmc_bval,0);
  89.                 OLED_printf(10,154,"mmc_cval   : %d.%d    ",mmc_cval,0);
  90.             }
  91.           Toggle_led0();
  92.     /* USER CODE END WHILE */
复制代码

        程序编译及下载

0f4c578f6c2647218275dd9c302815e6.png

         初始化打印输出

abbebceecc09415e8b34bfd7a7539c36.png

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

9fe161f989774fe7a5304646fae65405.png

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

3cba9a360297438380b425efdb9978d2.png

————————————————
版权声明:py_free-物联智能
如有侵权请联系删除




5b6e19539d784a688c7948a9d3f80bf2.png
收藏 评论0 发布时间:2023-4-6 22:05

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版