






#define APP_UART_FIFO_INIT(P_COMM_PARAMS, RX_BUF_SIZE, TX_BUF_SIZE, EVT_HANDLER, IRQ_PRIO, ERR_CODE) \
do \
{ \
app_uart_buffers_t buffers; \
static uint8_t rx_buf[RX_BUF_SIZE]; \
static uint8_t tx_buf[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)
代码理解:
代码概述 此代码定义了一个名为 APP_UART_FIFO_INIT 的宏,其用途是初始化一个基于 FIFO(先进先出)机制的 UART(通用异步收发传输器)通信。借助这个宏,你能够轻松地设置 UART 通信所需的参数,包含接收缓冲区、发送缓冲区、事件处理函数以及中断优先级等。
宏定义参数
• P_COMM_PARAMS:指向 UART 通信参数结构体的指针,该结构体里包含了波特率、数据位、停止位等 UART 通信所需的基本参数。
结构体定义如下 :
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;
结构体解析:用于配置 UART(通用异步收发传输器)通信参数。下面解释结构体中每个成员的作用:
// 定义一个名为 app_uart_comm_params_t 的结构体,用于配置 UART 通信参数
typedef struct
{
// RX 引脚编号,用于接收数据
uint32_t rx_pin_no; /**< RX pin number. */
// TX 引脚编号,用于发送数据
uint32_t tx_pin_no; /**< TX pin number. */
// RTS(请求发送)引脚编号,仅在启用流控制时使用
uint32_t rts_pin_no; /**< RTS pin number, only used if flow control is enabled. */
// CTS(清除发送)引脚编号,仅在启用流控制时使用
uint32_t cts_pin_no; /**< CTS pin number, only used if flow control is enabled. */
// 流控制设置,如果使用流控制,系统将基于 CTS 信号使用低功耗 UART 模式
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. */
// 是否使用奇偶校验,TRUE 表示使用偶校验,FALSE 表示不使用奇偶校验
bool use_parity; /**< Even parity if TRUE, no parity if FALSE. */
// 波特率配置,用于设置数据传输的速率
uint32_t baud_rate; /**< Baud rate configuration. */
} app_uart_comm_params_t;
其中:app_uart_flow_control_t(控制流)是一个枚举类型,其定义如下:
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;
// 定义 app_uart_flow_control_t 枚举类型,用于表示 UART 硬件流控制状态
typedef enum
{
// UART 硬件流控制禁用
APP_UART_FLOW_CONTROL_DISABLED, /**< UART Hw Flow Control is disabled. */
// 标准 UART 硬件流控制启用
APP_UART_FLOW_CONTROL_ENABLED, /**< Standard UART Hw Flow Control is enabled. */
} app_uart_flow_control_t;
再回到开始的宏参数:
• RX_BUF_SIZE:接收缓冲区的大小,也就是用于存储从 UART 接收到的数据的缓冲区大小。 • TX_BUF_SIZE:发送缓冲区的大小,即用于存储要通过 UART 发送出去的数据的缓冲区大小。 • EVT_HANDLER:UART 事件处理函数的指针,当 UART 发生特定事件(像数据接收、发送完成等)时,会调用这个函数。
• IRQ_PRIO:UART 中断的优先级,用于设置 UART 中断在系统中的优先级。
• ERR_CODE:用于存储 UART 初始化的错误码,若初始化成功,该变量会被赋值为 0;若失败,则会被赋值为相应的错误码。
代码详细解析
#define APP_UART_FIFO_INIT(P_COMM_PARAMS, RX_BUF_SIZE, TX_BUF_SIZE, EVT_HANDLER, IRQ_PRIO, ERR_CODE) \
do \
{ \
app_uart_buffers_t buffers; \
static uint8_t rx_buf[RX_BUF_SIZE]; \
static uint8_t tx_buf[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)
1. 定义缓冲区和变量:
app_uart_buffers_t buffers;:定义一个 app_uart_buffers_t 类型的结构体变量 buffers,该结构体用于存储接收和发送缓冲区的信息。
app_uart_buffers_t 类型的结构体定义如下 :
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;
static uint8_t rx_buf[RX_BUF_SIZE];:定义一个静态的接收缓冲区数组 rx_buf,其大小由 RX_BUF_SIZE 决定。
static uint8_t tx_buf[TX_BUF_SIZE];:定义一个静态的发送缓冲区数组 tx_buf,其大小由 TX_BUF_SIZE 决定。
2. 初始化缓冲区信息:
buffers.rx_buf = rx_buf;:把 rx_buf 数组的地址赋值给 buffers 结构体的 rx_buf 成员。
buffers.rx_buf_size = sizeof (rx_buf);:把 rx_buf 数组的大小赋值给 buffers 结构体的 rx_buf_size 成员。
buffers.tx_buf = tx_buf;:把 tx_buf 数组的地址赋值给 buffers 结构体的 tx_buf 成员。
buffers.tx_buf_size = sizeof (tx_buf);:把 tx_buf 数组的大小赋值给 buffers 结构体的 tx_buf_size 成员。
3 调用 UART 初始化函数:
ERR_CODE = app_uart_init(P_COMM_PARAMS, &buffers, EVT_HANDLER, IRQ_PRIO);:调用 app_uart_init 函数来初始化 UART 通信,将初始化的错误码存储在 ERR_CODE 变量中。
下面是一个简单的使用示例:
#include <stdio.h>
// 假设的 UART 通信参数结构体
typedef struct {
int baud_rate;
// 其他参数...
} app_uart_comm_params_t;
// 假设的 UART 缓冲区结构体
typedef struct {
uint8_t *rx_buf;
size_t rx_buf_size;
uint8_t *tx_buf;
size_t tx_buf_size;
} app_uart_buffers_t;
// 假设的 UART 初始化函数
int app_uart_init(app_uart_comm_params_t *p_comm_params, app_uart_buffers_t *p_buffers, void (*evt_handler)(void), int irq_prio) {
// 实际的初始化代码
return 0; // 假设初始化成功
}
// 假设的 UART 事件处理函数
void uart_evt_handler(void) {
// 处理 UART 事件
}
// 定义宏
#define APP_UART_FIFO_INIT(P_COMM_PARAMS, RX_BUF_SIZE, TX_BUF_SIZE, EVT_HANDLER, IRQ_PRIO, ERR_CODE) \
do \
{ \
app_uart_buffers_t buffers; \
static uint8_t rx_buf[RX_BUF_SIZE]; \
static uint8_t tx_buf[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)
int main() {
app_uart_comm_params_t comm_params = {115200}; // 波特率设置为 115200
int err_code;
APP_UART_FIFO_INIT(&comm_params, 256, 256, uart_evt_handler, 1, err_code);
if (err_code == 0) {
printf("UART initialization successful.\n");
} else {
printf("UART initialization failed with error code: %d\n", err_code);
}
return 0;
}
在这个示例中,我们定义了一个简单的 UART 通信系统,并且使用 APP_UART_FIFO_INIT 宏来初始化 UART 通信。若初始化成功,会输出相应的提示信息;若失败,则会输出错误码。
(2)app_uart_init函数学习
uint32_t app_uart_init(const app_uart_comm_params_t * p_comm_params,
app_uart_buffers_t * p_buffers,
app_uart_event_handler_t event_handler,
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(&m_rx_fifo, p_buffers->rx_buf, p_buffers->rx_buf_size);
VERIFY_SUCCESS(err_code);
// Configure buffer TX buffer.
err_code = app_fifo_init(&m_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)p_comm_params->baud_rate;
config.hwfc = (p_comm_params->flow_control == APP_UART_FLOW_CONTROL_DISABLED) ?
NRF_UART_HWFC_DISABLED : NRF_UART_HWFC_ENABLED;
config.interrupt_priority = irq_priority;
config.parity = p_comm_params->use_parity ? NRF_UART_PARITY_INCLUDED : NRF_UART_PARITY_EXCLUDED;
config.pselcts = p_comm_params->cts_pin_no;
config.pselrts = p_comm_params->rts_pin_no;
config.pselrxd = p_comm_params->rx_pin_no;
config.pseltxd = p_comm_params->tx_pin_no;
err_code = nrf_drv_uart_init(&app_uart_inst, &config, uart_event_handler);
VERIFY_SUCCESS(err_code);
m_rx_ovf = false;
// Turn on receiver if RX pin is connected
if (p_comm_params->rx_pin_no != UART_PIN_DISCONNECTED)
{
return nrf_drv_uart_rx(&app_uart_inst, rx_buffer,1);
}
else
{
return NRF_SUCCESS;
}
}
(a)app_uart_init(const app_uart_comm_params_t * p_comm_params,
app_uart_buffers_t * p_buffers,
app_uart_event_handler_t event_handler,
app_irq_priority_t irq_priority)
{
* 此函数用于初始化 UART 通信,配置通信参数、缓冲区、事件处理函数和中断优先级。
*
* @param p_comm_params 指向 app_uart_comm_params_t 结构体的指针,包含 UART 通信参数,如引脚编号、流控制设置、奇偶校验和波特率等。
* @param p_buffers 指向 app_uart_buffers_t 结构体的指针,该结构体应包含用于 UART 数据收发的缓冲区。
* @param event_handler 指向 UART 事件处理函数的指针,当 UART 发生特定事件(如接收数据、发送完成等)时会调用此函数。
* @param irq_priority UART 中断的优先级,用于确定 UART 中断在系统中的处理顺序。
*
* @return 函数返回值类型未给出,一般可能返回一个状态码,用于表示初始化是否成功。
*/
由于不清楚 app_uart_buffers_t、app_uart_event_handler_t 和 app_irq_priority_t 的具体定义,下面给出一个简单的模拟实现:
#include <stdio.h>
#include <stdint.h>
// 假设 app_uart_flow_control_t 定义如下
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;
// 假设 app_uart_comm_params_t 定义如下
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;
// 假设 app_uart_buffers_t 定义如下
typedef struct
{
uint8_t *rx_buffer;
uint8_t *tx_buffer;
size_t rx_buffer_size;
size_t tx_buffer_size;
} app_uart_buffers_t;
// 假设 app_uart_event_handler_t 是一个函数指针类型
typedef void (*app_uart_event_handler_t)(void);
// 假设 app_irq_priority_t 是一个枚举类型
typedef enum
{
APP_IRQ_PRIORITY_LOW,
APP_IRQ_PRIORITY_MEDIUM,
APP_IRQ_PRIORITY_HIGH
} app_irq_priority_t;
// 模拟实现 app_uart_init 函数
int app_uart_init(const app_uart_comm_params_t * p_comm_params,
app_uart_buffers_t * p_buffers,
app_uart_event_handler_t event_handler,
app_irq_priority_t irq_priority)
{
if (p_comm_params == NULL || p_buffers == NULL || event_handler == NULL)
{
return -1; // 输入参数无效
}
// 模拟配置 UART 通信参数
printf("Initializing UART with the following parameters:\n");
printf("RX Pin: %u\n", p_comm_params->rx_pin_no);
printf("TX Pin: %u\n", p_comm_params->tx_pin_no);
printf("Flow Control: %s\n", p_comm_params->flow_control == APP_UART_FLOW_CONTROL_ENABLED ? "Enabled" : "Disabled");
printf("Parity: %s\n", p_comm_params->use_parity ? "Even" : "None");
printf("Baud Rate: %u\n", p_comm_params->baud_rate);
// 模拟配置缓冲区
printf("RX Buffer Size: %zu\n", p_buffers->rx_buffer_size);
printf("TX Buffer Size: %zu\n", p_buffers->tx_buffer_size);
// 模拟设置事件处理函数
// 这里可以保存 event_handler 指针,在 UART 事件发生时调用
printf("Event handler set.\n");
// 模拟设置中断优先级
printf("Interrupt priority set to ");
switch (irq_priority)
{
case APP_IRQ_PRIORITY_LOW:
printf("LOW\n");
break;
case APP_IRQ_PRIORITY_MEDIUM:
printf("MEDIUM\n");
break;
case APP_IRQ_PRIORITY_HIGH:
printf("HIGH\n");
break;
default:
printf("UNKNOWN\n");
break;
}
return 0; // 初始化成功
}
使用示例
int main()
{
app_uart_comm_params_t comm_params = {
.rx_pin_no = 1,
.tx_pin_no = 2,
.rts_pin_no = 3,
.cts_pin_no = 4,
.flow_control = APP_UART_FLOW_CONTROL_ENABLED,
.use_parity = false,
.baud_rate = 115200
};
uint8_t rx_buffer[100];
uint8_t tx_buffer[100];
app_uart_buffers_t buffers = {
.rx_buffer = rx_buffer,
.tx_buffer = tx_buffer,
.rx_buffer_size = sizeof(rx_buffer),
.tx_buffer_size = sizeof(tx_buffer)
};
void dummy_event_handler()
{
// 处理 UART 事件的代码
}
app_irq_priority_t irq_priority = APP_IRQ_PRIORITY_MEDIUM;
int result = app_uart_init(&comm_params, &buffers, dummy_event_handler, irq_priority);
if (result == 0)
{
printf("UART initialization successful.\n");
}
else
{
printf("UART initialization failed.\n");
}
return 0;
}
上述代码中,首先为 app_uart_init 函数声明添加了详细注释,然后模拟实现了该函数,最后给出了一个使用示例,展示了如何调用 app_uart_init 函数进行 UART 初始化。
(b)