用于 MCXW71 的 PN7160 NXP-NCI 2.0 SPI 示例迁移指南
本文章将介绍如何使用 SPI 接口将 NXP NCI 2.0 NFC 库中的示例项目移植到 MCXW71 Wireless MCU,以便与 PN7160 SPI EVK 通信。
要使用本指南,请使用以下环境:
MCUXpresso IDE 25.06.136.
FRDM-MCXW71 SDK v25.12.00(MCUXpresso IDE 的最新版本)。
FRDM-MCXW71。
OM27160B1(PN7160 SPI EVK)。
硬件设置。
MCXW71 作为 OM27160B1 板符合 Arduino 接头标准,因此您可以直接将子卡连接到 FRDM-MCXW71 上,因为两者的引脚连接相匹配,这样设备之间就可以轻松连接。考虑到这种设置迫使我们使用 MCXW71 的 LPSPI1 实例,可以使用其他实例,但我们无法直接连接主板,而是需要使用跳线进行连接。
下载基本项目并为 MCXW71 移植进行调整。
要开始移植工作,请从本页下载 NXP-NCI 示例项目。这个压缩文件包含不同板的基础项目,这将允许我们进行必要的修改以增加对 MCXW71 的支持。下载完成后,将 SW6705 文件解压缩到已知路径(如下载文件夹)中,以便稍后将项目导入集成开发环境。解压缩后的文件夹应包含一个.zip 文件。文件,其中包含我们稍后将导入到集成开发环境的示例。
从SDK Builder 页面下载 FRDM-MCXW71 的 SDK,确保选择 25.12.00 版本,因为它是可在 MCUXpresso IDE 中使用的最新 SDK。
现在我们必须将之前提取的 nxp-nci2.0_mcuxpresso_examples.zip 文件导入到 IDE 的工作区,为此,单击 “ 从文件系统导入项目”,然后在 “项目存档 (zip)” 选项卡中,浏览步骤 1 中提取的文件 (nxp-NCI2.0_mcuxpress o_examples.zip) ,然后单击 Next > 注意: 如果 IDE 因为没有默认板(imxRT1170、LPC55s6x、LPC82x)的软件开发工具包或者版本不同而显示错误信息,请不要担心,关闭警告消息,我们只需要这些示例来复制 NCI 库和示例文件。 您的工作区现在应该如下图所示:
从 FRDM-MCXW71 SDK 中导入hello_world示例:
右键单击项目,将 SPI 驱动程序添加到导入的项目中,将光标悬停在 SDK 管理选项上,然后选择 “管理 SDK 元器件” 选项: 选择驱动程序,单击 “确定”,如果要求您刷新文件,则接受该驱动程序,之后您应该能够在 " 驱动程序中看到该驱动程序项目的 " 文件夹。
复制 iMXRT1170 项目源文件夹和 NfcLibrary 文件夹的内容,并将其粘贴到导入的hello_world项目中: 确保删除hello_world.c和hello_word.mex文件,因为我们不会再用到它们。 完成此过程后,您的项目应如下图所示:
为避免编译问题,请从版本文件中排除 nfc_example_P2P.c和nfc_example_RW.c、要执行此操作,请右键单击该文件,转到 “资源配置”,选择 “从版本中排除...”,然后选择所有配置。对每个文件都这样做。
添加预处理器宏:BOARD_NXPNCI_INTERFACE_SPI,因为示例使用该宏来选择与主板的接口。为此,请右键单击该项目并选择 “属性”,然后下拉 “C/C++ 构建” 选项并转到 “设置” 选项卡。在此,在预处理器选项中添加宏,点击应用并接受索引重建。
在 C/C++ 常规 > 路径和符号 > 源位置选项卡中添加根文件夹,单击 “确定”,然后单击 “应用”:
仍在 “路径和符号” 中,转到 “包含” 选项卡并添加工作空间中的源、TML 和工具文件夹,单击 “确定” 和 “应用”。确保逐一添加。
现在,转到 C/C++ 版本 > Settings > Includes 并从 Workspace 添加以下文件夹。您可以同时选择并添加它们,也可以逐个添加。完成后,点击 "应用"和 "应用并关闭"。如果要求您重建索引,请执行。 "${workspace_loc:/${ProjName}/source/TML}"
"${workspace_loc:/${ProjName}/source/tool}"
"${workspace_loc:/${ProjName}/NfcLibrary}"
"${workspace_loc:/${ProjName}/NfcLibrary/inc}"
"${workspace_loc:/${ProjName}/NfcLibrary/NdefLibrary}"
"${workspace_loc:/${ProjName}/NfcLibrary/NdefLibrary/inc}"
"${workspace_loc:/${ProjName}/NfcLibrary/NdefLibrary/src}"
"${workspace_loc:/${ProjName}/NfcLibrary/NxpNci20}"
"${workspace_loc:/${ProjName}/NfcLibrary/NxpNci20/inc}"
"${workspace_loc:/${ProjName}/NfcLibrary/NxpNci20/src}"
源代码更改。
在看板文件夹中,打开 board.h文件,并添加以下定义,以指代要使用的外设和时钟。请注意,您可以更改 LPSPI 实例,但是您需要连接跳线,而不是通过 FRDM 直接连接子卡。 #ifdef BOARD_NXPNCI_INTERFACE_SPI
#define BOARD_NXPNCI_SPI_CLOCK (CLOCK_GetIpFreq(kCLOCK_Lpspi1))
#define BOARD_NXPNCI_SPI_INSTANCE (LPSPI1)
#define BOARD_NXPNCI_SPI_BAUDRATE (400000)
#endif
#define BOARD_NXPNCI_IRQ_PORT (GPIOC) // J2.10 - GPIO0 [PN7160] - IRQ -> J2.10 GPIOC0 [MCXW71]
#define BOARD_NXPNCI_VEN_PORT (GPIOA) // J4.1 - GPIO1 [PN7160] - VEN -> J1.8 GPIOA21 [MCXW71]
#define BOARD_NXPNCI_DWL_PORT (GPIOA) // J4.2 - GPIO2 [PN7160] - REQ -> J1.7 GPIOA20 [MCXW71]
#define BOARD_NXPNCI_IRQ_PIN (0U)
#define BOARD_NXPNCI_VEN_PIN (21U)
#define BOARD_NXPNCI_DWL_PIN (20U)
现在我们需要为我们的主板添加所需的时钟、外设和引脚初始化。为此,请转到hardware_init.c将文件存入板文件夹,然后使用以下内容覆盖 BOARD_InitHardware 函数: void BOARD_InitHardware(void)
{
BOARD_InitPins();
BOARD_BootClockRUN();
BOARD_InitDebugConsole();
CLOCK_SetIpSrc(kCLOCK_Lpspi1, kCLOCK_IpSrcFro192M);
CLOCK_SetIpSrcDiv(kCLOCK_Lpspi1, kSCG_SysClkDivBy16);
}
要为 SPI 和 GPIO 引脚添加正确的引脚复用和配置,请转到pin_mux.c文件(也在看板文件夹中),然后用以下内容覆盖 board_initPin s 函数: void BOARD_InitPins(void)
{
/* Clock Configuration: Peripheral clocks are enabled; module does not stall low power mode entry */
CLOCK_EnableClock(kCLOCK_GpioA);
CLOCK_EnableClock(kCLOCK_GpioC);
CLOCK_EnableClock(kCLOCK_PortA);
CLOCK_EnableClock(kCLOCK_PortB);
CLOCK_EnableClock(kCLOCK_PortC);
/*IF SHORTING SH11, SH12, SH13, SH14 needed for LPSPI1*/
const port_pin_config_t portb0_pin46_config = {/* Internal pull-up resistor is enabled */
(uint16_t)kPORT_PullUp,
/* Low internal pull resistor value is selected. */
(uint16_t)kPORT_LowPullResistor,
/* Fast slew rate is configured */
(uint16_t)kPORT_FastSlewRate,
/* Passive input filter is disabled */
(uint16_t)kPORT_PassiveFilterDisable,
/* Open drain output is disabled */
(uint16_t)kPORT_OpenDrainDisable,
/* Low drive strength is configured */
(uint16_t)kPORT_LowDriveStrength,
/* Normal drive strength is configured */
(uint16_t)kPORT_NormalDriveStrength,
/* Pin is configured as LPSPI0_PCS0 */
(uint16_t)kPORT_MuxAlt2,
/* Pin Control Register fields [15:0] are not locked */
(uint16_t)kPORT_UnlockRegister};
/* PORTB0 (pin 46) is configured as LPSPI1_PCS0 */
PORT_SetPinConfig(PORTB, 0U, &portb0_pin46_config);
const port_pin_config_t portb1_pin47_config = {/* Internal pull-up resistor is enabled */
(uint16_t)kPORT_PullUp,
/* Low internal pull resistor value is selected. */
(uint16_t)kPORT_LowPullResistor,
/* Fast slew rate is configured */
(uint16_t)kPORT_FastSlewRate,
/* Passive input filter is disabled */
(uint16_t)kPORT_PassiveFilterDisable,
/* Open drain output is disabled */
(uint16_t)kPORT_OpenDrainDisable,
/* Low drive strength is configured */
(uint16_t)kPORT_LowDriveStrength,
/* Normal drive strength is configured */
(uint16_t)kPORT_NormalDriveStrength,
/* Pin is configured as LPSPI0_SIN */
(uint16_t)kPORT_MuxAlt2,
/* Pin Control Register fields [15:0] are not locked */
(uint16_t)kPORT_UnlockRegister};
/* PORTB1 (pin 47) is configured as LPSPI1_SIN */
PORT_SetPinConfig(PORTB, 1U, &portb1_pin47_config);
const port_pin_config_t portb3_pin1_config = {/* Internal pull-up resistor is enabled */
(uint16_t)kPORT_PullUp,
/* Low internal pull resistor value is selected. */
(uint16_t)kPORT_LowPullResistor,
/* Fast slew rate is configured */
(uint16_t)kPORT_FastSlewRate,
/* Passive input filter is disabled */
(uint16_t)kPORT_PassiveFilterDisable,
/* Open drain output is disabled */
(uint16_t)kPORT_OpenDrainDisable,
/* Low drive strength is configured */
(uint16_t)kPORT_LowDriveStrength,
/* Normal drive strength is configured */
(uint16_t)kPORT_NormalDriveStrength,
/* Pin is configured as LPSPI0_SOUT */
(uint16_t)kPORT_MuxAlt2,
/* Pin Control Register fields [15:0] are not locked */
(uint16_t)kPORT_UnlockRegister};
/* PORTB3 (pin 1) is configured as LPSPI1_SOUT */
PORT_SetPinConfig(PORTB, 3U, &portb3_pin1_config);
const port_pin_config_t portb2_pin48_config = {/* Internal pull-up resistor is enabled */
(uint16_t)kPORT_PullUp,
/* Low internal pull resistor value is selected. */
(uint16_t)kPORT_LowPullResistor,
/* Fast slew rate is configured */
(uint16_t)kPORT_FastSlewRate,
/* Passive input filter is disabled */
(uint16_t)kPORT_PassiveFilterDisable,
/* Open drain output is disabled */
(uint16_t)kPORT_OpenDrainDisable,
/* Low drive strength is configured */
(uint16_t)kPORT_LowDriveStrength,
/* Normal drive strength is configured */
(uint16_t)kPORT_NormalDriveStrength,
/* Pin is configured as LPSPI0_SCK */
(uint16_t)kPORT_MuxAlt2,
/* Pin Control Register fields [15:0] are not locked */
(uint16_t)kPORT_UnlockRegister};
/* PORTA19 (pin 14) is configured as LPSPI1_SCK */
PORT_SetPinConfig(PORTB, 2U, &portb2_pin48_config);
/*IF SHORTING SH11, SH12, SH13, SH14 needed for LPSPI1*/
const port_pin_config_t irq_pin = {/* Internal pull-up/down resistor is disabled */
(uint16_t)kPORT_PullUp,
/* Low internal pull resistor value is selected. */
(uint16_t)kPORT_LowPullResistor,
/* Fast slew rate is configured */
(uint16_t)kPORT_FastSlewRate,
/* Passive input filter is disabled */
(uint16_t)kPORT_PassiveFilterDisable,
/* Open drain output is disabled */
(uint16_t)kPORT_OpenDrainDisable,
/* Low drive strength is configured */
(uint16_t)kPORT_LowDriveStrength,
/* Normal drive strength is configured */
(uint16_t)kPORT_NormalDriveStrength,
/* Pin is configured as PTC0 */
(uint16_t)kPORT_MuxAsGpio,
/* Pin Control Register fields [15:0] are not locked */
(uint16_t)kPORT_UnlockRegister};
/* PORTC0 (pin 37) is configured as PTC0 */
PORT_SetPinConfig(PORTC, 0U, &irq_pin);
const port_pin_config_t ven_pin = {/* Internal pull-up/down resistor is disabled */
(uint16_t)kPORT_PullDisable,
/* Low internal pull resistor value is selected. */
(uint16_t)kPORT_LowPullResistor,
/* Fast slew rate is configured */
(uint16_t)kPORT_FastSlewRate,
/* Passive input filter is disabled */
(uint16_t)kPORT_PassiveFilterDisable,
/* Open drain output is disabled */
(uint16_t)kPORT_OpenDrainDisable,
/* Low drive strength is configured */
(uint16_t)kPORT_LowDriveStrength,
/* Normal drive strength is configured */
(uint16_t)kPORT_NormalDriveStrength,
/* Pin is configured as PTA20 */
(uint16_t)kPORT_MuxAsGpio,
/* Pin Control Register fields [15:0] are not locked */
(uint16_t)kPORT_UnlockRegister};
/* PORTA20 (pin 17) is configured as PTA20 */
PORT_SetPinConfig(PORTA, 20U, &ven_pin);
const port_pin_config_t req_pin = {/* Internal pull-up/down resistor is disabled */
(uint16_t)kPORT_PullDisable,
/* Low internal pull resistor value is selected. */
(uint16_t)kPORT_LowPullResistor,
/* Fast slew rate is configured */
(uint16_t)kPORT_FastSlewRate,
/* Passive input filter is disabled */
(uint16_t)kPORT_PassiveFilterDisable,
/* Open drain output is disabled */
(uint16_t)kPORT_OpenDrainDisable,
/* Low drive strength is configured */
(uint16_t)kPORT_LowDriveStrength,
/* Normal drive strength is configured */
(uint16_t)kPORT_NormalDriveStrength,
/* Pin is configured as PTA21 */
(uint16_t)kPORT_MuxAsGpio,
/* Pin Control Register fields [15:0] are not locked */
(uint16_t)kPORT_UnlockRegister};
/* PORTA21 (pin 18) is configured as PTA21 */
PORT_SetPinConfig(PORTA, 21U, &req_pin);
const port_pin_config_t portc2_pin39_config = {/* Internal pull-up/down resistor is disabled */
(uint16_t)kPORT_PullDisable,
/* Low internal pull resistor value is selected. */
(uint16_t)kPORT_LowPullResistor,
/* Fast slew rate is configured */
(uint16_t)kPORT_FastSlewRate,
/* Passive input filter is disabled */
(uint16_t)kPORT_PassiveFilterDisable,
/* Open drain output is disabled */
(uint16_t)kPORT_OpenDrainDisable,
/* Low drive strength is configured */
(uint16_t)kPORT_LowDriveStrength,
/* Normal drive strength is configured */
(uint16_t)kPORT_NormalDriveStrength,
/* Pin is configured as LPUART1_RX */
(uint16_t)kPORT_MuxAlt3,
/* Pin Control Register fields [15:0] are not locked */
(uint16_t)kPORT_UnlockRegister};
/* PORTC2 (pin 39) is configured as LPUART1_RX */
PORT_SetPinConfig(PORTC, 2U, &portc2_pin39_config);
const port_pin_config_t portc3_pin40_config = {/* Internal pull-up/down resistor is disabled */
(uint16_t)kPORT_PullDisable,
/* Low internal pull resistor value is selected. */
(uint16_t)kPORT_LowPullResistor,
/* Fast slew rate is configured */
(uint16_t)kPORT_FastSlewRate,
/* Passive input filter is disabled */
(uint16_t)kPORT_PassiveFilterDisable,
/* Open drain output is disabled */
(uint16_t)kPORT_OpenDrainDisable,
/* Low drive strength is configured */
(uint16_t)kPORT_LowDriveStrength,
/* Normal drive strength is configured */
(uint16_t)kPORT_NormalDriveStrength,
/* Pin is configured as LPUART1_TX */
(uint16_t)kPORT_MuxAlt3,
/* Pin Control Register fields [15:0] are not locked */
(uint16_t)kPORT_UnlockRegister};
/* PORTC3 (pin 40) is configured as LPUART1_TX */
PORT_SetPinConfig(PORTC, 3U, &portc3_pin40_config);
}
要添加芯片所需的特定接口应用程序接口,我们需要修改TML文件夹中的tml.c文件,在该文件中用以下函数覆盖INTF_INIT、INTF_WRITE 和 INTF_READ:INTF_INIT、INTF_WRITE和INTF_READ函数: static void INTF_INIT(void)
{
lpspi_master_config_t userConfig;
uint32_t srcFreq = 0;
/*SPI configuration*/
LPSPI_MasterGetDefaultConfig(&userConfig);
userConfig.baudRate = BOARD_NXPNCI_SPI_BAUDRATE;
srcFreq = BOARD_NXPNCI_SPI_CLOCK;
userConfig.whichPcs = (lpspi_which_pcs_t)kLPSPI_Pcs0;
userConfig.pcsActiveHighOrLow = (lpspi_pcs_polarity_config_t)kLPSPI_PcsActiveLow;
/*Initialize SPI*/
LPSPI_MasterInit(BOARD_NXPNCI_SPI_INSTANCE, &userConfig, srcFreq);
}
static status_t INTF_WRITE(uint8_t *pBuff, uint16_t buffLen)
{
uint8_t temp[1000];
temp[0] = 0x7F;
memcpy(temp+1, pBuff, buffLen);
masterXfer.txData = temp;
masterXfer.rxData = NULL;
masterXfer.dataSize = buffLen+1;
masterXfer.configFlags = kLPSPI_MasterPcs0 | kLPSPI_MasterPcsContinuous | kLPSPI_MasterByteSwap;;
return LPSPI_MasterTransferBlocking(BOARD_NXPNCI_SPI_INSTANCE, &masterXfer);
}
static status_t INTF_READ(uint8_t *pBuff, uint16_t buffLen)
{
status_t status;
uint8_t temp[257];
temp[0] = 0xFF;
masterXfer.txData = temp;
masterXfer.rxData = temp;
masterXfer.dataSize = buffLen+1;
masterXfer.configFlags = kLPSPI_MasterPcs0 | kLPSPI_MasterPcsContinuous | kLPSPI_MasterByteSwap;;
status = LPSPI_MasterTransferBlocking(BOARD_NXPNCI_SPI_INSTANCE, &masterXfer);
if(status == kStatus_Success) memcpy(pBuff, temp+1, buffLen);
SDK_DelayAtLeastUs(10, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
return status;
}
#endif
我们还需要重写函数:tml_init、tml_deinit 和 tml_ reset,以调整它们以使其适用于我们主板的 GPIO 的特定 API。 static Status tml_Init(void) {
gpio_pin_config_t in_config = {kGPIO_DigitalInput, 0};
gpio_pin_config_t out_config = {kGPIO_DigitalOutput, 0};
GPIO_PinInit(BOARD_NXPNCI_IRQ_PORT, BOARD_NXPNCI_IRQ_PIN, &in_config);
GPIO_PinInit(BOARD_NXPNCI_VEN_PORT, BOARD_NXPNCI_VEN_PIN, &out_config);
GPIO_PinInit(BOARD_NXPNCI_DWL_PORT, BOARD_NXPNCI_DWL_PIN, &out_config);
INTF_INIT();
return SUCCESS;
}
static Status tml_DeInit(void) {
GPIO_PortClear(BOARD_NXPNCI_VEN_PORT, 1U << BOARD_NXPNCI_VEN_PIN);
return SUCCESS;
}
static Status tml_Reset(void) {
/* Set DWL_REQ low for NCI protocol */
GPIO_PortClear(BOARD_NXPNCI_DWL_PORT, 1U << BOARD_NXPNCI_DWL_PIN);
GPIO_PortClear(BOARD_NXPNCI_VEN_PORT, 1U << BOARD_NXPNCI_VEN_PIN);
Sleep(10);
GPIO_PortSet(BOARD_NXPNCI_VEN_PORT, 1U << BOARD_NXPNCI_VEN_PIN);
Sleep(10);
return SUCCESS;
}
最后,修改主文件,使其使用 API 来初始化我们的电路板时钟和引脚: #include
#include
#include "app.h"
#include "board.h"
#include "pin_mux.h"
#include "fsl_debug_console.h"
extern void nfc_example (void);
int main(void)
{
BOARD_InitHardware();
#ifdef BOARD_NXPNCI_INTERFACE_I2C
PRINTF("\nRunning the NXP-NCI2.0 example (I2C interface)\n");
#else
PRINTF("\nRunning the NXP-NCI2.0 example (SPI interface)\n");
#endif
nfc_example();
}
测试示例。
此时我们已准备好使用 SPI 接口构建和刷新我们的示例,您可以通过按下蓝色的甲壳虫按钮继续编译和调试/刷新示例:
示例刷新后,打开 Teraterm 等串行终端,设置如下:
波特率115200.
数据:8 位
奇偶校验:奇偶校验:无。
停止位:1 位
无流量控制。
运行时,示例应向终端输出以下日志:
当标签被放置在天线附近时,示例应在终端中打印标签信息,如图所示:
NFC 控制器解决方案 NFC读取器库
View full article