nrf_serial的使用

NORDIC DK45

nrf_serial 库是nordic封装的比较上层的串口抽象层。可以支持多个串口,可以使用阻塞、中断、DMA三种模式。接口API比较简单,但是在使用之前需要先进行比较多的宏定义。

在SDK_CONFIG使能配置

在sdk_config中使能如下配置

NRFX_UARTE_ENABLED
NRFX_UART_ENABLED
NRF_SERIAL_ENABLED

并把对应的c文件添加到工程中,h头文件路径包含进工程中

添加串口底层配置定义

#define UART_TX_PIN 5
#define UART_RX_PIN 6

NRF_SERIAL_DRV_UART_CONFIG_DEF(uart_drv_config,
                      UART_RX_PIN, UART_TX_PIN,
                      NRF_UART_PSEL_DISCONNECTED, NRF_UART_PSEL_DISCONNECTED,
                      NRF_UART_HWFC_DISABLED, NRF_UART_PARITY_EXCLUDED,
                      NRF_UART_BAUDRATE_115200,
                      UART_DEFAULT_CONFIG_IRQ_PRIORITY);

该配置主要是用来配置串口的引脚、波特率、中断优先级等和硬件配置相关的东西。

添加FIFO和BUFFER定义

#define SERIAL_FIFO_TX_SIZE 128
#define SERIAL_FIFO_RX_SIZE 256
NRF_SERIAL_QUEUES_DEF(serial_queues, SERIAL_FIFO_TX_SIZE, SERIAL_FIFO_RX_SIZE);

#define SERIAL_BUFF_TX_SIZE 1
#define SERIAL_BUFF_RX_SIZE 1
NRF_SERIAL_BUFFERS_DEF(serial_buffs, SERIAL_BUFF_TX_SIZE, SERIAL_BUFF_RX_SIZE);

这两个东西很容易让人分不清,为什么既要定义queue又要定义一个buffer,是不是有点重复?

这里的BUFFER实际上就是传递给了底层,在DMA模式下当收到数据就直接把数据搬到了BUFFER里面。BUFFER定义的大小可以决定当收到几个byte以后会产生一个DMA中断,通知到上层就是一个NRF_SERIAL_EVENT_RX_DATA事件。所以为了让每接收一个byte会通知到上层来,通常就把SERIAL_BUFF_RX_SIZE设置为1了。

每一次DMA中断nrf_serial就会自动从BUFFER中取出接收到的数据,取出来的数据又会被写入到QUEUE中。应用读取接收到的数据实际上也就是从queue中提取出来了。

添加serial事件回调定义

static void uart_evt_handler_t(struct nrf_serial_s const * p_serial,nrf_serial_event_t event)
{
    if(event==NRF_SERIAL_EVENT_RX_DATA)
    {
    }
    else if(event==NRF_SERIAL_EVENT_FIFO_ERR)
    {
    }
    else if(event==NRF_SERIAL_EVENT_DRV_ERR)
    {
    }
}

前面的SERIAL_BUFF_RX_SIZE设置的是1,当接收到一个byte就会产生一个NRF_SERIAL_EVENT_RX_DATA事件。收到的数据nrf_serial自动的把数据存入到了queue中了。应用可以在接收事件中立马调用nrf_serial_read函数去读取数据,也可以放在app_scheduler中去

添加NRF_SERIAL定义

NRF_SERIAL_UART_DEF(serial_uarte, 0);
NRF_SERIAL_CONFIG_DEF(  serial_config, NRF_SERIAL_MODE_DMA,
                        &serial_queues, &serial_buffs, 
                        uart_evt_handler_t, NULL);

初始化nrf_serial

ret_code_t ret;
ret = nrf_serial_init(&serial_uarte, &uart_drv_config, &serial_config);
APP_ERROR_CHECK(ret);

当初始化以后就直接打开的接收功能,一旦有数据接收到就会产生事件。

发送数据接口函数

ret_code_t nrf_serial_write(nrf_serial_t const * p_serial,
                            void const * p_data,
                            size_t size,
                            size_t * p_written,
                            uint32_t timeout_ms);

接收数据接口函数

ret_code_t nrf_serial_read(nrf_serial_t const * p_serial,
                           void * p_data,
                           size_t size,
                           size_t * p_read,
                           uint32_t timeout_ms);

当使用DMA模式的时候,该函数需要在收到接收事件以后再调用,直接从queue取出接收到的数据。

喜欢 (5)