一、外设配置

从原理图可以看到这个传感器采用I2C和MCU进行通信,注意I2C的SCL和SDA都需要接入上拉电阻,一般取阻值为4.7KΩ。

下面,进入CUBEMX配置

首先,进行基础的配置

然后,I2C和USART的配置,因为我们传感器的测得的数据最后通过USART显示在PC端

再回到,gpio处修改I2C两个引脚的配置

这里解释一下I2C管脚配置

GPIO Mode:Alternate Function Open Drain(复用开漏输出)

复用(Alternate Function):为了让 I2C 硬件外设直接控制引脚(而非软件手动翻转电平),由外设自动生成 I2C 时序(时钟、起始 / 停止信号、数据收发等),效率更高、时序更精准。

开漏输出(Open Drain): 输出 0 时:引脚主动拉低总线(驱动能力强)。 输出 1 时:引脚进入 高阻态(相当于 “释放总线”),此时总线电平由 外部上拉电阻(或内部上拉)维持为高。

GPIO Pull-up/Pull-down:Pull-up(上拉)

I2C 协议规定,总线空闲时 SCL、SDA 必须为高电平,上拉确保这一点。

Maximum output speed:Medium(中等速度)

中等速度,足以满足时序,还能 降低功耗和电磁干扰,高速模式会增加功耗和辐射。

最后进行时钟配置,生成工程

这里是之前做的工程,在LED基础上修改的,所以名称还是LED

二、添加BSP板级支持包,编写代码

GITHub stm32官方社区下载驱动包

我们总共需要找到这三个文件,但是例程中读取寄存器的文件是基于其他芯片编写的,我们需要对这个文件(stts751_read_data_polling)进行修改

下面,我教大家如何去找这几个文件

打开链接,翻到最下面这个文档

打开是这个界面(关注最上面有文档路径),我们继续打开红框标注的这个文档

将这两个文件下载到D盘,放在新建文件夹命名为BSP,然后返回到上一个界面,打开EXAMPELS

下载这个例程中的寄存器读取文件,放在之前建好的BSP文件夹中,至此下载完成,注意如果网页长时间打不开,需要搭载VPN过去。

下面在工程文件中添加BSP包

根据上图我添加的路径将BSP包复制过去   ,然后打开KEIL工程文件

右键点击LED,选择ADD Group,之后对生成的NEW GROUP重新命名为BSP

接下来,添加已有的文件(之前下载的BSP包)

找到之前的路径,全选三个文件,点击ADD

如上图所示,添加成功,下面继续在工程中添加这些文件对应的路径

按照上述步骤,找到BSP包之后,点击选择文件夹即可。

出现BSP路径,表示添加成功,点击OK.

现在,就可以进行程序编写了,首先打开stts751_read_data_polling.C文件,此前下载的是基于其他板子的,在此,我将已将修改好的基于我们这款板子的代码全部罗列出来

/*
 * 本示例由 STMicroelectronics 开发,适用于以下评估板:
 *
 * - NUCLEO_F401RE + X-NUCLEO-IKS01A3
 * - DISCOVERY_SPC584B + STEVAL-MKI198V1K
 *
 * 使用的通信接口:
 * - UART(通过 USB 转串口桥连接主机)
 * - I2C(默认)或 SPI(支持)
 *
 * 如果你在不同硬件平台上运行该示例,请修改以下函数:
 * `platform_write`, `platform_read`, `tx_com` 和 `platform_init`
 */

/* 硬件平台定义(使用哪块板子):
 * 如果使用其他平台,请注释掉以下定义并自行修改对应平台的定义。
 */
//#define NUCLEO_F401RE    /* 小端模式 */
//#define SPC584B_DIS      /* 大端模式 */

/* 默认驱动为小端模式,如需切换到大端模式,
 * 请参考驱动头文件中的 "Endianness definitions" 部分。
 */

#define SENSOR_BUS hi2c2  // 指定使用 I2C2 作为传感器通信总线

/* 引入头文件 ---------------------------------------------------------------*/
#include <string.h>
#include <stdio.h>
#include "stts751_reg.h"   // STTS751 传感器寄存器与驱动头文件
#include "i2c.h"           // I2C 初始化配置头文件
#include "usart.h"         // UART 初始化配置头文件

/* 私有宏 --------------------------------------------------------------------*/

/* 私有变量 ------------------------------------------------------------------*/
static int16_t data_raw_temperature;        // 原始温度数据(16位整型)
static float temperature_degC;              // 转换后的摄氏度温度
static stts751_id_t whoamI;                 // 传感器ID信息
static uint8_t tx_buffer[1000];             // 串口发送缓冲区
stmdev_ctx_t dev_ctx;                       // MEMS 设备上下文结构体(读写函数等)

/* 外部变量 ------------------------------------------------------------------*/

