这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » 【换取手持数字示波器】使用MCXN947 I3C接口读取P3T1755DP传感器

共2条 1/1 1 跳转至

【换取手持数字示波器】使用MCXN947 I3C接口读取P3T1755DP传感器数据

助工
2024-05-25 13:06:03   被打赏 47 分(兑奖)     打赏

背景

        I2C总线接口,能够使多路设备挂在一个总线上,通过时分复用的方式实现硬件接口占用的降低。但其也存在一些缺点,一是因为需要协商机制,以确保从设备的正确响应,导致带宽浪费,而I2C总线标准中,即使最高速率3.4Mbit/s,也会在重度负荷时出现带宽不足的情况。二是I2C接口,若从设备有消息需更新至主设备端,单纯的I2C接口无法解决通知问题,需额外增加状态通知链路解决该问题。为解决以上问题,I3C标准应运而生。

I3C标准介绍

        I3C,全称为Improved Inter-Integrated Circuit,是一种由MIPI联盟发布的通信总线接口标准。作为I2C(Inter-Integrated Circuit)的升级版,I3C不仅继承了I2C的2线传输特性,还在性能、功耗和扩展性方面进行了显著的改进。以下是对I3C接口特点的详细介绍,特别是它相对于I2C的改善之处:

一、传输速率和性能的大幅提升

        I3C支持更高的数据传输速率。在标准CMOS I/O上,它支持最低10Mbps的数据速率,相比I2C有了显著的提升。此外,I3C还具有高性能的高数据速率(HDR)模式选项,理论最大速率可达到39.5Mbps(实际有效传输速率约为33.3Mbps),这远超过了I2C的通信速度。

二、功耗效率的改进

        I3C在功耗方面也有所优化。它最低支持1.2V电平(同时支持1.8V/3.3V,不支持5V),在相同的电平标准下,I3C的整体功耗远小于I2C,这使得I3C成为更为节能的通信接口。

三、动态寻址和多主设备支持

        与I2C的静态寻址不同,I3C采用了动态寻址方式。这意味着从设备的地址可以由当前的主控制器在初始化后动态分配,提供了更为灵活的设备配置和管理方式。

        I3C支持多主机和多从机配置,增强了总线系统的可扩展性和灵活性。这种多主设备的支持使得多个控制器能够共享同一条总线,从而简化了系统设计和布线。

四、高级功能和中断机制

        I3C提供了高级电源管理功能,如睡眠模式,以进一步降低功耗。

        它还支持带内中断功能,这意味着从设备可以通过I3C总线产生中断并通知主控制器,从而节省了一根额外的中断线,简化了系统布线并降低了成本。

五、广泛的兼容性和应用前景

        I3C向下兼容I2C,这使得现有的I2C设备可以无缝地集成到I3C系统中,保护了用户的投资并简化了升级过程。

        由于其高性能、低功耗和灵活的配置选项,I3C在移动无线传感器系统、可穿戴设备以及其他需要高效、低功耗通信的应用领域具有广阔的应用前景。

P3T1755简介

        P3T1755是一款高性能的数字温度传感器,它基于I3C/I2C总线通信,提供了极高的温度测量精度和广泛的工作温度范围。以下是关于P3T1755的详细简介:

一、产品概述

        P3T1755是一款精确的温度数字转换器,其测量精度达到了±0.5°C,温度测量范围覆盖从-40°C到+125°C。该传感器集成了片上带隙温度传感器,并采用先进的模数转换技术,确保温度数据的准确性和可靠性。

二、主要特性

        高精度测量:P3T1755的测量精度高达±0.5°C,能够满足各种高精度温度测量需求。

        宽温度范围:支持从-40°C到+125°C的宽温度范围,适用于各种环境条件下的温度监测。

        多种工作模式:P3T1755可配置为连续转换模式、单一转换模式或关闭模式,以满足不同应用场景的需求。

        超温检测功能:具有超温检测功能,能够在温度超过设定阈值时产生警报,确保系统安全。

        通信接口:支持2线串行I3C(高达12.5MHz)和I2C(高达3.4MHz)作为通信接口,方便与其他设备进行数据交换。

三、技术规格

        温度分辨率:0.0625°C,确保温度数据的精确性。

        温度寄存器:始终存储12位二进制补码数据,方便数据处理和存储。

        I3C特性:支持带内中断功能(IBI),使用同一总线报告警报中断。

