一叮喳、SPI簡介
SPI(Serial Peripheral Interface) 協(xié)議是由摩托羅拉公司提出的通訊協(xié)議痒玩,即串行外圍設(shè)備接口恤浪,是一種高速全雙工的通信總線挨稿。它被廣泛地使用在 ADC、LCD 等設(shè)備與 MCU 間鸟妙,要求通訊速率較高的場合焦人。
芯片的管腳上只占用四根線。
MISO: 主器件數(shù)據(jù)輸出重父,從器件數(shù)據(jù)輸入花椭。
MOSI:主器件數(shù)據(jù)輸入,從器件數(shù)據(jù)輸出房午。
SCK: 時鐘信號矿辽,由主設(shè)備控制發(fā)出。
NSS(CS): 從設(shè)備選擇信號,由主設(shè)備控制袋倔。當NSS為低電平則選中從器件雕蔽。
二、API說明
以下 SPI 從機接口須包含頭文件 nrf_drv_spis.h宾娜。
#include "nrf_drv_spis.h"
2.1 NRF_DRV_SPIS_INSTANCE
功能 | 實例化一個SPI從機 |
---|---|
函數(shù)定義 | NRFX_SPIS_INSTANCE(id) |
參數(shù) | id:SPI從機實例編號 |
返回 | 攜帶有EasyDMA的SPI從機實例 |
2.2 nrf_drv_spis_init
功能 | SPI從機驅(qū)動初始化 |
---|---|
函數(shù)定義 | ret_code_t nrf_drv_spis_init(nrf_drv_spis_t const * const p_instance, nrf_drv_spis_config_t const * p_config, nrf_drv_spis_event_handler_t event_handler) |
參數(shù) | p_instance:SPI從機實例 p_config:配置參數(shù) event_handler:回調(diào)處理函數(shù) |
返回 | 0-成功批狐,或其他錯誤碼 |
2.3 nrf_drv_spis_buffers_set
功能 | 配置SPI從機發(fā)送和接收緩存區(qū) |
---|---|
函數(shù)定義 | nrfx_err_t nrfx_spis_buffers_set(nrfx_spis_t const * const p_instance, uint8_t const * p_tx_buffer, size_t tx_buffer_length, uint8_t * p_rx_buffer, size_t rx_buffer_length) |
參數(shù) | p_instance:SPI從機實例 p_tx_buffer:發(fā)送數(shù)據(jù)緩存區(qū) tx_buffer_length:發(fā)送數(shù)據(jù)長度 p_rx_buffer:接收數(shù)據(jù)緩存區(qū) rx_buffer_length:接收數(shù)據(jù)長度 |
返回 | 0-成功,或其他錯誤碼 |
三前塔、SDK配置
點擊 sdk_config.h 文件
選擇 Configuration Wizard
nRF_Drivers 中勾選SPIS相關(guān)選項
在 nRF_Drivers 中添加文件
nrfx_spis.c | 新版本 SPIS 兼容庫 | modules\nrfx\drivers\src |
---|---|---|
nrf_drv_spis.c | 老版本 SPIS 基礎(chǔ)庫 | integration\nrfx\legacy |
四贾陷、硬件連接
功能口 | 引腳 |
---|---|
MISO | 30 |
MOSI | 29 |
CLK | 26 |
CSN | 31 |
五、使用例子
打開SDK示例工程 examples\peripheral\spis
5.1 包含頭文件
#include "nrf_drv_spis.h"
5.2 實例化SPI從機
#define SPIS_INSTANCE 1 /**< SPIS instance index. */
static const nrf_drv_spis_t spis = NRF_DRV_SPIS_INSTANCE(SPIS_INSTANCE);/**< SPIS instance. */
5.3 定義SPI從機事件處理函數(shù)
spis_event_handler
接收事件處理函數(shù)嘱根,當SPI從機接收到數(shù)據(jù)時進入該函數(shù)髓废。
spis_xfer_done
接收數(shù)據(jù)標志,當SPI從機接收到數(shù)據(jù)時置1该抒,處理完接收數(shù)據(jù)后要清0慌洪。
static volatile bool spis_xfer_done; /**< Flag used to indicate that SPIS instance completed the transfer. */
/**
* @brief SPIS user event handler.
*
* @param event
*/
void spis_event_handler(nrf_drv_spis_event_t event)
{
if (event.evt_type == NRF_DRV_SPIS_XFER_DONE)
{
spis_xfer_done = true;
SEGGER_RTT_printf(0," Transfer completed. Received: %s\n",(uint32_t)m_rx_buf);
}
}
5.4 初始化SPI從機
#define APP_SPIS_CS_PIN 31
#define APP_SPIS_MISO_PIN 30
#define APP_SPIS_MOSI_PIN 29
#define APP_SPIS_SCK_PIN 26
nrf_drv_spis_config_t spis_config = NRF_DRV_SPIS_DEFAULT_CONFIG;
spis_config.csn_pin = APP_SPIS_CS_PIN;
spis_config.miso_pin = APP_SPIS_MISO_PIN;
spis_config.mosi_pin = APP_SPIS_MOSI_PIN;
spis_config.sck_pin = APP_SPIS_SCK_PIN;
APP_ERROR_CHECK(nrf_drv_spis_init(&spis, &spis_config, spis_event_handler));
5.5 配置發(fā)送和接收緩存區(qū)
#define TEST_STRING "Nordic"
static uint8_t m_tx_buf[] = TEST_STRING; /**< TX buffer. */
static uint8_t m_rx_buf[sizeof(TEST_STRING) + 1]; /**< RX buffer. */
static const uint8_t m_length = sizeof(m_tx_buf); /**< Transfer length. */
APP_ERROR_CHECK(nrf_drv_spis_buffers_set(&spis, m_tx_buf, m_length, m_rx_buf, m_length));
5.6 完整代碼
由于SDK原工程NRF_LOG打印不出來,這里我改成了使用SEGGER_RTT打印凑保。須包含頭文件 SEGGER_RTT.h
#include "sdk_config.h"
#include "nrf_drv_spis.h"
#include "nrf_gpio.h"
#include "nrf_delay.h"
#include "boards.h"
#include "app_error.h"
#include <string.h>
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"
#include "SEGGER_RTT.h"
#define SPIS_INSTANCE 1 /**< SPIS instance index. */
static const nrf_drv_spis_t spis = NRF_DRV_SPIS_INSTANCE(SPIS_INSTANCE);/**< SPIS instance. */
#define TEST_STRING "Nordic"
static uint8_t m_tx_buf[] = TEST_STRING; /**< TX buffer. */
static uint8_t m_rx_buf[sizeof(TEST_STRING) + 1]; /**< RX buffer. */
static const uint8_t m_length = sizeof(m_tx_buf); /**< Transfer length. */
static volatile bool spis_xfer_done; /**< Flag used to indicate that SPIS instance completed the transfer. */
/**
* @brief SPIS user event handler.
*
* @param event
*/
void spis_event_handler(nrf_drv_spis_event_t event)
{
if (event.evt_type == NRF_DRV_SPIS_XFER_DONE)
{
spis_xfer_done = true;
SEGGER_RTT_printf(0," Transfer completed. Received: %s\n",(uint32_t)m_rx_buf);
}
}
int main(void)
{
// Enable the constant latency sub power mode to minimize the time it takes
// for the SPIS peripheral to become active after the CSN line is asserted
// (when the CPU is in sleep mode).
NRF_POWER->TASKS_CONSTLAT = 1;
bsp_board_init(BSP_INIT_LEDS); // 板載LED燈初始化
APP_ERROR_CHECK(NRF_LOG_INIT(NULL));
NRF_LOG_DEFAULT_BACKENDS_INIT();
SEGGER_RTT_printf(0,"SPIS example\n");
nrf_drv_spis_config_t spis_config = NRF_DRV_SPIS_DEFAULT_CONFIG;
spis_config.csn_pin = APP_SPIS_CS_PIN;
spis_config.miso_pin = APP_SPIS_MISO_PIN;
spis_config.mosi_pin = APP_SPIS_MOSI_PIN;
spis_config.sck_pin = APP_SPIS_SCK_PIN;
APP_ERROR_CHECK(nrf_drv_spis_init(&spis, &spis_config, spis_event_handler));
while (1)
{
memset(m_rx_buf, 0, m_length);
spis_xfer_done = false;
APP_ERROR_CHECK(nrf_drv_spis_buffers_set(&spis, m_tx_buf, m_length, m_rx_buf, m_length));
while (!spis_xfer_done)
{
__WFE();
}
NRF_LOG_FLUSH();
bsp_board_led_invert(BSP_BOARD_LED_0); // LED燈置反
}
}
查看打痈缘:
使用SDK中SPI主機工程進行接收。
? 由 Leung 寫于 2021 年 5 月 18 日