52832 SDK 循序渐进(一)1.点灯/ 2. 解决P9使能 / 3. RTT调试打印

3 篇文章 0 订阅

准备工作,先把作业例程解压到sdk包的example目录下

一 . 从blink例程开始

工程文件目录:....\nRF5_SDK_15.2.0_9412b96\examples\peripheral\hy-demo\1.1blinky\dev0628\s132\arm5_no_packs

嵌入式开发板第一件事,当然是点灯了,52832代码组织上有BSP底层软件,也有板子的资源定义文件,所以我们要根据原理图来自己定义资源文件。

我们开发板硬件连接, 先解决指示灯和按键。 

 

 

另外定义个板载资源文件dev0628.h,和pca10040.h文件放一起,然后修改boards.h

dev0628.h主要内容定义LED 和BUTTON

// LEDs definitions for DEV0628
#define LEDS_NUMBER    3

#define LED_START      5
#define LED_1          5
#define LED_2          7
#define LED_3          9

#define LED_STOP       9

#define LEDS_ACTIVE_STATE 0

#define LEDS_INV_MASK  LEDS_MASK

#define LEDS_LIST { LED_1, LED_2, LED_3 }

#define BSP_LED_0      LED_1
#define BSP_LED_1      LED_2
#define BSP_LED_2      LED_3


#define BUTTONS_NUMBER 3

#define BUTTON_START   2
#define BUTTON_1       2
#define BUTTON_2       3
#define BUTTON_3       4

#define BUTTON_STOP    4
#define BUTTON_PULL    NRF_GPIO_PIN_PULLUP

#define BUTTONS_ACTIVE_STATE 0

#define BUTTONS_LIST { BUTTON_1, BUTTON_2, BUTTON_3 }

#define BSP_BUTTON_0   BUTTON_1
#define BSP_BUTTON_1   BUTTON_2
#define BSP_BUTTON_2   BUTTON_3
 

boards.h增加编译选择开关
#elif defined(BOARD_DEV0628)
#include "dev0628.h"

工程设置的编译开关板子选择改一下:

 

主程序代码就是原来的blinky例程基本没变

 

 

int main(void)
{
    /* Configure board. */
    bsp_board_init(BSP_INIT_LEDS);

    /* Toggle LEDs. */
    while (true)
    {
        for (int i = 0; i < LEDS_NUMBER; i++)
        {
            bsp_board_led_invert(i);
            nrf_delay_ms(500);
        }
    }
}
 

涉及到api:

void bsp_board_init(uint32_t init_flags)

调用标志BSP_INIT_LEDS,BSP_INIT_BUTTONS,

本例程调用的是

bsp_board_leds_init();

驱动初始化调用的

void nrf_gpio_cfg_output(uint32_t pin_number);

主循环里点灯调用的bsp的led驱动接口

void bsp_board_led_invert(uint32_t led_idx);

这个在调取LEDS的列表后,实际调用的IO驱动

void nrf_gpio_pin_toggle(uint32_t pin_number)

延时用到了sdk的延时函数

void nrf_delay_ms(uint32_t ms_time)

 

注意,要先烧录s132的softdevice,选择softdevice,然后load烧录

然后再选择芯片,再load应用固件

烧录成功后,LED1, LED2正常,LED3并不会亮,也就是P9没有起作用,这就是我们下一个话题,怎么让P9/P10起作用,作为普通GPIO来使用。

 

二,打开上面一个例程,做出必要的修改

   52832的NFC功能是定义在P9/P10,而且是默认的配置, 所以9/10脚必须改变下设置,才能当作普通GPIO使用。

    打开的方法: 

    1. #include "system_nrf52.h" 主程序把这个头文件加上

    2. 头文件里要有一句

   //#define CONFIG_NFCT_PINS_AS_GPIOS

注意,修改system_nrf532.h时有可能要在资源管理器里修改文件默认属性为可写,才能够添加配置项。

详见第二个工程例程 nRF5_SDK_15.2.0_9412b96\examples\hy-demo\1.2blinky -3leds\dev0628\s132\arm5_no_packs

