nrf52832 spi使用

一、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控制。

三、参考链接

青风电子社区

Leung_ManWah博客

posted @ 2023-01-07 09:02  wfagly  阅读(1181)  评论(0编辑  收藏  举报