正在加载···
AI摘要
HunYuan-Lite

本教程使用的SDK版本为 nRF5_SDK_17.1.0

前言

Nordic 官方 SDK 中位于 \examples\peripheral\uart\ 目录下的串口例程仅支持单串口收发,实际使用中可能需要同时使用双串口收发,通过以下方法即可实现,该方法的使用带有 EasyDMA 的 UARTE。

详细步骤

  1. 修改位于 \components\libraries\uart\ 目录下的以下3个文件(修改请先备份原文件)
    (1)app_uart.h

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    /**
    * Copyright (c) 2013 - 2020, Nordic Semiconductor ASA
    *
    * All rights reserved.
    *
    * Redistribution and use in source and binary forms, with or without modification,
    * are permitted provided that the following conditions are met:
    *
    * 1. Redistributions of source code must retain the above copyright notice, this
    * list of conditions and the following disclaimer.
    *
    * 2. Redistributions in binary form, except as embedded into a Nordic
    * Semiconductor ASA integrated circuit in a product or a software update for
    * such product, must reproduce the above copyright notice, this list of
    * conditions and the following disclaimer in the documentation and/or other
    * materials provided with the distribution.
    *
    * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
    * contributors may be used to endorse or promote products derived from this
    * software without specific prior written permission.
    *
    * 4. This software, with or without modification, must only be used with a
    * Nordic Semiconductor ASA integrated circuit.
    *
    * 5. Any software provided in binary form under this license must not be reverse
    * engineered, decompiled, modified and/or disassembled.
    *
    * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
    * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
    * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
    * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
    * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
    * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    *
    */
    /**@file
    *
    * @defgroup app_uart UART module
    * @{
    * @ingroup app_common
    *
    * @brief UART module interface.
    */

    #ifndef APP_UART_H__
    #define APP_UART_H__

    #include <stdint.h>
    #include <stdbool.h>
    #include "app_util_platform.h"
    #include "nrf_drv_uart.h"
    #include "app_fifo.h"


    #ifdef __cplusplus
    extern "C" {
    #endif

    #define UART_PIN_DISCONNECTED 0xFFFFFFFF /**< Value indicating that no pin is connected to this UART register. */

    /**@brief UART Flow Control modes for the peripheral.
    */
    typedef enum
    {
    APP_UART_FLOW_CONTROL_DISABLED, /**< UART Hw Flow Control is disabled. */
    APP_UART_FLOW_CONTROL_ENABLED, /**< Standard UART Hw Flow Control is enabled. */
    } app_uart_flow_control_t;

    /**@brief UART communication structure holding configuration settings for the peripheral.
    */
    typedef struct
    {
    uint32_t rx_pin_no; /**< RX pin number. */
    uint32_t tx_pin_no; /**< TX pin number. */
    uint32_t rts_pin_no; /**< RTS pin number, only used if flow control is enabled. */
    uint32_t cts_pin_no; /**< CTS pin number, only used if flow control is enabled. */
    app_uart_flow_control_t flow_control; /**< Flow control setting, if flow control is used, the system will use low power UART mode, based on CTS signal. */
    bool use_parity; /**< Even parity if TRUE, no parity if FALSE. */
    uint32_t baud_rate; /**< Baud rate configuration. */
    } app_uart_comm_params_t;

    /**@brief UART buffer for transmitting/receiving data.
    */
    typedef struct
    {
    uint8_t * rx_buf; /**< Pointer to the RX buffer. */
    uint32_t rx_buf_size; /**< Size of the RX buffer. */
    uint8_t * tx_buf; /**< Pointer to the TX buffer. */
    uint32_t tx_buf_size; /**< Size of the TX buffer. */
    } app_uart_buffers_t;

    /**@brief Enumeration which defines events used by the UART module upon data reception or error.
    *
    * @details The event type is used to indicate the type of additional information in the event
    * @ref app_uart_evt_t.
    */
    typedef enum
    {
    APP_UART_DATA_READY, /**< An event indicating that UART data has been received. The data is available in the FIFO and can be fetched using @ref app_uart_get. */
    APP_UART_FIFO_ERROR, /**< An error in the FIFO module used by the app_uart module has occured. The FIFO error code is stored in app_uart_evt_t.data.error_code field. */
    APP_UART_COMMUNICATION_ERROR, /**< An communication error has occured during reception. The error is stored in app_uart_evt_t.data.error_communication field. */
    APP_UART_TX_EMPTY, /**< An event indicating that UART has completed transmission of all available data in the TX FIFO. */
    APP_UART_DATA, /**< An event indicating that UART data has been received, and data is present in data field. This event is only used when no FIFO is configured. */
    } app_uart_evt_type_t;

    /**@brief Struct containing events from the UART module.
    *
    * @details The app_uart_evt_t is used to notify the application of asynchronous events when data
    * are received on the UART peripheral or in case an error occured during data reception.
    */
    typedef struct
    {
    app_uart_evt_type_t evt_type; /**< Type of event. */
    union
    {
    uint32_t error_communication; /**< Field used if evt_type is: APP_UART_COMMUNICATION_ERROR. This field contains the value in the ERRORSRC register for the UART peripheral. The UART_ERRORSRC_x defines from nrf5x_bitfields.h can be used to parse the error code. See also the \nRFXX Series Reference Manual for specification. */
    uint32_t error_code; /**< Field used if evt_type is: NRF_ERROR_x. Additional status/error code if the error event type is APP_UART_FIFO_ERROR. This error code refer to errors defined in nrf_error.h. */
    uint8_t value; /**< Field used if evt_type is: NRF_ERROR_x. Additional status/error code if the error event type is APP_UART_FIFO_ERROR. This error code refer to errors defined in nrf_error.h. */
    } data;
    } app_uart_evt_t;

    /**@brief Function for handling app_uart event callback.
    *
    * @details Upon an event in the app_uart module this callback function will be called to notify
    * the application about the event.
    *
    * @param[in] p_app_uart_event Pointer to UART event.
    */
    typedef void (* app_uart_event_handler_t) (app_uart_evt_t * p_app_uart_event);

    struct nrf_uart_obj{
    nrf_drv_uart_t instance;
    bool rx_done;
    bool rx_ovf;
    app_uart_event_handler_t event_handler;
    uint8_t tx_buffer[1];
    uint8_t rx_buffer[1];
    app_fifo_t rx_fifo; /**< RX FIFO buffer for storing data received on the UART until the application fetches them using app_uart_get(). */
    app_fifo_t tx_fifo;/**< TX FIFO buffer for storing data to be transmitted on the UART when TXD is ready. Data is put to the buffer on using app_uart_put(). */
    app_uart_comm_params_t const* comm_params;
    };
    typedef struct nrf_uart_obj nrf_uart_obj_t;

    #define APP_UART_DEF(_name, _instance, _buf_size, _event_handler) \
    static uint8_t _name##_rx_buf[_buf_size]; \
    static uint8_t _name##_tx_buf[_buf_size]; \
    static app_uart_buffers_t _name##_buffers = { \
    .rx_buf = _name##_rx_buf, \
    .rx_buf_size = sizeof (_name##_rx_buf), \
    .tx_buf = _name##_tx_buf, \
    .tx_buf_size = sizeof (_name##_tx_buf), \
    }; \
    nrf_uart_obj_t _name = {\
    .instance = NRF_DRV_UART_INSTANCE(_instance),\
    .rx_done = false,\
    .rx_ovf = false,\
    .event_handler = _event_handler,\
    }

    /**@brief Macro for safe initialization of the UART module in a single user instance when using
    * a FIFO together with UART.
    *
    * @param[in] P_COMM_PARAMS Pointer to a UART communication structure: app_uart_comm_params_t
    * @param[in] RS485_RX_BUF_SIZE Size of desired RX buffer, must be a power of 2 or ZERO (No FIFO).
    * @param[in] RS485_TX_BUF_SIZE Size of desired TX buffer, must be a power of 2 or ZERO (No FIFO).
    * @param[in] EVT_HANDLER Event handler function to be called when an event occurs in the
    * UART module.
    * @param[in] IRQ_PRIO IRQ priority, app_irq_priority_t, for the UART module irq handler.
    * @param[out] ERR_CODE The return value of the UART initialization function will be
    * written to this parameter.
    *
    * @note Since this macro allocates a buffer and registers the module as a GPIOTE user when flow
    * control is enabled, it must only be called once.
    */
    #define APP_UART_FIFO_INIT(P_COMM_PARAMS, RS485_RX_BUF_SIZE, RS485_TX_BUF_SIZE, EVT_HANDLER, IRQ_PRIO, ERR_CODE) \
    do \
    { \
    app_uart_buffers_t buffers; \
    static uint8_t rx_buf[RS485_RX_BUF_SIZE]; \
    static uint8_t tx_buf[RS485_TX_BUF_SIZE]; \
    \
    buffers.rx_buf = rx_buf; \
    buffers.rx_buf_size = sizeof (rx_buf); \
    buffers.tx_buf = tx_buf; \
    buffers.tx_buf_size = sizeof (tx_buf); \
    ERR_CODE = app_uart_init(P_COMM_PARAMS, &buffers, EVT_HANDLER, IRQ_PRIO); \
    } while (0)

    /**@brief Macro for safe initialization of the UART module in a single user instance.
    *
    * @param[in] P_COMM_PARAMS Pointer to a UART communication structure: app_uart_comm_params_t
    * @param[in] EVT_HANDLER Event handler function to be called when an event occurs in the
    * UART module.
    * @param[in] IRQ_PRIO IRQ priority, app_irq_priority_t, for the UART module irq handler.
    * @param[out] ERR_CODE The return value of the UART initialization function will be
    * written to this parameter.
    *
    * @note Since this macro allocates registers the module as a GPIOTE user when flow control is
    * enabled, it must only be called once.
    */
    #define APP_UART_INIT(P_COMM_PARAMS, EVT_HANDLER, IRQ_PRIO, ERR_CODE) \
    do \
    { \
    ERR_CODE = app_uart_init(P_COMM_PARAMS, NULL, EVT_HANDLER, IRQ_PRIO); \
    } while (0)

    /**@brief Function for initializing the UART module. Use this initialization when several instances of the UART
    * module are needed.
    *
    *
    * @note Normally single initialization should be done using the APP_UART_INIT() or
    * APP_UART_INIT_FIFO() macro depending on whether the FIFO should be used by the UART, as
    * that will allocate the buffers needed by the UART module (including aligning the buffer
    * correctly).

    * @param[in] p_comm_params Pin and communication parameters.
    * @param[in] p_buffers RX and TX buffers, NULL is FIFO is not used.
    * @param[in] error_handler Function to be called in case of an error.
    * @param[in] irq_priority Interrupt priority level.
    *
    * @retval NRF_SUCCESS If successful initialization.
    * @retval NRF_ERROR_INVALID_LENGTH If a provided buffer is not a power of two.
    * @retval NRF_ERROR_NULL If one of the provided buffers is a NULL pointer.
    *
    * The below errors are propagated by the UART module to the caller upon registration when Hardware
    * Flow Control is enabled. When Hardware Flow Control is not used, these errors cannot occur.
    * @retval NRF_ERROR_INVALID_STATE The GPIOTE module is not in a valid state when registering
    * the UART module as a user.
    * @retval NRF_ERROR_INVALID_PARAM The UART module provides an invalid callback function when
    * registering the UART module as a user.
    * Or the value pointed to by *p_uart_uid is not a valid
    * GPIOTE number.
    * @retval NRF_ERROR_NO_MEM GPIOTE module has reached the maximum number of users.
    */
    uint32_t app_uart_init(nrf_uart_obj_t * uart_obj,
    app_uart_buffers_t * p_buffers,
    app_irq_priority_t irq_priority);

    /**@brief Function for getting a byte from the UART.
    *
    * @details This function will get the next byte from the RX buffer. If the RX buffer is empty
    * an error code will be returned and the app_uart module will generate an event upon
    * reception of the first byte which is added to the RX buffer.
    *
    * @param[out] p_byte Pointer to an address where next byte received on the UART will be copied.
    *
    * @retval NRF_SUCCESS If a byte has been received and pushed to the pointer provided.
    * @retval NRF_ERROR_NOT_FOUND If no byte is available in the RX buffer of the app_uart module.
    */
    uint32_t app_uart_get(nrf_uart_obj_t * uart_obj, uint8_t * p_byte);

    /**@brief Function for putting a byte on the UART.
    *
    * @details This call is non-blocking.
    *
    * @param[in] byte Byte to be transmitted on the UART.
    *
    * @retval NRF_SUCCESS If the byte was successfully put on the TX buffer for transmission.
    * @retval NRF_ERROR_NO_MEM If no more space is available in the TX buffer.
    * NRF_ERROR_NO_MEM may occur if flow control is enabled and CTS signal
    * is high for a long period and the buffer fills up.
    * @retval NRF_ERROR_INTERNAL If UART driver reported error.
    */
    uint32_t app_uart_put(nrf_uart_obj_t * uart_obj, uint8_t byte);

    /**@brief Function for flushing the RX and TX buffers (Only valid if FIFO is used).
    * This function does nothing if FIFO is not used.
    *
    * @retval NRF_SUCCESS Flushing completed (Current implementation will always succeed).
    */
    uint32_t app_uart_flush(nrf_uart_obj_t * uart_obj);

    /**@brief Function for closing the UART module.
    *
    * @retval NRF_SUCCESS If successfully closed.
    * @retval NRF_ERROR_INVALID_PARAM If an invalid user id is provided or the user id differs from
    * the current active user.
    */
    uint32_t app_uart_close(nrf_uart_obj_t * uart_obj);


    #ifdef __cplusplus
    }
    #endif

    #endif //APP_UART_H__

    /** @} */

    (2)app_uart_fifo.c

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    /**
    * Copyright (c) 2015 - 2020, Nordic Semiconductor ASA
    *
    * All rights reserved.
    *
    * Redistribution and use in source and binary forms, with or without modification,
    * are permitted provided that the following conditions are met:
    *
    * 1. Redistributions of source code must retain the above copyright notice, this
    * list of conditions and the following disclaimer.
    *
    * 2. Redistributions in binary form, except as embedded into a Nordic
    * Semiconductor ASA integrated circuit in a product or a software update for
    * such product, must reproduce the above copyright notice, this list of
    * conditions and the following disclaimer in the documentation and/or other
    * materials provided with the distribution.
    *
    * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
    * contributors may be used to endorse or promote products derived from this
    * software without specific prior written permission.
    *
    * 4. This software, with or without modification, must only be used with a
    * Nordic Semiconductor ASA integrated circuit.
    *
    * 5. Any software provided in binary form under this license must not be reverse
    * engineered, decompiled, modified and/or disassembled.
    *
    * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
    * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
    * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
    * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
    * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
    * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    *
    */
    #include "sdk_common.h"
    #if NRF_MODULE_ENABLED(APP_UART)
    #include "app_uart.h"

    #include "nrf_drv_uart.h"
    #include "nrf_assert.h"

    //static nrf_drv_uart_t app_uart_inst = NRF_DRV_UART_INSTANCE(APP_UART_DRIVER_INSTANCE);

    static __INLINE uint32_t fifo_length(app_fifo_t * const fifo)
    {
    uint32_t tmp = fifo->read_pos;
    return fifo->write_pos - tmp;
    }

    #define FIFO_LENGTH(F) fifo_length(&F) /**< Macro to calculate length of a FIFO. */


    //static app_uart_event_handler_t m_event_handler; /**< Event handler function. */
    //static uint8_t tx_buffer[1];
    //static uint8_t rx_buffer[1];
    //static bool m_rx_ovf;

    //static app_fifo_t m_rx_fifo; /**< RX FIFO buffer for storing data received on the UART until the application fetches them using app_uart_get(). */
    //static app_fifo_t m_tx_fifo; /**< TX FIFO buffer for storing data to be transmitted on the UART when TXD is ready. Data is put to the buffer on using app_uart_put(). */

    static void uart_event_handler(nrf_drv_uart_event_t * p_event, void* p_context)
    {
    app_uart_evt_t app_uart_event;
    uint32_t err_code;

    nrf_uart_obj_t * uart_obj = (nrf_uart_obj_t *)p_context;

    switch (p_event->type)
    {
    case NRF_DRV_UART_EVT_RX_DONE:
    // If 0, then this is a RXTO event with no new bytes.
    if(p_event->data.rxtx.bytes == 0)
    {
    // A new start RX is needed to continue to receive data
    (void)nrf_drv_uart_rx(&uart_obj->instance, uart_obj->rx_buffer, 1);
    break;
    }

    // Write received byte to FIFO.
    err_code = app_fifo_put(&uart_obj->rx_fifo, p_event->data.rxtx.p_data[0]);
    if (err_code != NRF_SUCCESS)
    {
    app_uart_event.evt_type = APP_UART_FIFO_ERROR;
    app_uart_event.data.error_code = err_code;

    if (uart_obj->event_handler) {
    uart_obj->event_handler(&app_uart_event);
    }
    }
    // Notify that there are data available.
    else if (FIFO_LENGTH(uart_obj->rx_fifo) != 0)
    {
    app_uart_event.evt_type = APP_UART_DATA_READY;

    if (uart_obj->event_handler) {
    uart_obj->event_handler(&app_uart_event);
    }
    }

    // Start new RX if size in buffer.
    if (FIFO_LENGTH(uart_obj->rx_fifo) <= uart_obj->rx_fifo.buf_size_mask)
    {
    (void)nrf_drv_uart_rx(&uart_obj->instance, uart_obj->rx_buffer, 1);
    }
    else
    {
    // Overflow in RX FIFO.
    uart_obj->rx_ovf = true;
    }

    break;

    case NRF_DRV_UART_EVT_ERROR:
    app_uart_event.evt_type = APP_UART_COMMUNICATION_ERROR;
    app_uart_event.data.error_communication = p_event->data.error.error_mask;
    (void)nrf_drv_uart_rx(&uart_obj->instance, uart_obj->rx_buffer, 1);

    if (uart_obj->event_handler) {
    uart_obj->event_handler(&app_uart_event);
    }

    break;

    case NRF_DRV_UART_EVT_TX_DONE:
    // Get next byte from FIFO.
    if (app_fifo_get(&uart_obj->tx_fifo, uart_obj->tx_buffer) == NRF_SUCCESS)
    {
    (void)nrf_drv_uart_tx(&uart_obj->instance, uart_obj->tx_buffer, 1);
    }
    else
    {
    // Last byte from FIFO transmitted, notify the application.
    app_uart_event.evt_type = APP_UART_TX_EMPTY;

    if (uart_obj->event_handler) {
    uart_obj->event_handler(&app_uart_event);
    }
    }
    break;

    default:
    break;
    }
    }


    uint32_t app_uart_init(nrf_uart_obj_t * uart_obj,
    app_uart_buffers_t * p_buffers,
    app_irq_priority_t irq_priority)
    {
    uint32_t err_code;

    // m_event_handler = event_handler;

    if (p_buffers == NULL)
    {
    return NRF_ERROR_INVALID_PARAM;
    }

    // Configure buffer RX buffer.
    err_code = app_fifo_init(&uart_obj->rx_fifo, p_buffers->rx_buf, p_buffers->rx_buf_size);
    VERIFY_SUCCESS(err_code);

    // Configure buffer TX buffer.
    err_code = app_fifo_init(&uart_obj->tx_fifo, p_buffers->tx_buf, p_buffers->tx_buf_size);
    VERIFY_SUCCESS(err_code);

    nrf_drv_uart_config_t config = NRF_DRV_UART_DEFAULT_CONFIG;
    config.baudrate = (nrf_uart_baudrate_t)uart_obj->comm_params->baud_rate;
    config.hwfc = (uart_obj->comm_params->flow_control == APP_UART_FLOW_CONTROL_DISABLED) ?
    NRF_UART_HWFC_DISABLED : NRF_UART_HWFC_ENABLED;
    config.interrupt_priority = irq_priority;
    config.parity = uart_obj->comm_params->use_parity ? NRF_UART_PARITY_INCLUDED : NRF_UART_PARITY_EXCLUDED;
    config.pselcts = uart_obj->comm_params->cts_pin_no;
    config.pselrts = uart_obj->comm_params->rts_pin_no;
    config.pselrxd = uart_obj->comm_params->rx_pin_no;
    config.pseltxd = uart_obj->comm_params->tx_pin_no;
    config.p_context = uart_obj;

    err_code = nrf_drv_uart_init(&uart_obj->instance, &config, uart_event_handler);
    VERIFY_SUCCESS(err_code);
    uart_obj->rx_ovf = false;

    // Turn on receiver if RX pin is connected
    if (uart_obj->comm_params->rx_pin_no != UART_PIN_DISCONNECTED)
    {
    return nrf_drv_uart_rx(&uart_obj->instance, uart_obj->rx_buffer,1);
    }
    else
    {
    return NRF_SUCCESS;
    }
    }


    uint32_t app_uart_flush(nrf_uart_obj_t * uart_obj)
    {
    uint32_t err_code;

    err_code = app_fifo_flush(&uart_obj->rx_fifo);
    VERIFY_SUCCESS(err_code);

    err_code = app_fifo_flush(&uart_obj->tx_fifo);
    VERIFY_SUCCESS(err_code);

    return NRF_SUCCESS;
    }


    uint32_t app_uart_get(nrf_uart_obj_t * uart_obj, uint8_t * p_byte)
    {
    ASSERT(p_byte);
    bool rx_ovf = uart_obj->rx_ovf;

    ret_code_t err_code = app_fifo_get(&uart_obj->rx_fifo, p_byte);

    // If FIFO was full new request to receive one byte was not scheduled. Must be done here.
    if (rx_ovf)
    {
    uart_obj->rx_ovf = false;
    uint32_t uart_err_code = nrf_drv_uart_rx(&uart_obj->instance, uart_obj->rx_buffer, 1);

    // RX resume should never fail.
    APP_ERROR_CHECK(uart_err_code);
    }

    return err_code;
    }


    uint32_t app_uart_put(nrf_uart_obj_t * uart_obj, uint8_t byte)
    {
    uint32_t err_code;
    err_code = app_fifo_put(&uart_obj->tx_fifo, byte);
    if (err_code == NRF_SUCCESS)
    {
    // The new byte has been added to FIFO. It will be picked up from there
    // (in 'uart_event_handler') when all preceding bytes are transmitted.
    // But if UART is not transmitting anything at the moment, we must start
    // a new transmission here.
    if (!nrf_drv_uart_tx_in_progress(&uart_obj->instance))
    {
    // This operation should be almost always successful, since we've
    // just added a byte to FIFO, but if some bigger delay occurred
    // (some heavy interrupt handler routine has been executed) since
    // that time, FIFO might be empty already.
    if (app_fifo_get(&uart_obj->tx_fifo, uart_obj->tx_buffer) == NRF_SUCCESS)
    {
    err_code = nrf_drv_uart_tx(&uart_obj->instance, uart_obj->tx_buffer, 1);
    }
    }
    }
    return err_code;
    }


    uint32_t app_uart_close(nrf_uart_obj_t * uart_obj)
    {
    nrf_drv_uart_uninit(&uart_obj->instance);
    return NRF_SUCCESS;
    }

    #endif //NRF_MODULE_ENABLED(APP_UART)

    (3)retarget.c

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    /**
    * Copyright (c) 2014 - 2020, Nordic Semiconductor ASA
    *
    * All rights reserved.
    *
    * Redistribution and use in source and binary forms, with or without modification,
    * are permitted provided that the following conditions are met:
    *
    * 1. Redistributions of source code must retain the above copyright notice, this
    * list of conditions and the following disclaimer.
    *
    * 2. Redistributions in binary form, except as embedded into a Nordic
    * Semiconductor ASA integrated circuit in a product or a software update for
    * such product, must reproduce the above copyright notice, this list of
    * conditions and the following disclaimer in the documentation and/or other
    * materials provided with the distribution.
    *
    * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
    * contributors may be used to endorse or promote products derived from this
    * software without specific prior written permission.
    *
    * 4. This software, with or without modification, must only be used with a
    * Nordic Semiconductor ASA integrated circuit.
    *
    * 5. Any software provided in binary form under this license must not be reverse
    * engineered, decompiled, modified and/or disassembled.
    *
    * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
    * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
    * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
    * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
    * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
    * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    *
    */
    #include "sdk_common.h"
    /** @file
    *
    * @defgroup retarget Retarget layer for stdio functions
    * @{
    * @ingroup app_common
    * @} */
    #if NRF_MODULE_ENABLED(RETARGET)
    #if !defined(NRF_LOG_USES_RTT) || NRF_LOG_USES_RTT != 1
    #if !defined(HAS_SIMPLE_UART_RETARGET)


    #include <stdio.h>
    #include <stdint.h>

    #include "app_uart.h"
    #include "nrf_error.h"


    #if defined(__CC_ARM)

    // This part is taken from MDK-ARM template file and is required here to prevent
    // linker from selecting libraries functions that use semihosting and failing
    // because of multiple definitions of fgetc() and fputc().
    // Refer to: http://www.keil.com/support/man/docs/gsac/gsac_retargetcortex.htm
    // -- BEGIN --
    struct __FILE { int handle; /* Add whatever you need here */ };
    FILE __stdout;
    FILE __stdin;
    // --- END ---

    extern uint32_t _app_uart_get(uint8_t * p_byte);
    extern uint32_t _app_uart_put(uint8_t byte);

    int fgetc(FILE * p_file)
    {
    uint8_t input;
    while (_app_uart_get(&input) == NRF_ERROR_NOT_FOUND)
    {
    // No implementation needed.
    }
    return input;
    }

    int fputc(int ch, FILE * p_file)
    {
    UNUSED_PARAMETER(p_file);

    UNUSED_VARIABLE(_app_uart_put((uint8_t)ch));
    return ch;
    }

    #elif defined(__GNUC__) && defined(__SES_ARM)

    int __getchar(FILE * p_file)
    {
    uint8_t input;
    while (app_uart_get(&input) == NRF_ERROR_NOT_FOUND)
    {
    // No implementation needed.
    }
    return input;
    }

    #if defined(__SES_VERSION) && (__SES_VERSION >= 34000)
    int __putchar(int ch, __printf_tag_ptr tag_ptr)
    {
    UNUSED_PARAMETER(tag_ptr);

    UNUSED_VARIABLE(app_uart_put((uint8_t)ch));
    return ch;
    }
    #else
    int __putchar(int ch, FILE * p_file)
    {
    UNUSED_PARAMETER(p_file);

    UNUSED_VARIABLE(app_uart_put((uint8_t)ch));
    return ch;
    }
    #endif

    #elif defined(__GNUC__) && !defined(__SES_ARM)

    int _write(int file, const char * p_char, int len)
    {
    int i;

    UNUSED_PARAMETER(file);

    for (i = 0; i < len; i++)
    {
    UNUSED_VARIABLE(app_uart_put(*p_char++));
    }

    return len;
    }

    int _read(int file, char * p_char, int len)
    {
    UNUSED_PARAMETER(file);
    while (app_uart_get((uint8_t *)p_char) == NRF_ERROR_NOT_FOUND)
    {
    // No implementation needed.
    }

    return 1;
    }
    #elif defined(__ICCARM__)

    size_t __write(int handle, const unsigned char * buffer, size_t size)
    {
    int i;
    UNUSED_PARAMETER(handle);
    for (i = 0; i < size; i++)
    {
    UNUSED_VARIABLE(app_uart_put(*buffer++));
    }
    return size;
    }

    size_t __read(int handle, unsigned char * buffer, size_t size)
    {
    UNUSED_PARAMETER(handle);
    UNUSED_PARAMETER(size);
    while (app_uart_get((uint8_t *)buffer) == NRF_ERROR_NOT_FOUND)
    {
    // No implementation needed.
    }

    return 1;
    }

    long __lseek(int handle, long offset, int whence)
    {
    return -1;
    }
    int __close(int handle)
    {
    return 0;
    }
    int remove(const char * filename)
    {
    return 0;
    }

    #endif

    #endif // !defined(HAS_SIMPLE_UART_RETARGET)
    #endif // NRF_LOG_USES_RTT != 1
    #endif //NRF_MODULE_ENABLED(RETARGET)
  2. 在 sdk_config.h 配置文件中勾选启用以下配置
    (1)nRF_Drivers 目录下的 NRFX_PRS_ENABLEDNRFX_UARTE_ENABLEDNRFX_UART_ENABLEDUART_ENABLED
    (2)nRF_Libraries 目录下的 APP_FIFO_ENABLEDAPP_UART_ENABLEDRETARGET_ENABLDNRF_STRERROR_ENABLED

  3. 在工程中添加以下文件并设置好对应 .h 文件的路径
    (1)\integration\nrfx\legacy\ 目录下的 nrf_drv_uart.c
    (2)\modules\nrfx\drivers\src\prs 目录下的 nrfx_prs.c
    (3)\modules\nrfx\drivers\src\ 目录下的 nrfx_uart.cnrfx_uarte.c
    (4)\components\libraries\uart\ 目录下的 app_uart_fifo.c
    (5)\components\libraries\fifo\ 目录下的 app_fifo.c
    (6)\components\libraries\uart\ 目录下的 retarget.c

  4. 完成以上步骤后即可开始设计你自己的初始化和收发函数,以下是我自己的设计,供大家参考
    (1)platform_uart.c

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    #include "platform_uart.h"
    #include <nrf_uart.h>
    #include <nrf_log.h>

    #define UART0_RECV_BUF_SIZE 2048
    #define UART1_RECV_BUF_SIZE 2048
    #define UART_SEND_FMT_BUF_SIZE ck256

    APP_UART_DEF(uart0, 0, UART0_RECV_BUF_SIZE, NULL);
    APP_UART_DEF(uart1, 1, UART1_RECV_BUF_SIZE, NULL);


    uint32_t _app_uart_get(uint8_t * p_byte)
    {
    return app_uart_get(&uart1, p_byte);
    }
    uint32_t _app_uart_put(uint8_t byte)
    {
    return app_uart_put(&uart1, byte);
    }


    void uart_init(uint8_t index, uint32_t rx_pin, uint32_t tx_pin, uint32_t baud_rate, app_irq_priority_t irq_priority)
    {
    uint32_t errCode;
    nrf_uart_obj_t *nrf_uart_obj;
    static app_uart_buffers_t *buffer;

    if (index == 0) {
    nrf_uart_obj = &uart0;
    buffer = &uart0_buffers;
    } else if (index == 1) {
    nrf_uart_obj = &uart1;
    buffer = &uart1_buffers;
    } else {
    return;
    }

    app_uart_comm_params_t commParams;

    commParams.rx_pin_no = rx_pin;
    commParams.tx_pin_no = tx_pin;
    commParams.rts_pin_no = NRF_UART_PSEL_DISCONNECTED;
    commParams.cts_pin_no = NRF_UART_PSEL_DISCONNECTED;
    commParams.flow_control = APP_UART_FLOW_CONTROL_DISABLED;
    commParams.use_parity = false;
    commParams.baud_rate = baud_rate;

    nrf_uart_obj->comm_params = &commParams;
    errCode = app_uart_init(nrf_uart_obj, buffer, irq_priority);
    APP_ERROR_CHECK(errCode);
    }

    void uart0_init(uint32_t rx_pin, uint32_t tx_pin, uint32_t baud_rate)
    {
    uart_init(0, rx_pin, tx_pin, baud_rate, APP_IRQ_PRIORITY_HIGHEST);
    }

    void uart1_init(uint32_t rx_pin, uint32_t tx_pin, uint32_t baud_rate)
    {
    uart_init(1, rx_pin, tx_pin, baud_rate, APP_IRQ_PRIORITY_HIGHEST);
    }


    static void uart_send(uint8_t index, const void *send_buf, const int send_count)
    {
    uint8_t *_send_buf = (uint8_t*)send_buf;

    nrf_uart_obj_t *nrf_uart_obj;

    if (index == 0) {
    nrf_uart_obj = &uart0;
    } else if (index == 1) {
    nrf_uart_obj = &uart1;
    } else {
    return;
    }

    for (int i = 0; i < send_count; i++) {
    while (app_uart_put(nrf_uart_obj, _send_buf[i]) != NRF_SUCCESS);
    }
    }


    void uart0_send(const void *send_buf, const int send_count)
    {
    uart_send(0, send_buf, send_count);
    }

    void uart1_send(const void *send_buf, const int send_count)
    {
    uart_send(1, send_buf, send_count);
    }


    static int uart_receive(uint8_t index, void *receive_buf, const int receive_count)
    {
    uint8_t *_receive_buf = (uint8_t*)receive_buf;

    nrf_uart_obj_t *nrf_uart_obj;

    if (index == 0) {
    nrf_uart_obj = &uart0;
    } else if (index == 1) {
    nrf_uart_obj = &uart1;
    } else {
    return -1;
    }

    int i, receive_count_real;

    for(i = 0, receive_count_real = 0; i < receive_count; i++) {
    if(app_uart_get(nrf_uart_obj, &_receive_buf[i]) != NRF_SUCCESS) {
    break;
    } else {
    receive_count_real++;
    }
    }

    return receive_count_real;
    }

    int uart0_receive(void *receive_buf, const int receive_count)
    {
    return uart_receive(0, receive_buf, receive_count);
    }

    int uart1_receive(void *receive_buf, const int receive_count)
    {
    return uart_receive(1, receive_buf, receive_count);
    }

    (2)platform_uart.h

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #ifndef __PLATFORM_UART_H__
    #define __PLATFORM_UART_H__
    #include <app_uart.h>
    #include <stdint.h>

    void uart_init(uint8_t index, uint32_t rx_pin, uint32_t tx_pin, uint32_t baud_rate, app_irq_priority_t irq_priority);

    void uart0_init(uint32_t rx_pin, uint32_t tx_pin, uint32_t baud_rate);
    void uart1_init(uint32_t rx_pin, uint32_t tx_pin, uint32_t baud_rate);

    void uart0_send(const void *send_buf, const int send_count);
    void uart1_send(const void *send_buf, const int send_count);

    int uart0_receive(void *receive_buf, const int receive_count);
    int uart1_receive(void *receive_buf, const int receive_count);

    #endif

参考:https://blog.csdn.net/qq_36347513/article/details/111319840