首页 > 其他分享 >nordic的nrf52系列32M速率的SPI-SPIM3

nordic的nrf52系列32M速率的SPI-SPIM3

时间:2023-12-06 10:22:40浏览次数:40  
标签:code PIN SPIM3 nrf52 NRF 32M spi nrf GPIO

简介:在nordic的nrf52系列中的nrf52833和nrf52840的SPIM3都是支持最大32M的spi速率,其余的只有8M,当在需要刷屏,或者一些需要高速32M-SPI时,这是一个很好的使用方式,下面我就结合GPIOTE+PPI+SPIM3实现无CPU参与的32M-SPI数据发送:

测试环境:软件:SDK_17.1,在ble_app_uart例子中添加

硬件:nrf52832-DK板

一、引脚选择

特别注意一点,需要使用32M的SPI时,一定要选择非低频的引脚作为SPI的pin脚,如下面这些引脚就不可以:

在数据手册中还有这样一条提示,他的意思是在使用32M的时候,可能还要配置为高驱模式,不然可能有数据错乱。

根据数据手册我当前选择4,5,27,26这4个引脚作为SPI的引脚。

二、代码编写

1.源文件添加

在工程中加入如下几个.c源文件,其中spi_test.c不是官方库文件,是我的SPIM配置代码,这一点注意,你只用添加前面的5个源文件就行

2、宏定义启用

 这一步主要是启用相关的源文件,如果宏定义不启用刚刚添加的部分源文件是无法添加的,这一步很重要:

 先启用SPIM3:

 还要勾选另一个宏定义,在调试过程中发现如果只启动NRFX_SPI_ENABLED,不任意使能它下面的NRFX_SPI0_ENABLED,NRFX_SPI1_ENABLED,NRFX_SPI2_ENABLED的其中一个,居然无法让NRFX_SPIM_ENABLED生效,这一点需要注意一下。

 经过以上的宏定义勾选,SPI的驱动就启动完成了。

启用PPI:

 到这一步宏定义就都启用完成了,你可以检测一下加入的源文件是否都启用了。

 然后就是代码部分,我已经进行了相关注释,可以直接copy使用。

 三、代码

 1、.c文件

#include "nrf_drv_spi.h"
#include "app_util_platform.h"
#include "nrf_drv_gpiote.h"
#include "nrf_delay.h"
#include "boards.h"
#include "app_error.h"
#include <string.h>

/*log打印的头文件*/
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"


#include "nrf_drv_ppi.h"
#include "spi_test.h"

#define PIN_IN    BUTTON_4
#define leng 10
#define TEST_STRING "spi_ppi_test"

uint8_t TX_buffer[]=TEST_STRING;
uint8_t RX_buffer[leng];

/*PPI 通道实例变了定义*/
static nrf_ppi_channel_t     m_ppi_channel;

/*SPIM3可以达到32M*/
static nrfx_spim_t my_spi=NRFX_SPIM_INSTANCE(3);

/*变量定义,用于确定SPI是否正确传输,每一次都会进行加一,0x31只是一个本次随意设置的初始值*/
uint8_t test=0x31;


/*同时设置TX和RX的buffer*/
nrfx_spim_xfer_desc_t m_buffer = NRFX_SPIM_XFER_TRX(TX_buffer,sizeof(TX_buffer),RX_buffer,leng);
/**
 * @brief SPI user event handler.
 * @param event
 */
void spi_event_handler(nrfx_spim_evt_t const * p_event,
                       void *                  p_context)
{
        ret_code_t err_code;
    /*传输事件判断*/
        if(NRF_DRV_SPI_EVENT_DONE == p_event->type)
        {
            NRF_LOG_INFO("Transfer completed.")
            TX_buffer[0]=++test;
            /*一次传输完成,提供下一次传输的buffer,如果有大量接收的数据,可以使用两个buffer交替接收,便于流出时间进行数据处理,第二个buffer也是使用 
            nrfx_spim_xfer_desc_t m_buffer = NRFX_SPIM_XFER_TRX(TX_buffer2,sizeof(TX_buffer2),RX_buffer2,leng2);进行定义,如果是只想单独定义一个TX和RX
            请使用 NRFX_SPIM_XFER_TX 或者 NRFX_SPIM_XFER_RX
            */
            err_code = nrfx_spim_xfer(&my_spi,&m_buffer,NRF_DRV_SPI_FLAG_HOLD_XFER);
            APP_ERROR_CHECK(err_code);
        }
        /*如果有接收数据就打印一下,实际应用中可以是其余处理*/
    if (RX_buffer[0] != 0)
    {
        NRF_LOG_INFO(" Received:");
        NRF_LOG_HEXDUMP_INFO(RX_buffer, strlen((const char *)RX_buffer));
    }
}