四、应用领域

        P3T1755广泛应用于各种需要高精度温度测量的领域,如工业自动化、环境监测、医疗设备、汽车电子等。其高性能和可靠性使其成为这些领域中不可或缺的传感器之一。

FRDM-MCXN947上硬件接口

原理图P3T1755接线

1.jpg

1.jpg

1.jpg

板卡上P3T1755位置

1.jpg

MCUXpresso Config Tool配置

1. 下载MCX-N947板卡SDK,打开MCUXpresso Config Tools软件,导入SDK,创建基础工程(带串口打印版本)。

2. 增加I3C引脚定义

1.jpg

3. 增加I3C模块功能配置

1.jpg

4. 增加时钟树配置

1.jpg

5. 重新生成工程

1.jpg

代码编写

编写p3t1755驱动文件

p3t1755.h

#ifndef __P3T1755_H_
#define __P3T1755_H_

#include "fsl_common.h"

/* Registers. */
#define P3T1755_TEMPERATURE_REG (0x00U)
#define P3T1755_CONFIG_REG      (0x01U)

/*! @brief Define sensor access function. */
typedef status_t (*sensor_write_transfer_func_t)(uint8_t deviceAddress,
                                                 uint32_t regAddress,
                                                 uint8_t *regData,
                                                 size_t dataSize);
typedef status_t (*sensor_read_transfer_func_t)(uint8_t deviceAddress,
                                                uint32_t regAddress,
                                                uint8_t *regData,
                                                size_t dataSize);

typedef struct _p3t1755_handle
{
    sensor_write_transfer_func_t writeTransfer;
    sensor_read_transfer_func_t readTransfer;
    uint8_t sensorAddress;
} p3t1755_handle_t;

typedef struct _p3t1755_config
{
    sensor_write_transfer_func_t writeTransfer;
    sensor_read_transfer_func_t readTransfer;
    uint8_t sensorAddress;
} p3t1755_config_t;

status_t P3T1755_Init(p3t1755_handle_t *handle, p3t1755_config_t *config);
status_t P3T1755_WriteReg(p3t1755_handle_t *handle, uint32_t regAddress, uint8_t *regData, size_t dataSize);
status_t P3T1755_ReadReg(p3t1755_handle_t *handle, uint32_t regAddress, uint8_t *regData, size_t dataSize);
status_t P3T1755_ReadTemperature(p3t1755_handle_t *handle, double *temperature);

#endif /* __P3T1755_H_ */

p3t1755.c

#include "p3t1755.h"

status_t P3T1755_WriteReg(p3t1755_handle_t *handle, uint32_t regAddress, uint8_t *regData, size_t dataSize)
{
    status_t result;
    result = handle->writeTransfer(handle->sensorAddress, regAddress, regData, dataSize);

    return (result == kStatus_Success) ? result : kStatus_Fail;
}

status_t P3T1755_ReadReg(p3t1755_handle_t *handle, uint32_t regAddress, uint8_t *regData, size_t dataSize)
{
    status_t result;
    result = handle->readTransfer(handle->sensorAddress, regAddress, regData, dataSize);

    return (result == kStatus_Success) ? result : kStatus_Fail;
}

status_t P3T1755_Init(p3t1755_handle_t *handle, p3t1755_config_t *config)
{
    assert(handle != NULL);
    assert(config != NULL);
    assert(config->writeTransfer != NULL);
    assert(config->readTransfer != NULL);

    handle->writeTransfer = config->writeTransfer;
    handle->readTransfer  = config->readTransfer;
    handle->sensorAddress = config->sensorAddress;

    return kStatus_Success;
}

status_t P3T1755_ReadTemperature(p3t1755_handle_t *handle, double *temperature)
{
    status_t result = kStatus_Success;
    uint8_t data[2];

    result = P3T1755_ReadReg(handle, P3T1755_TEMPERATURE_REG, &data[0], 2);
    if (result == kStatus_Success)
    {
        *temperature = (double)((((uint16_t)data[0] << 8U) | (uint16_t)data[1]) >> 4U);
        *temperature = *temperature * 0.0625;
    }

    return result;
}

编写程序应用层程序

main.c

