HPM知识库 | [SPI] 单线双向半双工通信功能详解和实践

描述

 

前言

  • 在引脚资源紧张、但对传输带宽要求不高的嵌入式场景中,我们往往希望用更少的引脚完成 SPI 通信。

    先楫半导体旗下全系MCU内置的 SPI 控制器,除了标准的SPI全双工模式,还支持 单线双向半双工 工作模式——仅用 MOSI 这一根数据线,就能完成命令、地址、数据的发送与接收。

参考示例

本文基于 先楫 HPM SDK 中的以下官方示例编写,可直接参考运行:

示例路径说明
samples/drivers/spi/dma/master/SPI Master 端,DMA 传输,mosi_bidir 使能
samples/drivers/spi/dma/slave/SPI Slave 端,DMA 传输,mosi_bidir 使能

两个示例需配合使用(一块板子跑 Master,另一块跑 Slave),通过 mosi_bidir = true 开启单线双向半双工通信。


 

实现原理

硬件层面

SPI 控制器内部通过一个 mosi_bidir 控制位将 MOSI 引脚配置为双向 I/O:

  • 写阶段:MOSI 作为输出,驱动数据到总线上。
  • 读阶段:MOSI 切换为输入,从总线上采样数据。
  • pinmux上只需要初始化MOSI即可

传输模式

trans_mode 决定了一次 SPI 帧中读写阶段的顺序。SDK 支持的模式包括:

  • spi_trans_write_only:纯写
  • spi_trans_read_only :纯读
  • spi_trans_write_read :先写后读
  • spi_trans_read_write :先读后写
  • spi_trans_write_dummy_read :先写 → Dummy 周期 → 后读
  • spi_trans_read_dummy_write :先读 → Dummy 周期 → 后写

单线半双工模式下,以上模式均可使用。示例中改使用为 spi_trans_write_read / spi_trans_read_write,读写方向切换由硬件自动完成。


 

代码配置

关键参数:mosi_bidir

mosi_bidir 默认为 false(关闭),即标准 4 线全双工模式。要开启 MOSI 单线双向半双工,只需将其设为 true:

// 默认为 false,需显式开启
format_config.common_config.mosi_bidir = true;

Master 端(先写后读)

// 文件:samples/drivers/spi/dma/master/src/spi.c

spi_master_get_default_format_config(&format_config);
format_config.common_config.data_len_in_bits = 8;      // 8 位数据
format_config.common_config.mosi_bidir = true;          // ★ MOSI 双向
format_config.common_config.data_merge = false;
format_config.common_config.mode = spi_master_mode;
format_config.common_config.cpol = spi_sclk_high_idle;
format_config.common_config.cpha = spi_sclk_sampling_even_clk_edges;
spi_format_init(TEST_SPI, &format_config);

spi_master_get_default_control_config(&control_config);
control_config.common_config.trans_mode = spi_trans_write_read;
// 先写数据 → 读取从机数据(读写之间硬件自动插入方向切换周期)
control_config.common_config.data_phase_fmt = spi_single_io_mode;
control_config.common_config.tx_dma_enable = true;
control_config.common_config.rx_dma_enable = true;

Slave 端(先读后写)

// 文件:samples/drivers/spi/dma/slave/src/spi.c

spi_slave_get_default_format_config(&format_config);
format_config.common_config.data_len_in_bits = 8;
format_config.common_config.mosi_bidir = true;          // ★ MOSI 双向(同样设置)
format_config.common_config.data_merge = false;
format_config.common_config.mode = spi_slave_mode;
format_config.common_config.cpol = spi_sclk_high_idle;
format_config.common_config.cpha = spi_sclk_sampling_even_clk_edges;
spi_format_init(TEST_SPI, &format_config);

spi_slave_get_default_control_config(&control_config);
control_config.common_config.trans_mode = spi_trans_read_write;
// 先接收数据 → 发送数据(读写之间硬件自动插入方向切换周期)
control_config.common_config.data_phase_fmt = spi_single_io_mode;
control_config.common_config.tx_dma_enable = true;
control_config.common_config.rx_dma_enable = true;

注意

  • Master 和 Slave 使用相反的传输模式(一个 Write→Read,另一个 Read→Write),才能完成双向数据交换。


 

实验验证

测试环境

项目规格
开发板HPM6200EVK/HPM6750EVK2,主从机角色随意
数据长度128 字节
时钟极性spi_sclk_high_idle
时钟相位spi_sclk_sampling_even_clk_edges
Dummy 周期无(硬件自动切换方向)
传输方式DMA(RX + TX)

逻辑分析仪波形

半双工

串口输出结果

  • 收发 128 字节 完全一致,错误计数为 0,验证了单线双向半双工通信的正确性。

适用场景 & 注意事项

适用场景

  • 引脚数受限的传感器互联
  • 需要减少连接器 pin 数的板间通信
  • 半双工协议兼容
  • 一对多星型拓扑(每个从设备仅用 3 根线:SCLK + MOSI + CS)

注意事项

注意点说明
不能同时读写半双工模式下,同一时刻数据只在一个方向传输
方向切换由硬件自动完成
 
主从模式互补Master 和 Slave 的 trans_mode 必须互补(写→读 vs 读→写)

总结

先楫 SPI 的 mosi_bidir 单线双向半双工功能,可以在不牺牲 SPI 协议灵活性的前提下,将引脚数从 4 根减少到 3 根(SCLK + MOSI + CS),对于引脚资源紧张的应用非常有价值。

配合 DMA 搬运,即使是单线模式也能获得不错的整体吞吐率。只需一行配置 mosi_bidir = true,就能让 MOSI 同时扮演"发球员"和"接球员"的角色,实现高效、可靠的双向通信。

 

 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分