void gpiote_init(void)
{
     ret_code_t err_code;
    /*由于这个例子是基于ble_app_uart,在 主函数中的buttons_leds_init(&erase_bonds);中已经初始化了GPIOTE,所以注释掉,不能重复初始化*/
//        err_code = nrf_drv_gpiote_init();
//    APP_ERROR_CHECK(err_code);
    
        nrf_drv_gpiote_in_config_t in_config = NRFX_GPIOTE_CONFIG_IN_SENSE_HITOLO(true);
    in_config.pull = NRF_GPIO_PIN_PULLUP;
    
    /*由于这个例子是基于ble_app_uart,在 主函数中的buttons_leds_init(&erase_bonds);中已经初始化了DK板上的按键4,我要用来做SPI数据触发,所以先解绑这个引脚在配置 */
        nrf_drv_gpiote_in_uninit(PIN_IN);
    /* 中断初始化,回调为NULL,因为是通过PPI触发SPIM所以不需要回调,当然如果有需要你也可以设置 */
        err_code = nrf_drv_gpiote_in_init(PIN_IN, &in_config, NULL);
    APP_ERROR_CHECK(err_code);
    /* GPIO中断事件使能 */
        nrf_drv_gpiote_in_event_enable(PIN_IN, true);
}

void spim_init(void)
{
    /*不能使用低频引脚,还要配置为高驱*/
    nrfx_spim_config_t spi_config = NRFX_SPIM_DEFAULT_CONFIG;
    spi_config.ss_pin   = 27;
    spi_config.miso_pin = 4;//如果是刷屏可以不使用MISO数据pin脚,可以设置为 NRFX_SPIM_PIN_NOT_USED
    spi_config.mosi_pin = 5;
    spi_config.sck_pin  = 26;
        spi_config.frequency=NRF_SPIM_FREQ_32M;
    APP_ERROR_CHECK(nrfx_spim_init(&my_spi, &spi_config, spi_event_handler, NULL));
    
    /*高驱配置*/
        nrf_gpio_cfg(27,
                NRF_GPIO_PIN_DIR_OUTPUT,
                NRF_GPIO_PIN_INPUT_DISCONNECT,
        NRF_GPIO_PIN_NOPULL,
        NRF_GPIO_PIN_H0H1,
        NRF_GPIO_PIN_NOSENSE);
        nrf_gpio_cfg(4,
                NRF_GPIO_PIN_DIR_INPUT,
                NRF_GPIO_PIN_INPUT_CONNECT,
        NRFX_SPIM_MISO_PULL_CFG,
        NRF_GPIO_PIN_H0H1,
        NRF_GPIO_PIN_NOSENSE);
        nrf_gpio_cfg(5,
                NRF_GPIO_PIN_DIR_OUTPUT,
                NRF_GPIO_PIN_INPUT_DISCONNECT,
        NRF_GPIO_PIN_NOPULL,
        NRF_GPIO_PIN_H0H1,
        NRF_GPIO_PIN_NOSENSE);
        nrf_gpio_cfg(26,
                NRF_GPIO_PIN_DIR_OUTPUT,
                NRF_GPIO_PIN_INPUT_DISCONNECT,
        NRF_GPIO_PIN_NOPULL,
        NRF_GPIO_PIN_H0H1,
        NRF_GPIO_PIN_NOSENSE);
                
        NRF_LOG_INFO("SPI init end.");
}

void ppi_init(void)
{
        ret_code_t err_code;

    err_code = nrf_drv_ppi_init();
    APP_ERROR_CHECK(err_code);
    
        /*给spi初始化缓存,并flag选择什么时候启动传输*/
        /*NRF_DRV_SPI_FLAG_HOLD_XFER ---- 占时不启用,可在PPI触发下的SPIM的传输*/
        err_code = nrfx_spim_xfer(&my_spi,&m_buffer,NRF_DRV_SPI_FLAG_HOLD_XFER);
        APP_ERROR_CHECK(err_code);
        
        /* 触发的事件地址*/
        uint32_t gpio_event_addr = nrfx_gpiote_in_event_addr_get(PIN_IN);
        /* 执行的任务地址 */
        uint32_t spim_tick_addr  = nrfx_spim_start_task_get(&my_spi);
    
        /*PPI设置*/
        //把PPI的通道1分配出来
    err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel);
    APP_ERROR_CHECK(err_code);
        /* 关联事件和任务*/
        err_code = nrf_drv_ppi_channel_assign(m_ppi_channel,
                                          gpio_event_addr,
                                          spim_tick_addr);
        APP_ERROR_CHECK(err_code);
        /* 启动PPI*/
        err_code = nrf_drv_ppi_channel_enable(m_ppi_channel);
    APP_ERROR_CHECK(err_code);
    
}

