NRF52832學(xué)習(xí)筆記(5)——SPI(主機(jī))接口使用

一、硬件連接

功能口 引腳
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.cboard_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ū)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末笛粘,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌薪前,老刑警劉巖润努,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異序六,居然都是意外死亡任连,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進(jìn)店門例诀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來随抠,“玉大人,你說我怎么就攤上這事繁涂」八” “怎么了?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵扔罪,是天一觀的道長秉沼。 經(jīng)常有香客問我,道長矿酵,這世上最難降的妖魔是什么唬复? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮全肮,結(jié)果婚禮上敞咧,老公的妹妹穿的比我還像新娘。我一直安慰自己辜腺,他們只是感情好休建,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著评疗,像睡著了一般测砂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上百匆,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天砌些,我揣著相機(jī)與錄音,去河邊找鬼加匈。 笑死寄症,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的矩动。 我是一名探鬼主播,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼释漆,長吁一口氣:“原來是場噩夢啊……” “哼悲没!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤示姿,失蹤者是張志新(化名)和其女友劉穎甜橱,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體栈戳,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡岂傲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了子檀。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片镊掖。...
    茶點(diǎn)故事閱讀 38,577評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖褂痰,靈堂內(nèi)的尸體忽然破棺而出亩进,到底是詐尸還是另有隱情,我是刑警寧澤缩歪,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布归薛,位于F島的核電站,受9級特大地震影響匪蝙,放射性物質(zhì)發(fā)生泄漏主籍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一逛球、第九天 我趴在偏房一處隱蔽的房頂上張望千元。 院中可真熱鬧,春花似錦需忿、人聲如沸诅炉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽涕烧。三九已至,卻和暖如春汗洒,著一層夾襖步出監(jiān)牢的瞬間议纯,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工溢谤, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留瞻凤,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓世杀,卻偏偏與公主長得像阀参,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子瞻坝,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內(nèi)容