一、nrf52 spi简介
SPI(Serial Peripheral Interface) 称为串行外设接口。 SPI 总线系统是一种同步串行外设接口,它可以使 MCU 与各种外围设备以串行方式进行通信以交换信息。SPI 接口可以连接很多类型的外围设备, 比如包括 FLASHRAM、 网络控制器、 LCD 显示驱动器、 A/D 转换器和 MCU 等具有 SPI 接口的设备 。
1、总线接口
SPI管脚 | 方向 | 描述 |
---|---|---|
MISO | 主机输入/从机输出 | 主机读取从机数据的通道 |
MOSI | 主机输出/从机输入 | 主机发送数据到从机的通道 |
SCK | 主机输出 | 主机提供的总线时钟信号 |
CS | 主机输出 | 主机选择从机设备的片选信号 |
SPI总线可以挂载多个设备,主机通过CS从机选择端口进行从设备的区分,nrf52832也是如此,SPI主机通过多个io去分别连接不同SPI从机的CS端口,使用哪个从机设备把它对应的CS IO口拉低即可。拉高表示释放该器件对SPI总线的占用。
2、SPI数据传输方式
-
时钟极性控制为CPOL:SPI总线空闲时,时钟线SCK的电平状态称为时钟极性。
CPOL = 1:SPI总线空闲时,时钟线SCK的电平状态为低电平;
CPOL = 0:SPI总线空闲时,时钟线SCK的电平状态为高电平;
-
时钟相位控制位 CPHA: 决定了 SPI 总线在时钟先 SCK 的第几个跳变沿开始采样数据的。
CPHA=0: SPI 总线在时钟先 SCK 的第 1 个跳变沿开始采样数据;
CPHA=1: SPI 总线在时钟先 SCK 的第 2 个跳变沿开始采样数据;
所以它形成如下四种数据传输模式:
二、硬件spi
1、sdk_config.h配置
2、添加spi驱动文件
nrfx_spi.c 新版本SPI兼容库
nrfx_spim.c 新版本SPIM兼容库
nrf_drv_spi.c 老版本SPI基础库
3、驱动文件
per_spi.c
/**
******************************************************************************
* @file per_spi.c
* @author wfagly
* @brief
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "per_spi.h"
#include "nrf_drv_spi.h"
#include "nrfx_spim.h"
#define SPI_MISO_PIN 29
#define SPI_MOSI_PIN 28
#define SPI_SCLK_PIN 27
#define SPI_CS_PIN 26
static nrf_drv_spi_t per_spi = NRF_DRV_SPI_INSTANCE(1); /**< SPI instance. */
static void spi1_event_handler(nrf_drv_spi_evt_t const *p_event,
void *p_context)
{
spi_xfer_done = true;
if (p_event->type == NRF_DRV_SPI_EVENT_DONE)
{
}
}
void per_spi_init(void)
{
nrf_drv_spi_config_t spi1_Config = NRF_DRV_SPI_DEFAULT_CONFIG;
spi1_Config.mosi_pin = SPI_MOSI_PIN;
spi1_Config.sck_pin = SPI_SCLK_PIN;
spi1_Config.miso_pin = SPI_MISO_PIN;
spi1_Config.ss_pin = SPI_CS_PIN;
spi1_Config.mode = NRF_DRV_SPI_MODE_0;
spi1_Config.frequency = NRF_DRV_SPI_FREQ_4M; // MAX 8M
spi1_Config.irq_priority = SPI_DEFAULT_CONFIG_IRQ_PRIORITY;
APP_ERROR_CHECK(nrf_drv_spi_init(&per_spi, &spi1_Config, spi1_event_handler, NULL));
}
void per_spi_uninit(void)
{
nrf_drv_spi_uninit(&per_spi);
nrf_gpio_cfg_default(SPI_MOSI_PIN);
nrf_gpio_cfg_default(SPI_SCLK_PIN);
nrf_gpio_cfg_default(SPI_MISO_PIN);
nrf_gpio_cfg_default(SPI_CS_PIN);
}
bool spi1_WriteBuff(const uint8_t *buff, uint8_t len)
{
ret_code_t reErr = 0;
spi_xfer_done = false;
reErr = nrf_drv_spi_transfer(&per_spi, buff, len, m_rx_buf, len);
APP_ERROR_CHECK(reErr);
while (!spi_xfer_done)
;
if (NRF_SUCCESS != reErr)
{
return false;
}
return true;
}
bool spi1_ReadBuff(const uint8_t *buff, uint8_t len, uint8_t *destination, uint8_t readLen)
{
ret_code_t reErr = 0;
spi_xfer_done = false;
reErr = nrf_drv_spi_transfer(&per_spi, buff, len, destination, readLen);
APP_ERROR_CHECK(reErr);
while (!spi_xfer_done)
;
if (NRF_SUCCESS != reErr)
{
return false;
}
return true;
}
/************************ (C) COPYRIGHT ... *****END OF FILE****/
per_spi.h
/**
******************************************************************************
* @file per_spi.h
* @author wfagly
* @brief
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef PER_SPI_H
#define PER_SPI_H
/* Includes ------------------------------------------------------------------*/
#ifdef __cplusplus
extern "C"
{
#endif
/**
* @brief spi init.
*
*/
void per_spi_init(void);
/**
* @brief spi uninit.
*
*/
void per_spi_uninit(void);
/**
* @brief spi write func.
*
* @param buff write data.
* @param len data len.
* @return true write done.
* @return false write fail.
*/
bool spi1_WriteBuff(const uint8_t *buff, uint8_t len);
/**
* @brief spi read func.
*
* @param buff write data.
* @param len write data len.
* @param destination read data.
* @param readLen read data len.
* @return true read done.
* @return false read fail.
*/
bool spi1_ReadBuff(const uint8_t *buff, uint8_t len, uint8_t *destination, uint8_t readLen);
#ifdef __cplusplus
}
#endif
#endif /* PER_SPI_H */
/************************ (C) COPYRIGHT ... *****END OF FILE****/
注意:NRF的SPI片选引脚CSN只支持低电平活动。如果该信号应该是高的,应由外部控制,即单独写个GPIO控制。