手把手教你用C语言测试立创泰山派RK3566的SPI通信(附逻辑分析仪抓包分析)

张开发
2026/5/29 7:20:21 15 分钟阅读
手把手教你用C语言测试立创泰山派RK3566的SPI通信(附逻辑分析仪抓包分析)
手把手教你用C语言测试立创泰山派RK3566的SPI通信附逻辑分析仪抓包分析当你在立创泰山派RK3566开发板上成功添加了SPI设备节点/dev/spidev3.0后接下来的关键问题是如何验证SPI通信是否真正正常工作。本文将带你从零开始通过编写C语言测试程序结合逻辑分析仪进行波形抓取与分析彻底掌握SPI通信的验证方法。1. SPI通信测试环境搭建在开始编写测试程序前需要确保开发环境准备就绪。以下是必要的准备工作硬件连接立创泰山派RK3566开发板SPI从设备如Flash芯片或另一个开发板逻辑分析仪如Saleae Logic或DSView杜邦线若干软件依赖交叉编译工具链如aarch64-linux-gnu-gcc开发板上的Linux系统已启用SPI驱动逻辑分析仪配套软件小技巧在连接逻辑分析仪时建议使用短而粗的接地线这能显著减少信号噪声。同时确保逻辑分析仪的采样率至少是SPI时钟频率的4倍以上。2. 编写SPI测试程序下面是一个完整的SPI测试程序它能够设置SPI模式、频率并进行双向数据传输#include stdio.h #include stdlib.h #include stdint.h #include string.h #include fcntl.h #include unistd.h #include sys/ioctl.h #include linux/spi/spidev.h #define SPI_DEV_PATH /dev/spidev3.0 int spi_fd; struct spi_config { uint8_t mode; uint8_t bits; uint32_t speed; uint16_t delay; }; int spi_init(struct spi_config *config) { int ret; spi_fd open(SPI_DEV_PATH, O_RDWR); if (spi_fd 0) { perror(Failed to open SPI device); return -1; } ret ioctl(spi_fd, SPI_IOC_WR_MODE, config-mode); if (ret -1) { perror(Failed to set SPI mode); return -1; } ret ioctl(spi_fd, SPI_IOC_WR_BITS_PER_WORD, config-bits); if (ret -1) { perror(Failed to set bits per word); return -1; } ret ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, config-speed); if (ret -1) { perror(Failed to set SPI speed); return -1; } printf(SPI initialized with:\n); printf( Mode: 0x%x\n, config-mode); printf( Bits per word: %d\n, config-bits); printf( Speed: %d Hz\n, config-speed); return 0; } void spi_transfer(uint8_t *tx_buf, uint8_t *rx_buf, size_t len) { struct spi_ioc_transfer tr { .tx_buf (unsigned long)tx_buf, .rx_buf (unsigned long)rx_buf, .len len, .delay_usecs 0, .speed_hz 0, .bits_per_word 0, .cs_change 0, }; int ret ioctl(spi_fd, SPI_IOC_MESSAGE(1), tr); if (ret 1) { perror(SPI transfer failed); } } int main(int argc, char *argv[]) { struct spi_config config { .mode SPI_MODE_0, .bits 8, .speed 1000000, // 1MHz .delay 0, }; if (spi_init(config) 0) { return EXIT_FAILURE; } uint8_t tx_buf[] {0xAA, 0x55, 0x01, 0x02, 0x03}; uint8_t rx_buf[sizeof(tx_buf)] {0}; printf(Sending data:); for (int i 0; i sizeof(tx_buf); i) { printf( 0x%02X, tx_buf[i]); } printf(\n); spi_transfer(tx_buf, rx_buf, sizeof(tx_buf)); printf(Received data:); for (int i 0; i sizeof(rx_buf); i) { printf( 0x%02X, rx_buf[i]); } printf(\n); close(spi_fd); return EXIT_SUCCESS; }提示在实际项目中建议将SPI初始化代码封装成独立的函数库方便多个项目复用。3. 编译与运行测试程序使用交叉编译工具链编译上述程序aarch64-linux-gnu-gcc -o spi_test spi_test.c将编译好的程序上传到开发板并运行adb push spi_test /tmp/ adb shell chmod x /tmp/spi_test adb shell /tmp/spi_test程序运行后你应该能看到类似以下的输出SPI initialized with: Mode: 0x0 Bits per word: 8 Speed: 1000000 Hz Sending data: 0xAA 0x55 0x01 0x02 0x03 Received data: 0x00 0x00 0x00 0x00 0x00注意如果接收到的全是0可能是SPI从设备没有正确响应需要检查硬件连接和从设备配置。4. 逻辑分析仪抓包与分析逻辑分析仪是验证SPI通信的终极工具。以下是使用逻辑分析仪分析SPI通信的详细步骤连接探头SCLK连接到SPI时钟线MOSI连接到主设备输出线MISO连接到从设备输出线CS连接到片选线GND连接到开发板地线设置逻辑分析仪采样率至少设置为SPI时钟频率的4倍对于1MHz SPI建议5MHz以上触发方式设置为CS线下降沿触发协议解码启用SPI协议解码功能抓取波形启动逻辑分析仪捕获在开发板上运行SPI测试程序停止捕获并分析波形下表展示了SPI模式0CPOL0CPHA0下的信号特征信号线空闲状态数据采样边沿数据变化边沿SCLK低电平上升沿下降沿MOSI任意上升沿下降沿MISO任意上升沿下降沿CS高电平下降沿激活上升沿释放经验分享在实际调试中我发现逻辑分析仪的探头接地非常重要。如果发现信号质量不佳可以尝试缩短接地线长度或使用更粗的接地线。5. 常见问题排查在SPI通信调试过程中可能会遇到以下问题设备节点不存在检查设备树配置是否正确确认内核配置启用了SPI驱动使用ls /dev/spi*验证设备节点权限问题adb shell chmod 666 /dev/spidev3.0通信失败检查硬件连接是否正确确认SPI主从设备的模式CPOL/CPHA匹配降低SPI时钟频率测试逻辑分析仪无信号检查探头连接是否牢固确认逻辑分析仪接地良好尝试调整触发阈值6. 高级调试技巧对于更复杂的SPI调试场景可以尝试以下方法使用示波器测量信号完整性检查信号上升/下降时间观察是否存在过冲或振铃修改SPI参数// 尝试不同的SPI模式 config.mode SPI_MODE_0; // 可改为0/1/2/3 // 调整SPI时钟频率 config.speed 500000; // 降低频率测试添加调试打印// 在ioctl调用前后添加调试信息 printf(Setting SPI mode...\n); ret ioctl(spi_fd, SPI_IOC_WR_MODE, config.mode); printf(ioctl returned %d\n, ret);检查内核日志adb shell dmesg | grep spi通过本文介绍的方法你应该能够全面验证立创泰山派RK3566的SPI通信功能。记住SPI调试是一个需要耐心的过程结合软件测试和硬件分析工具能够快速定位并解决问题。

更多文章