void SPIM_test_init(void)
{
        spim_init();
        gpiote_init();
        ppi_init();
}

2、.h文件

#ifndef SPI_TEST_H__
#define SPI_TEST_H__


void SPIM_test_init(void);


#endif

只要在主函数中引用SPIM_test_init();就可以了。

 

标签:code,PIN,SPIM3,nrf52,NRF,32M,spi,nrf,GPIO
From: https://www.cnblogs.com/HW-liu/p/17877460.html

相关文章

  • 基于mdev实现adb热插拔(@STM32MP157D+fusb302)
    关键词:fusb302、uevent、mdev、adbd等等。1fusb302关于USB插拔检测,以及增加uevent事件fsusb302支持USBPowerDelivery协议(USBPowerDelivery),支持识别各种USB设备和对应的状态。fusb302支持DRP(DualRolePower)、DFP(DownstreamFacingPort)、UFP(UpstreamFacingPort)......
  • 嵌入式Linux adbd实现概要梳理(基于STM32MP157D+Buildroot)
    关键词:USBGadget、dwc2、configfs、functionfs、adbd等等。基于STM32MP157D简单记录ADB实现的过程,涉及到USB、Gadget、configfs、functionfs、adbd、ADB协议等等。基于Buildroot2020.02.6编译adbd运行于设备,和PCWindows交互的简要框图:1Linux下USBGadget1.1Linux内核Gad......
  • nRF52840 SYSTEM OFF模式下唤醒的唤醒方式
    参考spec上的说明,唤醒源有5个。分别是:1.GPIO外设发出的DETECT信号2.LPCOMP模块发出的ANADETECT信号3.NFC模块发出的SENSE信号4.USB模块VBUSpin出现有效电压时5.给复位管脚一个信号供参考示例在如下工程中,NCS示例有待再发现\nRF5_SDK_17.1.0\examples\peripheral......
  • 如何选择米尔基于STM32MP1系列核心板和开发板
    一款合适的处理器,是每个工程师在开发设计前期调研必须面对的难题。而如何挑选一款符合产品开发的处理器呢?今天我们就以ST公司的STM32MP1系列处理器进行分析比较。ST公司目前已经发布了两款不同类型的MPU芯片,分别是STM32MP15系列和STM32MP13系列。这两款芯片的特点十分鲜明:STM32MP......
  • STM32MP135开发板5折,米尔邀您参与2023 STM32全国巡展
    2023年9月12日至10月27日,以“STM32,不止于芯”为主题的第十六届STM32全国巡回研讨会将走进11个城市。本届研讨会为全天会议,我们将围绕STM32最新产品开展技术演讲和方案演示。本次STM32全国研讨会,米尔电子将现场展出STM32相关的最新产品技术和应用演示,为工程师们提供共话交流共同探......
  • STM32MP135开发板5折,米尔邀您参与2023 STM32全国巡展
    2023年9月12日至10月27日,以“STM32,不止于芯”为主题的第十六届STM32全国巡回研讨会将走进11个城市。本届研讨会为全天会议,我们将围绕STM32最新产品开展技术演讲和方案演示。本次STM32全国研讨会,米尔电子将现场展出STM32相关的最新产品技术和应用演示,为工程师们提供共话交流共同探索......
  • nrf52832-mdk
    https://wiki.makerdiary.com/nrf52832-mdk/getting-started/https://nuttx.apache.org/docs/latest/platforms/arm/nrf52/boards/nrf52832-mdk/index.html......
  • iTOP-STM32MP157开发板一键烧写 QT 程序到开发板
    1根据上一小节设置好编译套件后,打开自己的qt工程,然后点击qtcreator里面的项目,把编译器切换成上一章节设置好的的编译器,如下图所示:2然后打开要编译的QT代码的pro文件,在里面添加以下代码,这俩行代码的意思是说把编译的可执行程序下载到开发板的/opt目录下并执行。target.pa......
  • ST官方基于米尔STM32MP135开发板培训课程(一)
    本文将以Myirtech的MYD-YF13X以及STM32MP135F-DK为例,讲解如何使用STM32CubeMX结合Developerpackage实现最小系统启动。    1.开发准备1.1Developer package准备a.Developerpackage下载:‍https://www.st.com/en/embedded-software/stm32mp1dev.html‍b.解压后进入......
  • 4 STM32MP1 Linux系统启动过程
    1.ROM代码  这是ST官方写的代码,在STM32MP1出厂时就已经烧录进去,不能被修改。ROM代码是上电以后首先执行的程序,它的主要工作就是读取STM32MP1的BOOT引脚电平,然后根据电平来判断当前启动设备,最后从选定的启动设备里面读取FSBL代码,将FSBL代码放在对应的RAM空间。  STM32MP1启......