/* 私有函数声明 -------------------------------------------------------------*/
/*
 * 注意:
 * 以下函数的定义和硬件平台强相关,必须根据使用的平台进行调整
 */
static int32_t platform_write(void *handle, uint8_t reg, const uint8_t *bufp, uint16_t len); // I2C 写操作
static int32_t platform_read(void *handle, uint8_t reg, uint8_t *bufp, uint16_t len);         // I2C 读操作
static void tx_com(uint8_t *tx_buffer, uint16_t len);                                         // 串口发送数据
static void platform_delay(uint32_t ms);                                                      // 延时函数
static void platform_init(void);                                                              // 平台初始化(留空)

/* 主程序逻辑:轮询方式读取温度数据 ----------------------------------------*/
void stts751_read_data_polling(void)
{
    //uint8_t flag;
    // 获取忙标志位,仅在数据准备好时读取
   // stts751_flag_busy_get(&dev_ctx, &flag);

   // if (flag) {
      // 读取温度原始数据
      memset(&data_raw_temperature, 0, sizeof(int16_t));
      stts751_temperature_raw_get(&dev_ctx, &data_raw_temperature);
      
      // 将原始数据转换为摄氏度
      temperature_degC = stts751_from_lsb_to_celsius(data_raw_temperature);

      // 将温度格式化为字符串并通过串口发送
      sprintf((char *)tx_buffer, "Temperature [degC]:%3.2f\r\n", temperature_degC);
      tx_com(tx_buffer, strlen((char const *)tx_buffer));
   // }
}

/* STTS751 初始化 ------------------------------------------------------------*/
void stts751_init(void)
{
  // 设置驱动器函数和句柄
  dev_ctx.write_reg = platform_write;
  dev_ctx.read_reg = platform_read;
  dev_ctx.mdelay = platform_delay;
  dev_ctx.handle = &SENSOR_BUS;

  // 执行平台初始化(此处为空)
  platform_init();

  // 读取传感器ID进行验证
  stts751_device_id_get(&dev_ctx, &whoamI);
  if ((whoamI.product_id != STTS751_ID_0xxxx) || 
      (whoamI.manufacturer_id != STTS751_ID_MAN) ||
      (whoamI.revision_id != STTS751_REV)) {
//    while (1); // 如果不是预期设备,卡死程序
  }

  // 设置高温(49.5℃)和低温(-4.5℃)阈值报警
  float temperature_high_limit = 49.5f;
  stts751_high_temperature_threshold_set(&dev_ctx,
      stts751_from_celsius_to_lsb(temperature_high_limit));

  float temperature_low_limit = -4.5f;
  stts751_low_temperature_threshold_set(&dev_ctx,
      stts751_from_celsius_to_lsb(temperature_low_limit));

  // 启用中断引脚输出
  stts751_pin_event_route_set(&dev_ctx, PROPERTY_ENABLE);

  // 设置采样频率为 1Hz(每秒采样一次)
  stts751_temp_data_rate_set(&dev_ctx, STTS751_TEMP_ODR_1Hz);

  // 设置精度为 11 位
  stts751_resolution_set(&dev_ctx, STTS751_11bit);
}

/* -------------------------- 平台相关底层函数 ---------------------------- */

/*
 * 向传感器指定寄存器写入数据
 */
static int32_t platform_write(void *handle, uint8_t reg, const uint8_t *bufp, uint16_t len)
{
  HAL_I2C_Mem_Write(handle, STTS751_0xxxx_ADD_7K5, reg,
                    I2C_MEMADD_SIZE_8BIT, (uint8_t*) bufp, len, 1000);
  return 0;
}

/*
 * 从传感器指定寄存器读取数据
 */
static int32_t platform_read(void *handle, uint8_t reg, uint8_t *bufp, uint16_t len)
{
  HAL_I2C_Mem_Read(handle, STTS751_0xxxx_ADD_7K5, reg,
                   I2C_MEMADD_SIZE_8BIT, bufp, len, 1000);
  return 0;
}

/*
 * 将数据通过 UART2 打印出来
 */
static void tx_com(uint8_t *tx_buffer, uint16_t len)
{
  HAL_UART_Transmit(&huart2, tx_buffer, len, 1000);
}

/*
 * 平台延时函数
 */
static void platform_delay(uint32_t ms)
{
  HAL_Delay(ms);
}

/*
 * 平台初始化函数(预留给 GPIO、外设等初始化,此处未使用)
 */
static void platform_init(void)
{
}

各位可以直接复制粘贴,替换原有代码

下面打开mian.c文件,添加必要头文件,串口重定向函数和温度读取函数

此处,简要说明:由于我是基于此前配置LED基础上进行修改的,所以如果仅是根据本文重新建立工程的朋友,以上重定向代码中LED部分会报错,把这部分注释掉即可

添加温度读取函数。至此,代码编写完成,可以仿照测评一进行编译烧录。

三、效果实现

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