一、硬件連接
功能口 | 引腳 |
---|---|
MISO | 17 |
MOSI | 18 |
CLK | 20 |
CSN | 19 |
二老玛、移植文件
注意:以下出現(xiàn)缺失common.h文件錯(cuò)誤淤年,去除即可。uint8改為uint8_t或unsigned char或自己宏定義
鏈接:https://pan.baidu.com/s/1AP3VuZz2v5gN47zDDTqCVA 提取碼:d84r
將 board_spi.c 和 board_spi.h 兩個(gè)文件加入工程的Application文件夾下
2.1 board_spi.c
NRF的SPI片選引腳CSN只支持低電平活動(dòng)蜡豹。如果該信號應(yīng)該是高的麸粮,應(yīng)由外部控制,即單獨(dú)寫個(gè)GPIO控制镜廉。
/*********************************************************************
* 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數(shù)據(jù)傳輸完成標(biāo)志
static const nrf_drv_spi_t s_spiHandle = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE); // SPI instance
/*********************************************************************
* PUBLIC FUNCTIONS
*/
/**
@brief SPI的初始化函數(shù)
@param 無
@return 無
*/
void SPI_Init(void)
{
ret_code_t errCode;
nrf_drv_spi_config_t spiConfig = NRF_DRV_SPI_DEFAULT_CONFIG; // 使用SPI默認(rèn)配置
// 配置SPI端口弄诲,注意CSN不要在這設(shè)置,另外用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; // 在定時(shí)器中使用優(yōu)先級需小于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片選信號設(shè)置
@param pinState -[in] 引腳狀態(tài)
@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讀出寫入數(shù)據(jù)
@param pWriteData -[in] 寫入數(shù)據(jù)
@param pReadData -[out] 讀出數(shù)據(jù)
@param writeDataLen -[in] 寫入數(shù)據(jù)長度
@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桨吊,與初始化區(qū)別:沒有初始化CS引腳
@param 無
@return 無
*/
void SPI_Enable(void)
{
ret_code_t errCode;
nrf_drv_spi_config_t spiConfig = NRF_DRV_SPI_DEFAULT_CONFIG; // 使用SPI默認(rèn)配置
// 配置SPI端口威根,注意CSN不要在這設(shè)置,另外用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; // 在定時(shí)器中使用優(yōu)先級需小于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中斷處理回調(diào)函數(shù)
@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調(diào)用
需包含頭文件 board_spi.h
SPI_Init
功能 | 初始化SPI驅(qū)動(dòng) |
---|---|
函數(shù)定義 | void SPI_Init(void) |
參數(shù) | 無 |
返回 | 無 |
1.其中CS片選信號引腳不要直接在 spiConfig.ss_pin 設(shè)置洛搀,需要自己另外用GPIO驅(qū)動(dòng)
2.spiConfig.irq_priority 為中斷優(yōu)先級,如果在定時(shí)器中使用則優(yōu)先級需小于6
3.spiConfig.frequency 為傳輸速率佑淀,最高可設(shè)為SPI_FREQUENCY_FREQUENCY_M8即 8 Mbps
4.spiConfig.mode 為SPI模式留美,有4種模式0-3,通常為模式0
SPI_CsnSet
功能 | SPI片選信號設(shè)置 |
---|---|
函數(shù)定義 | void SPI_CsnSet(bool pinState) |
參數(shù) | pinState:引腳狀態(tài) |
返回 | 無 |
SPI_ReadWriteData
功能 | SPI讀出寫入數(shù)據(jù) |
---|---|
函數(shù)定義 | void SPI_ReadWriteData(uint8_t *pWriteData, uint8_t *pReadData, uint8_t writeDataLen) |
參數(shù) | pWriteData:寫入數(shù)據(jù) pReadData:讀出數(shù)據(jù) writeDataLen:寫入數(shù)據(jù)長度 |
返回 | 無 |
SPI_Enable
功能 | 開啟SPI伸刃,實(shí)現(xiàn)低功耗配合SPI_Disable使用 |
---|---|
函數(shù)定義 | void SPI_Enable(void) |
參數(shù) | 無 |
返回 | 無 |
SPI_Disable
功能 | 禁用SPI谎砾,實(shí)現(xiàn)低功耗配合SPI_Enable使用 |
---|---|
函數(shù)定義 | void SPI_Disable(void) |
參數(shù) | 無 |
返回 | 無 |
四、SDK配置
點(diǎn)擊 sdk_config.h 文件
選擇 Configuration Wizard
nRF_Drivers 中勾選SPI及SPIM相關(guān)選項(xiàng)
注意捧颅,使用EasyDMA(例如SPIM)的外圍設(shè)備要求將傳輸緩沖區(qū)放在數(shù)據(jù)RAM區(qū)域景图。如果不是,并且使用SPM實(shí)例碉哑,nrf_drv_spi_transfet()函數(shù)將失敗挚币,錯(cuò)誤代碼為NRF_ERROR_INVALID_ADDR。
在 nRF_Drivers 中添加文件
五扣典、使用例子
1)添加頭文件
#include "board_spi.h"
2)添加初始化代碼(SDK15.3 中 ble_peripheral 的 ble_app_template 工程 main() 函數(shù)中)
加入 SPI_Init() 并在初始化后調(diào)用 SPI_Disable 進(jìn)入低功耗妆毕,在需要用SPI時(shí)調(diào)用 SPI_Enable 開啟SPI
int main(void)
{
bool erase_bonds;
/*-------------------------- 外設(shè)驅(qū)動(dòng)初始化 ---------------------------*/
// Initialize.
log_init(); // 日志驅(qū)動(dòng)初始化
timers_init(); // 定時(shí)器驅(qū)動(dòng)初始化(在此加入自定義定時(shí)器)
SI522_Init(); // SI522驅(qū)動(dòng)初始化(含SPI)
/*-------------------------- 藍(lán)牙協(xié)議棧初始化 ---------------------------*/
power_management_init();
ble_stack_init(); // 協(xié)議棧初始化
gap_params_init();
gatt_init();
advertising_init(); // 廣播初始化
services_init(); // 服務(wù)初始化
conn_params_init(); // 連接參數(shù)初始化
peer_manager_init();
/*-------------------------- 開啟應(yīng)用 ---------------------------*/
// Start execution.
NRF_LOG_INFO("Template example started.");
advertising_start(erase_bonds); // 開啟廣播
application_timers_start(); // 定時(shí)器應(yīng)用開啟(在此開啟自定義定時(shí)器)
SPI_Disable(); // 禁用SPI,進(jìn)入低功耗模式贮尖,等待讀卡時(shí)再開啟
// Enter main loop.
for(;;)
{
idle_state_handle();
}
}
3)寫入數(shù)據(jù)
uint8_t temp[1] = {0x01};
SPI_ReadWriteData(temp, NULL, sizeof(uint8_t));
4)查看示波器
CLK
MOSI
? 由 Leung 寫于 2019 年 12 月 24 日
? 參考:青風(fēng)電子社區(qū)