LoopBack
该示例演示了通过中断方式使 SPI 主设备与从设备进行通信。
在通信过程中,主设备和从设备之间互相发送数据来进行通信,并通过中断方式进行数据接收。
当主设备与从设备接收的数据达到设定的阈值时,会触发 SPI_INT_RXF
中断,进行数据的接收。
在该示例中,SPI1 被配置为主设备,SPI0 被配置为从设备。
环境需求
该示例的环境需求,可参考 环境需求。
硬件连线
EVB 连接 P2_4(Master SCK)和 P3_0(Slave SCK),P2_5(Master MOSI)和 P3_1(Slave MOSI),P2_6(Master MISO)和 P3_2(Slave MISO),P2_7(Master CS)和 P3_3(Slave CS)。
配置选项
可配置如下宏修改引脚定义。
/* SPI1 MASTER pin define*/ #define SPI_MASTER_SCK_PIN P2_4 #define SPI_MASTER_MOSI_PIN P2_5 #define SPI_MASTER_MISO_PIN P2_6 #define SPI_MASTER_CS_PIN P2_7 /* SPI0 SLAVE pin define*/ #define SPI_SLAVE_SCK_PIN P3_0 #define SPI_SLAVE_MOSI_PIN P3_1 #define SPI_SLAVE_MISO_PIN P3_2 #define SPI_SLAVE_CS_PIN P3_3
编译和下载
该示例的编译和下载流程,可参考 编译和下载。
测试验证
EVB 启动后,在 Debug Analyzer 工具内观察 log。
Start spi loopback test!
主设备端向从设备端发送数据 {0, 1, …, 0x14}。从设备端接收到主设备端发来的数据,进入中断,打印从设备端接收数据长度,从设备端接收数据信息和主设备端发送的数据信息。
SPI SLAVE receieves 20 data. slave_rx_buf[0] = 0x00000001, master_tx_buf[0] = 0x00000001 slave_rx_buf[1] = 0x00000002, master_tx_buf[1] = 0x00000002 ... slave_rx_buf[19] = 0x00000014, master_tx_buf[19] = 0x00000014
从设备端向主设备端发送数据 {0x10, 0x11, …, 0x23}。主设备端接收到从设备端发送的信息,进入中断,打印主设备端接收数据长度,主设备端接收数据信息和从设备端发送的数据信息。
SPI MASTER receieves 20 data master_rx_buf[0] = 0x00000010, slave_tx_buf[0] = 0x00000010 master_rx_buf[1] = 0x00000011, slave_tx_buf[1] = 0x00000011 ... master_rx_buf[19] = 0x00000023, slave_tx_buf[19] = 0x00000023
代码介绍
该章节主要介绍示例中的初始化和相应功能实现的代码和流程说明。
源码路径
工程文件和源码路径如下:
工程路径:
sdk\samples\peripheral\spi\loopback\proj
源码路径:
sdk\samples\peripheral\spi\loopback\src
初始化
外设的初始化流程可参考 General Introduction 中的 初始化流程 部分。
调用
Pad_Config()
与Pinmux_Config()
,配置对应引脚的 PAD 和 PINMUX。将 SPI1 相关引脚 PINMUX 为主设备功能,将 SPI0 相关引脚 PINMUX 为从设备功能。void board_spi_master_init(void) { Pad_Config(SPI_MASTER_SCK_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_ENABLE, PAD_OUT_HIGH); Pad_Config(SPI_MASTER_MOSI_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_ENABLE, PAD_OUT_HIGH); Pad_Config(SPI_MASTER_MISO_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_ENABLE, PAD_OUT_HIGH); Pad_Config(SPI_MASTER_CS_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_ENABLE, PAD_OUT_HIGH); Pinmux_Deinit(SPI_MASTER_SCK_PIN); Pinmux_Deinit(SPI_MASTER_MOSI_PIN); Pinmux_Deinit(SPI_MASTER_MISO_PIN); Pinmux_Deinit(SPI_MASTER_CS_PIN); Pinmux_Config(SPI_MASTER_SCK_PIN, SPI1_CLK_MASTER); Pinmux_Config(SPI_MASTER_MOSI_PIN, SPI1_MO_MASTER); Pinmux_Config(SPI_MASTER_MISO_PIN, SPI1_MI_MASTER); Pinmux_Config(SPI_MASTER_CS_PIN, SPI1_CSN_0_MASTER); } void board_spi_slave_init(void) { Pad_Config(SPI_SLAVE_SCK_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_ENABLE, PAD_OUT_HIGH); Pad_Config(SPI_SLAVE_MOSI_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_ENABLE, PAD_OUT_HIGH); Pad_Config(SPI_SLAVE_MISO_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_ENABLE, PAD_OUT_HIGH); Pad_Config(SPI_SLAVE_CS_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP, PAD_OUT_ENABLE, PAD_OUT_HIGH); /* Must deinit P4_0~P4_3 before use SPI SLAVE!!! */ Pinmux_Deinit(P4_0); Pinmux_Deinit(P4_1); Pinmux_Deinit(P4_2); Pinmux_Deinit(P4_3); Pinmux_Deinit(SPI_SLAVE_SCK_PIN); Pinmux_Deinit(SPI_SLAVE_MOSI_PIN); Pinmux_Deinit(SPI_SLAVE_MISO_PIN); Pinmux_Deinit(SPI_SLAVE_CS_PIN); Pinmux_Config(SPI_SLAVE_SCK_PIN, SPI0_CLK_SLAVE); Pinmux_Config(SPI_SLAVE_MOSI_PIN, SPI0_SI_SLAVE); Pinmux_Config(SPI_SLAVE_MISO_PIN, SPI0_SO_SLAVE); Pinmux_Config(SPI_SLAVE_CS_PIN, SPI0_CSN_0_SLAVE); }
调用
RCC_PeriphClockCmd()
,开启 SPI 时钟。对 SPI 外设进行初始化:
定义
SPI_InitTypeDef
类型SPI_InitStruct
,调用SPI_StructInit()
将SPI_InitStruct
预填默认值。根据需求修改
SPI_InitStruct
参数,SPI0_SLAVE 与 SPI1 的初始化参数配置如下表。调用
SPI_Init()
,初始化 SPI 外设。
SPI Hardware Parameters |
Setting in the |
SPI1 |
SPI0_SLAVE |
---|---|---|---|
SPI Transfer Mode |
|||
SPI Data Size |
|||
Clock Mode - CPOL |
|||
Clock Mode - CPHA |
|||
Clock Prescaler |
100 |
100 |
|
Frame Format |
|||
RX Threshold |
|
|
调用
SPI_Cmd()
,使能相应 SPI 外设。
功能实现
在主设备调用
SPI_SendBuffer()
发送数据之前,从设备必须先调用SPI_SendBuffer()
将数据预先放入 FIFO 内。主设备开始发送回数据后,发起时钟信号,从设备随之将数据打出。主设备接收从设备发送的数据,接收数据达到阈值后,会触发
SPI_INT_RXF
中断,从设备收到数据时同理。在中断函数内,调用SPI_GetRxFIFOLen()
和SPI_ReceiveData()
接收数据。void SPI_Handler_MASTER(void) { if (SPI_GetINTStatus(SPI_MASTER, SPI_INT_RXF)) { SPI_INTConfig(SPI_MASTER, SPI_INT_RXF, DISABLE); SPI_ClearINTPendingBit(SPI_MASTER, SPI_INT_RXF); uint32_t master_rx_len = SPI_GetRxFIFOLen(SPI_MASTER); ... SPI_INTConfig(SPI_MASTER, SPI_INT_RXF, ENABLE); } } void SPI_Handler_SLAVE(void) { if (SPI_GetINTStatus(SPI_SLAVE, SPI_INT_RXF)) { SPI_INTConfig(SPI_SLAVE, SPI_INT_RXF, DISABLE); SPI_ClearINTPendingBit(SPI_SLAVE, SPI_INT_RXF); uint32_t slave_rx_len = SPI_GetRxFIFOLen(SPI_SLAVE); ... SPI_INTConfig(SPI_SLAVE, SPI_INT_RXF, ENABLE); } }