编译下载后,三个灯都会依次点亮。 

三,接下来,我们要搞定调试打印输出

JLINK有个非常有用的功能,就是可以通过RTT库来输出调试信息,然后用JLINK配套的工具RTT VIEWER来查看,就可以省掉一个串口输出。

viewer打开长这个样子

记得选择正确的芯片

 

当然,我们的开发板在烧录口也引入了一路串口,所以插上板子后会识别到一个串口,这个串口的调试信息打印我们在后续的例程讲解,这一节先通过RTT输出调试信息。

好,现在来看代码,要完成以下几个步骤: 

1)copy RTT库文件

2)main.c增加头文件

#include "SEGGER_RTT.h"   // added for RTT include

3)工程结构里加入文件

4) 编译环境设置添加RTT目录的路径

 

5)接下来 在main.c 使用RTT功能前初始化

 SEGGER_RTT_Init();

就可以在想要的位置调用格式化打印

窗口可以指定,默认为0

    SEGGER_RTT_printf(0,"52832 BLINK-RTT demo start. \r\n");

编译,下载,观察。

可以观察到除了闪灯之外, RTT VIEWER能观察到打印输出

 

 

二 . 下一步预备知识 : 要处理按键中断,就必须先了解52832的GPIOTE机制

可以参考文章https://blog.csdn.net/qq_33575901/article/details/90041554

GPIOTE原理
1.概念
1)nRF52832的GPIO只能作为通用的输入输出使能,它作为输入时无法产生中断的,这时候就需要通过GPIOTE实现这种效果了;
2)GPIOTE(GPIO任务和事件),是在GPIO的基础上引入任务和事件;
3)通过任务和事件来操作IO,任务是针对输出的,它可以让IO输出不同的动作,而事件针对输入,IO的状态变化会置位事件寄存器,从而产生事件中断。

2.原理
1)nRF52832的GPIOTE共有8个通道,每个通道都可以分配给一个引脚,分配的引脚可以配置为任务模式或事件模式;
2)GPIOTE每个通道都有SET、CLR和OUT任务,其中SET任务让引脚输出高电平,CLR任务让引脚输出低电平,OUT任务可以通过配置对引脚执行置位、清零和翻转操作;
3)GPIOTE每个通道的事件都可以配置为三种输入状态:上升沿、下降沿和任意电平跳变;
4)任务和事件通过CONFIG[n](n=0~7)寄存器配置,每个CONFIG[n]寄存器可配置一个对应编号OUT[n](n=0~7)任务寄存器和IN[n]事件寄存器;
5)当通过CONFIG寄存器配置某个引脚由SET、CLR和OUT任务寄存器或IN事件寄存器控制后,该引脚只能被GPIOTE模块写操作,正常的GPIO写入无效;
6)当在同一个GPIOTE通道中同时触发了有冲突的任务,这些任务的执行级别由高到低依次为:OUT-->CLR-->SET;
7)GPIOTE除了8个通道外,还包含一个PORT事件,PORT事件是多个引脚通过GPIO DETECT信号产生的事件。

GPIOTE寄存器(n=0~7)
1.OUT任务寄存器
OUT[n]:对CONFIG[n].PSEL指定的引脚进行写操作,引脚动作由CONFIG[n].POLARITY中的配置决定

2.TASKS_SET任务寄存器
TASKS_SET[n]:对CONFIG[n].PSEL指定的引脚进行写操作,引脚动作为输出高电平

3.TASKS_CLR任务寄存器
TASKS_CLR[n]:对CONFIG[n].PSEL指定的引脚进行写操作,引脚动作为输出低电平

4.EVENT_IN事件寄存器
EVENT_IN[n]:CONFIG[n].PSEL指定的引脚产生的事件

5.通用寄存器
1)INTENSET:使能中断
2)INTENCLR:禁止中断
3)CONFIG[n]:OUT[n],SET[n],CLR[n]和IN[n]的配置
我们来用GPIOTE的机制来控制blink。

主要的API接口:

