nrf_serial的使用
nrf_serial 库是nordic封装的比较上层的串口抽象层。可以支持多个串口,可以使用阻塞、中断、DMA三种模式。接口API比较简单,但是在使用之前需要先进行比较多的宏定义。
在SDK_CONFIG使能配置
在sdk_config中使能如下配置
1 2 3 |
NRFX_UARTE_ENABLED NRFX_UART_ENABLED NRF_SERIAL_ENABLED |
并把对应的c文件添加到工程中,h头文件路径包含进工程中
添加串口底层配置定义
1 2 3 4 5 6 7 8 9 |
#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定义
1 2 3 4 5 6 7 |
#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事件回调定义
1 2 3 4 5 6 7 8 9 10 11 12 |
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定义
1 2 3 4 |
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
1 2 3 |
ret_code_t ret; ret = nrf_serial_init(&serial_uarte, &uart_drv_config, &serial_config); APP_ERROR_CHECK(ret); |
当初始化以后就直接打开的接收功能,一旦有数据接收到就会产生事件。
发送数据接口函数
1 2 3 4 5 |
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); |
接收数据接口函数
1 2 3 4 5 |
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取出接收到的数据。