背景
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接线



板卡上P3T1755位置

MCUXpresso Config Tool配置
1. 下载MCX-N947板卡SDK,打开MCUXpresso Config Tools软件,导入SDK,创建基础工程(带串口打印版本)。
2. 增加I3C引脚定义

3. 增加I3C模块功能配置

4. 增加时钟树配置

5. 重新生成工程

代码编写
编写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已经可以读取信息,且手指放在板卡背面温度传感器对应位置时,可监测到传感器读取到的温度值在逐步上升,因此可以判定温度值读取正确。
我要赚赏金
