一、硬件連接
功能口 | 引腳 |
---|---|
MISO | 17 |
MOSI | 18 |
CLK | 20 |
CSN | 19 |
二、移植文件
注意:以下出現缺失common.h文件錯誤,去除即可。uint8改爲uint8_t或unsigned char或自己宏定義
鏈接:https://pan.baidu.com/s/1AP3VuZz2v5gN47zDDTqCVA 提取碼:d84r
將 board_spi.c 和 board_spi.h 兩個文件加入工程的Application文件夾下
2.1 board_spi.c
/*********************************************************************
* INCLUDES
*/
#include "nrf_drv_spi.h"
#include "nrf_gpio.h"
#include "app_error.h"
#include "board_spi.h"
#include "common.h"
static void spiCallbackFunc(nrf_drv_spi_evt_t const *pEvent, void *arg);
/*********************************************************************
* LOCAL VARIABLES
*/
static volatile bool s_transferOk = true; // SPI數據傳輸完成標誌
static const nrf_drv_spi_t s_spiHandle = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE); // SPI instance
/*********************************************************************
* PUBLIC FUNCTIONS
*/
/**
@brief SPI的初始化函數
@param 無
@return 無
*/
void SPI_Init(void)
{
ret_code_t errCode;
nrf_drv_spi_config_t spiConfig = NRF_DRV_SPI_DEFAULT_CONFIG; // 使用SPI默認配置
// 配置SPI端口,注意CSN不要在這設置,另外用GPIO口控制
spiConfig.miso_pin = BOARD_SPI0_MISO_IO;
spiConfig.mosi_pin = BOARD_SPI0_MOSI_IO;
spiConfig.sck_pin = BOARD_SPI0_CLK_IO;
spiConfig.mode = NRF_DRV_SPI_MODE_0;
spiConfig.frequency = SPI_FREQUENCY_FREQUENCY_K250;
spiConfig.irq_priority = 4; // 在定時器中使用優先級需小於6
errCode = nrf_drv_spi_init(&s_spiHandle, &spiConfig, spiCallbackFunc, NULL);
APP_ERROR_CHECK(errCode);
nrf_gpio_cfg_output(BOARD_SPI0_CSN_IO);
}
/**
@brief SPI片選信號設置
@param pinState -[in] 引腳狀態
@return 無
*/
void SPI_CsnSet(bool pinState)
{
if(pinState == BOARD_SPI_CS_OFF)
{
nrf_gpio_pin_write(BOARD_SPI0_CSN_IO, 1);
}
else if(pinState == BOARD_SPI_CS_ON)
{
nrf_gpio_pin_write(BOARD_SPI0_CSN_IO, 0);
}
}
/**
@brief SPI讀出寫入數據
@param pWriteData -[in] 寫入數據
@param pReadData -[out] 讀出數據
@param writeDataLen -[in] 寫入數據長度
@return 無
*/
void SPI_ReadWriteData(uint8 *pWriteData, uint8 *pReadData, uint8 writeDataLen)
{
s_transferOk = false;
APP_ERROR_CHECK(nrf_drv_spi_transfer(&s_spiHandle, pWriteData, writeDataLen, pReadData, writeDataLen));
while(!s_transferOk)
{
__WFE();
} // Error in SPI or transfer already in progress.
}
/**
@brief 開啓SPI,與初始化區別:沒有初始化CS引腳
@param 無
@return 無
*/
void SPI_Enable(void)
{
ret_code_t errCode;
nrf_drv_spi_config_t spiConfig = NRF_DRV_SPI_DEFAULT_CONFIG; // 使用SPI默認配置
// 配置SPI端口,注意CSN不要在這設置,另外用GPIO口控制
spiConfig.miso_pin = BOARD_SPI0_MISO_IO;
spiConfig.mosi_pin = BOARD_SPI0_MOSI_IO;
spiConfig.sck_pin = BOARD_SPI0_CLK_IO;
spiConfig.mode = NRF_DRV_SPI_MODE_0;
spiConfig.frequency = SPI_FREQUENCY_FREQUENCY_M8;
spiConfig.irq_priority = 4; // 在定時器中使用優先級需小於6
errCode = nrf_drv_spi_init(&s_spiHandle, &spiConfig, spiCallbackFunc, NULL);
APP_ERROR_CHECK(errCode);
}
/**
@brief 禁用SPI
@param 無
@return 無
*/
void SPI_Disable(void)
{
nrf_drv_spi_uninit(&s_spiHandle);
}
/*********************************************************************
* LOCAL FUNCTIONS
*/
/**
@brief SPI中斷處理回調函數
@param 無
@return 無
*/
static void spiCallbackFunc(nrf_drv_spi_evt_t const *pEvent, void *arg)
{
s_transferOk = true;
}
/****************************************************END OF FILE****************************************************/
2.2 board_spi.h
#ifndef _BOARD_SPI_H_
#define _BOARD_SPI_H_
/*********************************************************************
* INCLUDES
*/
#include <stdbool.h>
#include "common.h"
/*********************************************************************
* DEFINITIONS
*/
#define BOARD_SPI_CS_ON 0
#define BOARD_SPI_CS_OFF 1
#define SPI_CS_HIGH SPI_CsnSet(BOARD_SPI_CS_OFF)
#define SPI_CS_LOW SPI_CsnSet(BOARD_SPI_CS_ON)
#define BOARD_SPI0_MISO_IO 17
#define BOARD_SPI0_MOSI_IO 18
#define BOARD_SPI0_CLK_IO 20
#define BOARD_SPI0_CSN_IO 19
#define SPI_INSTANCE 0 // SPI instance index
/*********************************************************************
* API FUNCTIONS
*/
void SPI_Init(void);
void SPI_CsnSet(bool pinState);
void SPI_ReadWriteData(uint8 *pWriteData, uint8 *pReadData, uint8 writeDataLen);
void SPI_Enable(void);
void SPI_Disable(void);
#endif /* _BOARD_SPI_H_ */
三、API調用
需包含頭文件 board_spi.h
SPI_Init
功能 | 初始化SPI驅動 |
---|---|
函數定義 | void SPI_Init(void) |
參數 | 無 |
返回 | 無 |
1.其中CS片選信號引腳不要直接在 spiConfig.ss_pin 設置,需要自己另外用GPIO驅動
2.spiConfig.irq_priority 爲中斷優先級,如果在定時器中使用則優先級需小於6
3.spiConfig.frequency 爲傳輸速率,最高可設爲SPI_FREQUENCY_FREQUENCY_M8即 8 Mbps
4.spiConfig.mode 爲SPI模式,有4種模式0-3,通常爲模式0
SPI_CsnSet
功能 | SPI片選信號設置 |
---|---|
函數定義 | void SPI_CsnSet(bool pinState) |
參數 | pinState:引腳狀態 |
返回 | 無 |
SPI_ReadWriteData
功能 | SPI讀出寫入數據 |
---|---|
函數定義 | void SPI_ReadWriteData(uint8_t *pWriteData, uint8_t *pReadData, uint8_t writeDataLen) |
參數 | pWriteData:寫入數據 pReadData:讀出數據 writeDataLen:寫入數據長度 |
返回 | 無 |
SPI_Enable
功能 | 開啓SPI,實現低功耗配合SPI_Disable使用 |
---|---|
函數定義 | void SPI_Enable(void) |
參數 | 無 |
返回 | 無 |
SPI_Disable
功能 | 禁用SPI,實現低功耗配合SPI_Enable使用 |
---|---|
函數定義 | void SPI_Disable(void) |
參數 | 無 |
返回 | 無 |
四、SDK配置
點擊 sdk_config.h 文件
選擇 Configuration Wizard
nRF_Drivers 中勾選SPI及SPIM相關選項
在 nRF_Drivers 中添加文件
五、使用例子
1)添加頭文件
#include "board_spi.h"
2)添加初始化代碼(SDK15.3 中 ble_peripheral 的 ble_app_template 工程 main() 函數中)
加入 SPI_Init() 並在初始化後調用 SPI_Disable 進入低功耗,在需要用SPI時調用 SPI_Enable 開啓SPI
int main(void)
{
bool erase_bonds;
/*-------------------------- 外設驅動初始化 ---------------------------*/
// Initialize.
log_init(); // 日誌驅動初始化
timers_init(); // 定時器驅動初始化(在此加入自定義定時器)
SI522_Init(); // SI522驅動初始化(含SPI)
/*-------------------------- 藍牙協議棧初始化 ---------------------------*/
power_management_init();
ble_stack_init(); // 協議棧初始化
gap_params_init();
gatt_init();
advertising_init(); // 廣播初始化
services_init(); // 服務初始化
conn_params_init(); // 連接參數初始化
peer_manager_init();
/*-------------------------- 開啓應用 ---------------------------*/
// Start execution.
NRF_LOG_INFO("Template example started.");
advertising_start(erase_bonds); // 開啓廣播
application_timers_start(); // 定時器應用開啓(在此開啓自定義定時器)
SPI_Disable(); // 禁用SPI,進入低功耗模式,等待讀卡時再開啓
// Enter main loop.
for(;;)
{
idle_state_handle();
}
}
3)寫入數據
uint8_t temp[1] = {0x01};
SPI_ReadWriteData(temp, NULL, sizeof(uint8_t));
4)查看示波器
CLK
MOSI
• 由 Leung 寫於 2019 年 12 月 24 日
• 參考:青風電子社區