LoopBack
该示例演示使用 SPI 自发自收的方式进行数据通信。
将SPI1配置为Master来使用,SPI0配置为Slave来使用,Master和Slave之间互相发送数据来进行通信。
该示例使用中断的方式进行数据接收。当数据传输完成时,触发 SPI_INT_RXF
中断,进行数据的接收。
环境需求
该示例支持以下开发套件:
Hardware Platforms |
Board Name |
---|---|
RTL87x2G HDK |
RTL87x2G EVB |
更多信息请参考快速入门。
硬件连线
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)。
编译和下载
该示例的工程路径如下:
Project file: samples\peripheral\spi\loopback\proj\rtl87x2g\mdk
Project file: samples\peripheral\spi\loopback\proj\rtl87x2g\gcc
请按照以下步骤操作构建并运行该示例:
打开工程文件。
按照 快速入门 中 编译APP Image 给出的步骤构建目标文件。
编译成功后,在路径
mdk\bin
或gcc\bin
下会生成 app binapp_MP_xxx.bin
文件。按下复位按键,开始运行。
测试验证
EVB启动后,在Debug Analyzer工具内观察log。
Start spi loopback test!
Slave 端接收到Master端发来的数据,进入中断,打印Slave端接收数据长度,Slave端接收数据信息和Master端发送的数据信息。
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
Master端接收到Slave端发送的信息,进入中断,打印Master端接收数据长度,Master端接收数据信息和Slave端发送的数据信息、
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
该工程的工程文件代码结构如下:
└── Project: loopback
└── secure_only_app
└── Device includes startup code
├── startup_rtl.c
└── system_rtl.c
├── CMSIS includes CMSIS header files
├── CMSE Library Non-secure callable lib
├── Lib includes all binary symbol files that user application is built on
└── rtl87x2g_io.lib
├── Peripheral includes all peripheral drivers and module code used by the application
├── rtl_rcc.c
├── rtl_pinmux.c
├── rtl_nvic.c
└── rtl_spi.c
└── APP includes the ble_peripheral user application implementation
├── main_ns.c
├── spi_flash.c includes a wrapper implementation of functions to communicate with external flash
└── io_spi.c
初始化
初始化流程包括了 board_spi_slave_init
, board_spi_master_init
, driver_spi_slave_init
和 driver_spi_master_init
board_spi_slave_init
中包含了对SPI0_SLAVE的PAD与PINMUX设置:
配置PAD:设置引脚、PINMUX模式、PowerOn、内部上拉。
配置PINMUX:分配引脚分别为SPI0_CLK_SLAVE、SPI0_SI_SLAVE、SPI0_SO_SLAVE、SPI0_CSN_0_SLAVE功能。
board_spi_master_init
中包含了对SPI1的PAD与PINMUX设置:
配置PAD:参考
board_spi_slave_init
中PAD设置。配置PINMUX:分配引脚分别为SPI1_CLK_MASTER、SPI1_MO_MASTER、SPI1_MI_MASTER、SPI1_CSN_0_MASTER功能。
driver_spi_slave_init
包含了对SPI0_SLAVE外设的初始化:
使能PCC时钟源。
设置传输模式为全双工模式。
配置传输数据宽度
配置串行时钟的稳态悬空高,数据捕获于第二个时钟沿。
配置接收数据长度阈值为
SEND_LENGTH - 1
。设置数据传输格式。
使能SPI0_SLAVE。
配置接收缓冲区满中断
SPI_INT_RXF
。准备Slave端需要发送的数据,执行
SPI_SendBuffer()
函数,将数据存放至FIFO中。
RCC_PeriphClockCmd(APBPeriph_SPI_SLAVE, APBPeriph_SPI_CLOCK_SLAVE, ENABLE);
...
SPI_InitStruct.SPI_Direction = SPI_Direction_FullDuplex;
SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;
SPI_InitStruct.SPI_CPHA = SPI_CPHA_2Edge;
/* SPI_Direction_EEPROM mode read data lenth. */
SPI_InitStruct.SPI_RxThresholdLevel = SEND_LENGTH - 1;/* Flash id lenth = 3*/
/* cause SPI_INT_RXF interrupt if data length in receive FIFO >= SPI_RxThresholdLevel + 1*/
SPI_InitStruct.SPI_FrameFormat = SPI_Frame_Motorola;
SPI_Init(SPI_SLAVE, &SPI_InitStruct);
SPI_Cmd(SPI_SLAVE, ENABLE);
SPI_INTConfig(SPI_SLAVE, SPI_INT_RXF, ENABLE);
...
for (uint32_t i = 0; i < SEND_LENGTH; i++)
{
slave_tx_buf[i] = 0x10 + i;
}
SPI_SendBuffer(SPI_SLAVE, slave_tx_buf, SEND_LENGTH);
driver_spi_master_init
包含了对SPI1外设的初始化:
基本初始化设置参考
driver_spi_slave_init
。使能SPI MASTER。
准备Master端需要发送的数据,执行
SPI_SendBuffer()
函数,将数据存放至FIFO中。
备注
master端发起通信之前,slave端必须将数据准备好放至FIFO内。
功能实现
Master端向slave端发送数据。slave端收到clock信号后,将FIFO中的数据发送至master端。
Master端收到slave发来的数据后,触发
SPI_INT_RXF
中断,进入中断函数SPI_Handler_MASTER
。清除SPI_INT_RXF中断挂起位。
执行
SPI_GetRxFIFOLen()
获取FIFO中数据长度。执行
SPI_ReceiveData()
接收slave端发送的数据并打印,比较接收到的数据和发送的数据是否相同。
SPI_INTConfig(SPI_MASTER, SPI_INT_RXF, DISABLE);
SPI_ClearINTPendingBit(SPI_MASTER, SPI_INT_RXF);
uint32_t master_rx_len = SPI_GetRxFIFOLen(SPI_MASTER);
for (uint32_t i = 0; i < master_rx_len; i++)
{
master_rx_buf[i] = SPI_ReceiveData(SPI_MASTER);
...
}
SPI_INTConfig(SPI_MASTER, SPI_INT_RXF, ENABLE);
Slave端收到master端发送的数据后,触发
SPI_INT_RXF
中断,进入中断函数SPI_Handler_SLAVE
。清除SPI_INT_RXF中断挂起位。
执行
SPI_GetRxFIFOLen()
获取FIFO中数据长度。执行
SPI_ReceiveData()
接收master端发送的数据并打印,比较接收到的数据和发送的数据是否相同。
SPI_INTConfig(SPI_MASTER, SPI_INT_RXF, DISABLE);
SPI_ClearINTPendingBit(SPI_MASTER, SPI_INT_RXF);
uint32_t master_rx_len = SPI_GetRxFIFOLen(SPI_MASTER);
for (uint32_t i = 0; i < master_rx_len; i++)
{
master_rx_buf[i] = SPI_ReceiveData(SPI_MASTER);
...
}
SPI_INTConfig(SPI_MASTER, SPI_INT_RXF, ENABLE);