首先感谢电子产品世界和恩智浦公司的信任能够参加本次对FRDM-MCXA156开发板的评测。
FRDM-MCXA156基于Arm Cortex-M33 拥有一个I3C接口。开发板板载P3T1755温度传感器可以通过I3C(12.5MHZ)和I2C(3.4MHZ)数据接口读取P3T1755寄存器。I3C的设备并不常见,之前少有涉猎,所以先从I3C入手开始评测。
恩智浦提供了I3C相关例程,位于:SDK_2_16_100_FRDM-MCXA156\boards\frdmmcxa156\driver_examples\i3c\master_read_sensor_p3t1755
本文试图对该例程进行解读。
一、硬件连接



通过I3C0(P0_16、P0_17)连接P3T1755。
二、P3T1755
The P3T1755 is a temperature-to-digital converter from -40 °C to +125 °C range. It uses an on-chip band gap
temperature sensor and A-to-D conversion technique with an overtemperature detection. The device contains a
number of configuration and data registers to store the device settings, such as device operation mode, and a
temperature register (Temp) to store the digital temp reading that can be communicated by a controller via the
2-wire serial I3C (up to 12.5 MHz) and I2C (up to 3.4 MHz) interface.



SDA、SCL是I3C接口,在I3C模式下ALERT不起作用。A0、A1、A2用于用户自定义设备地址,开发板上这3个引脚接地。
P3T1755做为从机使用,数据手册上给出了地址的确定方法:

可以得出从机地址为0x48(SENSOR_SLAVE_ADDR)
三、源码解读
1、BOARD_InitPins();
初始化I3C0
const port_pin_config_t port0_16_pin83_config = {/* Internal pull-up/down resistor is disabled */
kPORT_PullDisable,
/* Low internal pull resistor value is selected. */
kPORT_LowPullResistor,
/* Fast slew rate is configured */
kPORT_FastSlewRate,
/* Passive input filter is disabled */
kPORT_PassiveFilterDisable,
/* Open drain output is disabled */
kPORT_OpenDrainDisable,
/* Low drive strength is configured */
kPORT_LowDriveStrength,
/* Normal drive strength is configured */
kPORT_NormalDriveStrength,
/* Pin is configured as I3C0_SDA */
kPORT_MuxAlt10,
/* Digital input enabled */
kPORT_InputBufferEnable,
/* Digital input is not inverted */
kPORT_InputNormal,
/* Pin Control Register fields [15:0] are not locked */
kPORT_UnlockRegister};
/* PORT0_16 (pin 83) is configured as I3C0_SDA */
PORT_SetPinConfig(PORT0, 16U, &port0_16_pin83_config);
const port_pin_config_t port0_17_pin84_config = {/* Internal pull-up/down resistor is disabled */
kPORT_PullDisable,
/* Low internal pull resistor value is selected. */
kPORT_LowPullResistor,
/* Fast slew rate is configured */
kPORT_FastSlewRate,
/* Passive input filter is disabled */
kPORT_PassiveFilterDisable,
/* Open drain output is disabled */
kPORT_OpenDrainDisable,
/* Low drive strength is configured */
kPORT_LowDriveStrength,
/* Normal drive strength is configured */
kPORT_NormalDriveStrength,
/* Pin is configured as I3C0_SCL */
kPORT_MuxAlt10,
/* Digital input enabled */
kPORT_InputBufferEnable,
/* Digital input is not inverted */
kPORT_InputNormal,
/* Pin Control Register fields [15:0] are not locked */
kPORT_UnlockRegister};
/* PORT0_17 (pin 84) is configured as I3C0_SCL */
PORT_SetPinConfig(PORT0, 17U, &port0_17_pin84_config);2、I3C初始化
I3C_MasterGetDefaultConfig(&masterConfig); masterConfig.baudRate_Hz.i2cBaud = EXAMPLE_I2C_BAUDRATE; masterConfig.baudRate_Hz.i3cPushPullBaud = EXAMPLE_I3C_PP_BAUDRATE; masterConfig.baudRate_Hz.i3cOpenDrainBaud = EXAMPLE_I3C_OD_BAUDRATE; masterConfig.enableOpenDrainStop = false; masterConfig.disableTimeout = true; I3C_MasterInit(EXAMPLE_MASTER, &masterConfig, I3C_MASTER_CLOCK_FREQUENCY); /* Create I3C handle. */ I3C_MasterTransferCreateHandle(EXAMPLE_MASTER, &g_i3c_m_handle, &masterCallback, NULL);
3、设置P3T1755动态地址p3t1755_set_dynamic_address()
#define SENSOR_SLAVE_ADDR 0x48U
#define SENSOR_ADDR 0x08U
#define CCC_RSTDAA 0x06U
#define CCC_SETDASA 0x87
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(EXAMPLE_MASTER, &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(EXAMPLE_MASTER, &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(EXAMPLE_MASTER, &masterXfer);
}这一步基于数据手册的这个图解:

在 p3t1755_set_dynamic_address(void)中,首先对地址做了一个复位操作,然后将I3C从机指定地址为SENSOR_ADDR(0x08U),考虑到I3C是7h(7位),所以做了一个SENSOR_ADDR << 1左移1位的操作。
CCC是I3C Common Command Codes的缩写。P3T1755 supports CCCs that allow the controller to control multiple targets through a broadcast command at once or individual targets through direct commands这些指令如下:

本例中用到了0x06、0x87指令。
RESET 地址,需要发送0X7E,0x06

设置动态地址:

4、p3t1755初始化
p3t1755Config.writeTransfer = I3C_WriteSensor; p3t1755Config.readTransfer = I3C_ReadSensor; p3t1755Config.sensorAddress = SENSOR_ADDR; P3T1755_Init(&p3t1755Handle, &p3t1755Config);
指定了I3C读写p3t1755寄存器的处理函数和I3C从机地址。
5、I3C_ReadSensor()
P3T1755_ReadReg函数会调用I3C_ReadSensor。
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(EXAMPLE_MASTER, &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;
}I3C_MasterTransferNonBlocking向从机发送I3C数据实现读取P3T1755寄存器。
regAddress取值:

6、温度读取及计算
/* Registers. */
#define P3T1755_TEMPERATURE_REG (0x00U)
#define P3T1755_CONFIG_REG (0x01U)
status_t P3T1755_ReadTemperature(p3t1755_handle_t *handle, double *temperature)
{
status_t result = kStatus_Success;
uint8_t data[2];
uint16_t temp;
result = P3T1755_ReadReg(handle, P3T1755_TEMPERATURE_REG, &data[0], 2);
if (result == kStatus_Success)
{
temp = (((uint16_t)data[0] << 8U) | (uint16_t)data[1]) >> 4U;
*temperature = (double)temp * 0.0625;
}
return result;
}
四、运行效果

我要赚赏金