#include <string.h>
/*  SDK Included Files */
#include "board.h"
#include "clock_config.h"
#include "fsl_debug_console.h"
#include "fsl_i3c.h"
#include "p3t1755.h"
#include "peripherals.h"
#include "pin_mux.h"

/*******************************************************************************
 * Definitions
 ******************************************************************************/
#define SENSOR_SLAVE_ADDR 0x48U
#define I3C_TIME_OUT_INDEX 100000000U

#define SENSOR_ADDR 0x08U
#define CCC_RSTDAA 0x06U
#define CCC_SETDASA 0x87

/*******************************************************************************
 * Prototypes
 ******************************************************************************/
static void i3c_master_callback(I3C_Type *base, i3c_master_handle_t *handle, status_t status, void *userData);
/*******************************************************************************
 * Variables
 ******************************************************************************/
volatile status_t g_completionStatus;
volatile bool g_masterCompletionFlag;
i3c_master_handle_t g_i3c_m_handle;
p3t1755_handle_t p3t1755Handle;

const i3c_master_transfer_callback_t masterCallback = {
    .slave2Master = NULL, .ibiCallback = NULL, .transferComplete = i3c_master_callback};

/*******************************************************************************
 * Code
 ******************************************************************************/
static void i3c_master_callback(I3C_Type *base, i3c_master_handle_t *handle, status_t status, void *userData) {
  if (status == kStatus_Success) {
    g_masterCompletionFlag = true;
  }

  g_completionStatus = status;
}

status_t I3C_WriteSensor(uint8_t deviceAddress, uint32_t regAddress, uint8_t *regData, size_t dataSize) {
  status_t result                  = kStatus_Success;
  i3c_master_transfer_t masterXfer = {0};
  uint32_t timeout                 = 0U;

  masterXfer.slaveAddress   = deviceAddress;
  masterXfer.direction      = kI3C_Write;
  masterXfer.busType        = kI3C_TypeI3CSdr;
  masterXfer.subaddress     = regAddress;
  masterXfer.subaddressSize = 1;
  masterXfer.data           = regData;
  masterXfer.dataSize       = dataSize;
  masterXfer.flags          = kI3C_TransferDefaultFlag;

  g_masterCompletionFlag = false;
  g_completionStatus     = kStatus_Success;
  result                 = I3C_MasterTransferNonBlocking(I3C1_PERIPHERAL, &g_i3c_m_handle, &masterXfer);
  if (kStatus_Success != result) {
    return result;
  }

  while (!g_masterCompletionFlag) {
    timeout++;
    if ((g_completionStatus != kStatus_Success) || (timeout > I3C_TIME_OUT_INDEX)) {
      break;
    }
  }

  if (timeout == I3C_TIME_OUT_INDEX) {
    result = kStatus_Timeout;
  }
  result = g_completionStatus;

  return result;
}

status_t I3C_ReadSensor(uint8_t deviceAddress, uint32_t regAddress, uint8_t *regData, size_t dataSize) {
  status_t result                  = kStatus_Success;
  i3c_master_transfer_t masterXfer = {0};
  uint32_t timeout                 = 0U;

  masterXfer.slaveAddress   = deviceAddress;
  masterXfer.direction      = kI3C_Read;
  masterXfer.busType        = kI3C_TypeI3CSdr;
  masterXfer.subaddress     = regAddress;
  masterXfer.subaddressSize = 1;
  masterXfer.data           = regData;
  masterXfer.dataSize       = dataSize;
  masterXfer.flags          = kI3C_TransferDefaultFlag;

  g_masterCompletionFlag = false;
  g_completionStatus     = kStatus_Success;
  result                 = I3C_MasterTransferNonBlocking(I3C1_PERIPHERAL, &g_i3c_m_handle, &masterXfer);
  if (kStatus_Success != result) {
    return result;
  }

  while (!g_masterCompletionFlag) {
    timeout++;
    if ((g_completionStatus != kStatus_Success) || (timeout > I3C_TIME_OUT_INDEX)) {
      break;
    }
  }

  if (timeout == I3C_TIME_OUT_INDEX) {
    result = kStatus_Timeout;
  }
  result = g_completionStatus;

  return result;
}

