nRF5的特殊外设PPI/GPIOTE

/ 0评 / 0

凑在一起讲的原因,实在是因为他们关联密切,这个算是nRF5系特殊外设了.

说起这个东西,特别需要注意几个概念.

EVENT和TASK概念:

我就拿官方例子说事,定时器EVENT驱动GPIO TASK,完整的自己去看examplesperipheralgpiote,这里只是抽取重点和添加一些注释.

static nrf_drv_timer_t timer = NRF_DRV_TIMER_INSTANCE(0);



void timer_dummy_handler(nrf_timer_event_t event_type, void * p_context){}



static void led_blinking_setup()

{

    uint32_t compare_evt_addr;

    uint32_t gpiote_task_addr;

    nrf_ppi_channel_t ppi_channel;

    nrf_drv_gpiote_out_config_t config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(false);



    /* GPIOTE OUT就是TASK,声明一个TASK,config传递的是默认状态,比如这里false指的是低电平. */

    nrf_drv_gpiote_out_init(13, &config);

    /* 设置定时器比较通道参数 */

    nrf_drv_timer_extended_compare(&timer, (nrf_timer_cc_channel_t)0, 500 * 1000UL, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, false);

    

    nrf_drv_ppi_channel_alloc(&ppi_channel);

    /* 比较通道0事件,作为PPI输入. */

    compare_evt_addr = nrf_drv_timer_event_address_get(&timer, NRF_TIMER_EVENT_COMPARE0);

    /* GPIO连接GPUOTE OUT. */

    gpiote_task_addr = nrf_drv_gpiote_out_task_addr_get(13);

    /* 连接这个EVENT到TASK,然后使能. */

    nrf_drv_ppi_channel_assign(ppi_channel, compare_evt_addr, gpiote_task_addr);

    nrf_drv_ppi_channel_enable(ppi_channel);



    /* 使用GPIOTE里面的TASK配置. */

    nrf_drv_gpiote_out_task_enable(13);

}



int main(void)

{

    nrf_drv_ppi_init();

    nrf_drv_gpiote_init();

    /* 定时器初始化第三个参数不能为NULL,所以创建个空函数,接受各种事件回调. */

    nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;

    nrf_drv_timer_init(&timer, &timer_cfg, timer_dummy_handler);



    /* 创建PPI连接 */

    led_blinking_setup();



    /* 使能定时器后PPI生效 */

    nrf_drv_timer_enable(&timer);



    while (true)

    {

        /* 什么都不需要做,PPI自动操作LED. */

    }

}



主要就是COMPORE0输出事件,会导致GPIO的TASK执行,然后GPIO就会按照一定的规律,进行翻转.这个规律,取决于COMPORE0的情况,后面还有ppi和pin_change_int的各种例子,可以参考.