目录
概述
1 SPI相关的寄存器
1.1 SPI的框架结构
1.2 功能描述
1.3 SPI Master模式引脚配置
1.4 SPI Master模式下的时序
2 SPI相关的寄存器
2.1 Instances
2.2 详细寄存器定义
2.3 SPI master interface特性
3 Zephyr 平台下SPI功能时序(寄存器)
3.1 寄存器的文件地址
3.2 SPI驱动实现
3.3 源代码
概述
本文详细介绍了nRF52832芯片的SPI接口寄存器配置与功能实现。主要内容包括:1)SPI主设备框架结构,重点说明双缓冲TXD/RXD寄存器的工作机制;2)SPI主模式下的引脚配置(SCK/MOSI/MISO)与时序控制要求;3)给出了完整的寄存器定义表,涵盖使能、引脚选择、频率配置等关键寄存器;4)基于Zephyr平台提供了SPI驱动实现方案,包含初始化代码、数据传输函数及芯片选择控制逻辑,并附有完整的源代码示例。特别强调SPI主设备不直接支持片选功能,需通过GPIO独立控制从设备选择。
1 SPI相关的寄存器
1.1 SPI的框架结构
SPI 主设备提供了一个简单的 CPU 接口,其中包括用于发送数据的 TXD 寄存器和用于接收数据的 RXD 寄存器。
1.2 功能描述
TXD和RXD寄存器是双缓冲的,以便在一定程度上允许不间断的数据流进出SPI主机。SPI主控不直接实现对芯片选择的支持。因此,CPU必须使用可用的 gpio来选择正确的从站,并独立于SPI主站进行控制。SPI主机支持 SPI模式0 ~ 3。
SPI 工作列表
1.3 SPI Master模式引脚配置
与SPI主控相关联的不同信号SCK、MOSI和MISO被映射到物理引脚。该映射分别根据PSELSCK、PSELMOSI和PSELMISO 寄存器中指定的配置。如果在这些寄存器中指定了0xFFFFFFFF的值,则相关的SPI 主信号不会连接到任何物理引脚。
PSELSCK、PSELMOSI和PSELMISO寄存器 及其配置仅在SPI主设备启用时使用,并且仅在 设备处于ON模式时保留。
1.4 SPI Master模式下的时序
SPI主事务通过将第一个字节写入 TXD寄存器来启动,该字节将由SPI主服务器传输。由于发送器是双缓冲的,第二个字节可以在第一个字节 之后立即写入TXD寄存器。然后SPI主机将按照写入TXD寄存器的顺序发送这些字节。
SPI主控将传入的字节移动到RXD寄存器后,随着SCK时钟 在字节的最后一位周期的短暂延迟。这也意味着READY事件将相应地延迟,参见下图的SPI主事务。因此,务必始终清除 READY事件,即使没有使用RXD寄存器和正在接收的数据。
2 SPI相关的寄存器
2.1 Instances
nRF52832总共有3个SPI接口可供使用
和SPI相关的寄存器总表
2.2 详细寄存器定义
1)Enable interrupt
2) Disable interrupt
3) Enable SPI
4) PSELSCK
5) PSELMOSI
6) PSELMISO
7) RXD
8) TXD
9) FREQUENCY
10) CONFIG
2.3 SPI master interface特性
1) SPI master interface的电器特性
2) SPI master interface的时序
3 Zephyr 平台下SPI功能时序(寄存器)
Zephyr OS下定义的SPI寄存器数据结构
3.1 寄存器的文件地址
D:\ncs\v2.9.0\modules\hal\nordic\nrfx\hal\nrf_spi.h
D:\ncs\v2.9.0\modules\hal\nordic\nrfx\drivers\include\nrfx_spim.h
使用寄存器时,必须在.c文件中引用如下两个头文件:
#include <hal/nrf_spi.h>
#include <nrfx_spim.h>
3.2 SPI驱动实现
1) 初始化SPI接口
2) SPI相关的接口配置
3)数据传输函数
4)芯片使能引脚
3.3 源代码
#include <zephyr/kernel.h>
#include <hal/nrf_spi.h>
#include <nrfx_spim.h>/*psels = <NRF_PSEL(SPIS_SCK, 0, 27)>,<NRF_PSEL(SPIS_MISO, 0, 28)>,<NRF_PSEL(SPIS_MOSI, 0, 26)>,<NRF_PSEL(SPIS_CSN, 0, 24)>;
*/#define SPI_SCK_PIN 27
#define SPI_MOSI_PIN 26
#define SPI_MISO_PIN 28#define SPI_OBJ NRF_SPI2Flash_Info flash_Info_Obj;void spi_init( void )
{// 1 enable POWER dk_set_led(CTRL_FLASH_POWER_PIN, 1);// 1 选择SPI引脚SPI_OBJ->PSEL.SCK = SPI_SCK_PIN;SPI_OBJ->PSEL.MOSI = SPI_MOSI_PIN;SPI_OBJ->PSEL.MISO = SPI_MISO_PIN;// 2. 配置 SPI 模式 (模式0)NRF_SPI0->CONFIG = (SPI_CONFIG_CPHA_Leading << SPI_CONFIG_CPHA_Pos) |(SPI_CONFIG_CPOL_ActiveHigh << SPI_CONFIG_CPOL_Pos);SPI_OBJ->FREQUENCY = NRF_SPI_FREQ_4M; // 4 MHz// 使能SPISPI_OBJ->ENABLE = SPI_ENABLE_ENABLE_Enabled << SPI_ENABLE_ENABLE_Pos;
}u8 spi_transfer_byte( u8 data )
{SPI_OBJ->EVENTS_READY = 0; // 清除就绪事件// 发送数据SPI_OBJ->TXD = data;// 等待发送完成while(!SPI_OBJ->EVENTS_READY);// 清除事件标志SPI_OBJ->EVENTS_READY = 0;// 读取接收到的数据(如果需要)return (u8)SPI_OBJ->RXD; // 返回接收数据
}/**** @brief select the flash chip * * @details en = true, select the chip* en = false, release the chip* * @ingroup spi flash driver */
void spi_cs_ctrl( bool en )
{if( en )dk_set_led(CTRL_FLASH_PIN, 0); // cs is enable elsedk_set_led(CTRL_FLASH_PIN, 1);
}