status_t p3t1755_set_dynamic_address(void) {
  status_t result                  = kStatus_Success;
  i3c_master_transfer_t masterXfer = {0};
  uint8_t g_master_txBuff[1];

  /* Reset dynamic address. */
  g_master_txBuff[0]      = CCC_RSTDAA;
  masterXfer.slaveAddress = 0x7E;
  masterXfer.data         = g_master_txBuff;
  masterXfer.dataSize     = 1;
  masterXfer.direction    = kI3C_Write;
  masterXfer.busType      = kI3C_TypeI3CSdr;
  masterXfer.flags        = kI3C_TransferDefaultFlag;
  result                  = I3C_MasterTransferBlocking(I3C1_PERIPHERAL, &masterXfer);
  if (result != kStatus_Success) {
    return result;
  }

  /* Assign dynmic address. */
  memset(&masterXfer, 0, sizeof(masterXfer));
  g_master_txBuff[0]      = CCC_SETDASA;
  masterXfer.slaveAddress = 0x7E;
  masterXfer.data         = g_master_txBuff;
  masterXfer.dataSize     = 1;
  masterXfer.direction    = kI3C_Write;
  masterXfer.busType      = kI3C_TypeI3CSdr;
  masterXfer.flags        = kI3C_TransferNoStopFlag;
  result                  = I3C_MasterTransferBlocking(I3C1_PERIPHERAL, &masterXfer);
  if (result != kStatus_Success) {
    return result;
  }

  memset(&masterXfer, 0, sizeof(masterXfer));
  g_master_txBuff[0]      = SENSOR_ADDR << 1;
  masterXfer.slaveAddress = SENSOR_SLAVE_ADDR;
  masterXfer.data         = g_master_txBuff;
  masterXfer.dataSize     = 1;
  masterXfer.direction    = kI3C_Write;
  masterXfer.busType      = kI3C_TypeI3CSdr;
  masterXfer.flags        = kI3C_TransferDefaultFlag;
  return I3C_MasterTransferBlocking(I3C1_PERIPHERAL, &masterXfer);
}


int main(void) {
  status_t result = kStatus_Success;
  i3c_master_config_t masterConfig;
  p3t1755_config_t p3t1755Config;
  double temperature;

  CLOCK_SetClkDiv(kCLOCK_DivI3c1FClk, 6U);
  CLOCK_AttachClk(kPLL0_to_I3C1FCLK);

  BOARD_InitPins();
  BOARD_InitBootClocks();
  BOARD_InitDebugConsole();
  BOARD_InitBootPeripherals();

  PRINTF("I3C master read sensor data.\r\n");

  /* Create I3C handle. */
  I3C_MasterTransferCreateHandle(I3C1_PERIPHERAL, &g_i3c_m_handle, &masterCallback, NULL);

  p3t1755_set_dynamic_address();

  p3t1755Config.writeTransfer = I3C_WriteSensor;
  p3t1755Config.readTransfer  = I3C_ReadSensor;
  p3t1755Config.sensorAddress = SENSOR_ADDR;
  P3T1755_Init(&p3t1755Handle, &p3t1755Config);

  while (1) {
    result = P3T1755_ReadTemperature(&p3t1755Handle, &temperature);
    if (result != kStatus_Success) {
      PRINTF("P3T1755 read temperature failed.\r\n");
    } else {
      PRINTF("Temperature:%f \r\n", temperature);
    }
    SDK_DelayAtLeastUs(1000000, CLOCK_GetCoreSysClkFreq());
  }
}

结果验证

        程序编写完毕后,编译代码并下载至板卡端,查看运行结果:

I3C master read sensor data.

Temperature:28.750000

Temperature:28.812500

Temperature:28.812500

Temperature:28.812500

Temperature:28.750000

Temperature:28.750000

Temperature:29.000000

Temperature:29.250000

Temperature:29.687500

Temperature:30.000000

Temperature:30.250000

Temperature:30.500000

Temperature:30.750000

Temperature:30.937500

Temperature:31.125000

Temperature:31.312500

Temperature:31.437500

Temperature:31.562500

Temperature:31.687500

Temperature:31.875000

从结果上看,MCX-N947已经可以读取信息,且手指放在板卡背面温度传感器对应位置时,可监测到传感器读取到的温度值在逐步上升,因此可以判定温度值读取正确。








关键词: P3T1755     i3c    

院士
2024-05-27 14:41:05     打赏
2楼

楼主这都已经开玩I3C接口了啊!

羡慕一下


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]