仅能调试STM32主控板,如何验证与EVB-LAN9252-SPI从机的SPI通信?
SPI通信调试问题(STM32F429 Nucleo 主机 + EVB-LAN9252-SPI 从机)
我使用STM32F429ZI Nucleo板作为SPI主机(通过UART辅助调试),EVB-LAN9252-SPI板作为SPI从机,无法对从机端进行调试或检测,需要验证SPI通信是否正常。
第一阶段测试(SPI1主机 + SPI4模拟从机)
我编写了以下测试代码验证SPI工作状态:
while (k < 32) { HAL_UART_Transmit(&huart4, &SPI1_Buffer_Tx[k], 1, 100); k++; } k = 0; while (k < 32) { HAL_GPIO_WritePin(GPIOE, GPIO_PIN_9, GPIO_PIN_RESET); // 硬件NSS引脚 HAL_SPI_Transmit(&hspi1, &SPI1_Buffer_Tx[k], 1, 100); HAL_SPI_Receive(&hspi4, &SPI4_Buffer_Rx[k], 1, 100); HAL_GPIO_WritePin(GPIOE, GPIO_PIN_9, GPIO_PIN_SET); k++; } k = 0; while (k < 32) { HAL_UART_Transmit(&huart4, &SPI1_Buffer_Tx[k], 1, 100); k++; } k = 0; while (k < 32) { HAL_UART_Transmit(&huart4, &SPI4_Buffer_Rx[k], 1, 100); k++; }
UART输出结果
abcdefghijklmnopqrstuvwxyzABCDEF // 原始发送缓冲区内容 bcdefghijklmnopqrstuvwxyzABCDEF // 接收缓冲区内容
这个现象可能是因为通过HAL_SPI_Receive(&hspi4, &SPI4_Buffer_Rx[k], 1, 100);能在模拟从机侧读取到数据。
原项目测试(SPI1主机 + LAN9252从机)
我最初假设主机发送的数据会在从机端循环回传,因此编写了以下代码:
while (k < 32) { HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET); HAL_SPI_Transmit(&hspi1, &SPI1_Buffer_Tx[k], 1, 100); HAL_SPI_Receive(&hspi1, &SPI1_Buffer_Rx[k], 1, 100); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET); k++; }
但主机接收到的是32个0xFF,我有以下疑问:
- 数据是否真的会在从机端循环回传,是否是我的操作有误?
- 数据似乎已正确发送,但从机未被命令回传数据,导致无法收到有效数据?
2-1. 若是如此,如何确认从机已正确接收数据?
2-2. 仅能调试主机板时,如何命令从机回传有效数据?
问题分析与解答
1. 从机自动回传数据的误解
SPI是全双工同步通信,但从机不会自动回传主机发送的数据——除非从机固件被设计成将接收的数据立刻放入发送寄存器。你之前用SPI4模拟从机时收到偏移1位的数据,是SPI通信的时序特性导致:主机发送时钟时,从机必须同步输出数据,若从机未提前准备好发送数据,就会输出上一次的残留数据或默认电平,你看到的偏移是因为收发的时序延迟。
2. 收到全0xFF的核心原因
你收到全0xFF,说明从机在主机接收阶段没有输出有效数据,本质原因是:
LAN9252是SPI接口的以太网控制器,它的通信遵循特定的寄存器读写协议,不会随便回传主机发送的数据,必须先发送对应的读写命令+寄存器地址,才会返回有效数据。
2-1. 确认从机已接收数据的方法
在无法调试从机的情况下,可通过以下方式验证:
- 抓取SPI硬件信号:用示波器检测SCK、MOSI、NSS的电平、时钟频率、相位/极性,确认是否和LAN9252 datasheet要求的一致(通常为SPI Mode 0或Mode 3)。
- 读取从机固定寄存器:比如LAN9252的芯片ID寄存器,按手册要求发送读命令,若能读到预期的ID值,说明通信链路正常,从机已正确接收命令。
2-2. 命令从机回传数据的操作方法
必须严格遵循LAN9252的SPI通信协议:
- 查阅LAN9252 datasheet,确认SPI帧格式(通常是
读写位+寄存器地址+数据的结构)。 - 构造符合要求的命令帧,比如读取芯片ID的命令(具体以手册为准)。
- 使用
HAL_SPI_TransmitReceive()替代分开的Transmit和Receive,因为SPI是同步传输,一次操作同时完成收发,更符合协议要求。示例代码:
uint8_t cmd[3] = {0x00, 0x00, 0x00}; // 示例:读命令+寄存器地址(需按手册修改) uint8_t rx_data[2]; HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET); // 发送3字节命令,同时接收2字节芯片ID HAL_SPI_TransmitReceive(&hspi1, cmd, rx_data, sizeof(cmd), 100); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET); // 通过UART输出rx_data,验证是否符合预期
内容的提问来源于stack exchange,提问作者Junseok Oh
相关产品推荐
相关产品推荐