3.相关库函数使用
//头文件:nrf_drv_gpiote.h
1)ret_code_t nrf_drv_gpiote_init(void)
功能:初始化GPIOTE模块
2)ret_code_t nrf_drv_gpiote_out_init(nrf_drv_gpiote_pin_t pin,nrf_drv_gpiote_out_config_t const *p_config)
功能:初始化GPIOTE输出引脚,输出引脚初始化设置中会设定引脚的动作(低电平到高电平、高电平到低电平或者翻转状态)和初始化状态(高电平或低电平)
3)void nrf_drv_gpiote_out_uninit(nrf_drv_gpiote_pin_t pin)
功能:释放GPIOTE输出引脚
4)void nrfx_gpiote_out_task_enable(nrfx_drv_gpiote_pin_t pin)
功能:使能GPIOTE输出引脚的任务模式
5)void nrfx_gpiote_out_task_disable(nrfx_drv_gpiote_pin_t pin)
功能:禁止GPIOTE输出引脚的任务模式
6)触发任务驱动引脚函数
1>nrf_drv_gpiote_set_task_trigger(nrf_drv_gpiote_pin_t pin)
功能:收到触发GPIOTE SET任务,触发后,对应的引脚输出高电平
2>nrf_drv_gpiote_clr_task_trigger(nrf_drv_gpiote_pin_t pin)
功能:收到触发GPIOTE CLR任务,触发后,对应的引脚输出低电平
3>nrf_drv_gpiote_out_task_trigger(nrf_drv_gpiote_pin_t pin)
功能:收到触发GPIOTE OUT任务,触发后,对应的引脚输出状态翻转

7)ret_code_t nrf_drv_gpiote_in_init(nrf_drv_gpiote_pin_t pin,nrf_drv_gpiote_in_config_t const *p_config,nrf_drv_gpiote_evt_handler_t evt_handler)
功能:初始化GPIOTE输入引脚,
8)void nrfx_gpiote_in_event_enable(nrfx_drv_gpiote_pin_t pin,bool int_enable)
功能:使能GPIOTE输入引脚
 

先初始化LED1对应的通道

static void led_blinking_setup()
{

    ret_code_t err_code;
    // init the GPIOTE module
      err_code = nrf_drv_gpiote_init();
    APP_ERROR_CHECK(err_code);
// define the GPIOTE task for output
    nrf_drv_gpiote_out_config_t config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(true);
// define the GPIOTE out PINNUMBER
    err_code = nrf_drv_gpiote_out_init(LED1, &config);
    APP_ERROR_CHECK(err_code);

   // enable the GPIO out task model
    nrf_drv_gpiote_out_task_enable(LED1);
}

/**
 * @brief Function for application main entry.
 */

主循环就是触发GPIOTE任务,然后延时


int main(void)
{
    ret_code_t err_code;

   
  
   // Setup GPIOTE task for pin toggle.
    led_blinking_setup();

  

    while (true)
    {
        // Do Nothing - GPIO can be toggled without software intervention.
            nrf_drv_gpiote_out_task_trigger(LED1);
            nrf_delay_ms(500);

    }
}
问题? GPIOTE只有通道0-7,7以外的怎么用? 

可以使用Port event

Port event是所有GPIO DETECT信号的组合事件,每个GPIO都可以触发GPIOTE Port event。

但因为事件公用,所以不能同时触发多个GPIO。

 处理技巧

5.3.1 如果不在乎功耗,那么很简单,配置p_config->hi_accuracy = true使用pin event

5.3.2 如果功耗非常重要,并且没有多个GPIO同时中断的场景,那么配置p_config->hi_accuracy = false使用port event

5.3.3 如果功耗非常重要 , 并且需要多个GPIO同时中断,那么配置p_config->hi_accuracy = false使用port event,并且p_config->sense配置为NRF_GPIOTE_POLARITY_TOGGLE, 这样配置如果按键按下触发port event 中断后改变按键GPIO sense设置就不会持续触发DETECT信号,这时有其他GPIO中断就可以触发Port Event中断。

我们在下面一节的按键中断处理中来体会port event的用处。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海里的鱼2022

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值