Nordic52810入门篇

您所在的位置:网站首页 52832串口 Nordic52810入门篇

Nordic52810入门篇

2024-07-09 18:40| 来源: 网络整理| 查看: 265

一、前言

Nordic52810串口外设手册命名为 UARTE,直译的意思就是带EasyDma的通用异步收发器 ; 52810仅一路UARTE0外设,应用中如果需要多路串口进行通信的话,可以重新映射到任意的GPIO引脚上,实现异步的串口切换(无法同时进行多路收发)

二、工作原理详解

UARTE功能特点

全双工硬件流控制EasyDMA高达1Mpbs波特率

UARTE原理框图

如下图,RXD输入信号通过FIFO经由EasyDMA输出到RXD缓存中,输出反之EasyDMA读取TXD缓存,调制后经由TXD引脚发送

原理框图

数据发送

如下图

TXD.MAXCNT计数器中存放了需要发送的数据长度,使能STARTTX任务后即开始进行发送(将会生成一个TXSTARTTED指示开始发送)每发送一个字节后,会触发一个TXDRDY事件当数据发送完成后(MAXCNT)将会生成ENDTX事件使能STOPTX任务后,串口发送停止时将会触发一个TXSTOPPED事件当UARTE发送器停止时,如果尚未生成ENDTX事件,UARTE将显式生成ENDTX事件如果启用了发送流控CTS,当CTS被停用时传输将自动挂起,当CTS再次被激活时将继续传输

在这里插入图片描述

数据接收

EasyDma将串口接收的数据传到数据缓存中,如下图

RX缓存地址通过RXD.PTR寄存器指定RX缓存大小由RXD.MAXCNT寄存器配置,当RX缓存填满后将会触发ENDRX事件RXD每接收一个字节数据,将会产生RXDRDY事件RXD.AMOUNT寄存器指示有多少数据已经被搬移到RAM中

在这里插入图片描述

三、寄存器 SHORTS [5-6]:地址偏移0x200,ENDRX_STARTRX写1开启DMA接收任务,ENDRX_STOPRX写1停止接收任务INTEN [0-2/4/7-9/17/19-20/22]:中断控制寄存器,写0禁用中断,写1使能中断INTENSET:中断使能寄存器,写1使能中断,写0无效INTENCLR:中断禁用寄存器,写1禁止中断,写0无效ERRORSRC:错误状态寄存器,当串口异常触发时,可读取该寄存器(帧错误、校验错误),写1可进行清状态ENABLE:写1使能串口,写1禁用串口PSEL.RTS[0-4]: RTS映射寄存器,将串口RTS信号关联到指定的引脚PSEL.TXD[0-4]:TXD映射寄存器,将串口TXD信号关联到指定的引脚PSEL.CTS[0-4]:CTS映射寄存器,将串口CTS信号关联到指定的引脚PSEL.RXD[0-4]:RXD映射寄存器,将串口RXD信号关联到指定的引脚BAUDRATE[0-31]:波特率控制寄存器(1200baud - 1Mbaud)RXD.PTR:接收数据制作RXD.MAXCNT:接收缓存数据大小RXD.AMOUNT:接收数据长度TXD.PTR:发送数据指针TXD.MAXCNT:发送缓存数据大小TXD.AMOUNT: 发送数据长度CONFIG: 配置寄存器,配置校验与硬件流控 四、相关接口

UARTE的相关接口在nrfx_uarte.c中

串口UARTE初始化接口nrfx_uarte_init

nrfx_err_t nrfx_uarte_init(nrfx_uarte_t const * p_instance, nrfx_uarte_config_t const * p_config, nrfx_uarte_event_handler_t event_handler) { NRFX_ASSERT(p_config); uarte_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; nrfx_err_t err_code = NRFX_SUCCESS; if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED) { err_code = NRFX_ERROR_INVALID_STATE; NRFX_LOG_WARNING("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); return err_code; } #if NRFX_CHECK(NRFX_PRS_ENABLED) static nrfx_irq_handler_t const irq_handlers[NRFX_UARTE_ENABLED_COUNT] = { #if NRFX_CHECK(NRFX_UARTE0_ENABLED) nrfx_uarte_0_irq_handler, #endif #if NRFX_CHECK(NRFX_UARTE1_ENABLED) nrfx_uarte_1_irq_handler, #endif }; if (nrfx_prs_acquire(p_instance->p_reg, irq_handlers[p_instance->drv_inst_idx]) != NRFX_SUCCESS) { err_code = NRFX_ERROR_BUSY; NRFX_LOG_WARNING("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); return err_code; } #endif // NRFX_CHECK(NRFX_PRS_ENABLED) apply_config(p_instance, p_config); p_cb->handler = event_handler; p_cb->p_context = p_config->p_context; if (p_cb->handler) { interrupts_enable(p_instance, p_config->interrupt_priority); } nrf_uarte_enable(p_instance->p_reg); p_cb->rx_buffer_length = 0; p_cb->rx_secondary_buffer_length = 0; p_cb->tx_buffer_length = 0; p_cb->state = NRFX_DRV_STATE_INITIALIZED; NRFX_LOG_WARNING("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); return err_code; }

串口UARTE发送接口nrfx_uarte_tx

nrfx_err_t nrfx_uarte_tx(nrfx_uarte_t const * p_instance, uint8_t const * p_data, size_t length) { uarte_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_INITIALIZED); NRFX_ASSERT(p_data); NRFX_ASSERT(length > 0); NRFX_ASSERT(UARTE_LENGTH_VALIDATE(p_instance->drv_inst_idx, length)); nrfx_err_t err_code; // EasyDMA requires that transfer buffers are placed in DataRAM, // signal error if the are not. if (!nrfx_is_in_ram(p_data)) { err_code = NRFX_ERROR_INVALID_ADDR; NRFX_LOG_WARNING("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); return err_code; } if (nrfx_uarte_tx_in_progress(p_instance)) { err_code = NRFX_ERROR_BUSY; NRFX_LOG_WARNING("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); return err_code; } p_cb->tx_buffer_length = length; p_cb->p_tx_buffer = p_data; NRFX_LOG_INFO("Transfer tx_len: %d.", p_cb->tx_buffer_length); NRFX_LOG_DEBUG("Tx data:"); NRFX_LOG_HEXDUMP_DEBUG(p_cb->p_tx_buffer, p_cb->tx_buffer_length * sizeof(p_cb->p_tx_buffer[0])); err_code = NRFX_SUCCESS; nrf_uarte_event_clear(p_instance->p_reg, NRF_UARTE_EVENT_ENDTX); nrf_uarte_event_clear(p_instance->p_reg, NRF_UARTE_EVENT_TXSTOPPED); nrf_uarte_tx_buffer_set(p_instance->p_reg, p_cb->p_tx_buffer, p_cb->tx_buffer_length); nrf_uarte_task_trigger(p_instance->p_reg, NRF_UARTE_TASK_STARTTX); if (p_cb->handler == NULL) { bool endtx; bool txstopped; do { endtx = nrf_uarte_event_check(p_instance->p_reg, NRF_UARTE_EVENT_ENDTX); txstopped = nrf_uarte_event_check(p_instance->p_reg, NRF_UARTE_EVENT_TXSTOPPED); } while ((!endtx) && (!txstopped)); if (txstopped) { err_code = NRFX_ERROR_FORBIDDEN; } p_cb->tx_buffer_length = 0; } NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); return err_code; }

串口UARTE接收接口nrfx_uarte_rx

nrfx_err_t nrfx_uarte_rx(nrfx_uarte_t const * p_instance, uint8_t * p_data, size_t length) { uarte_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; NRFX_ASSERT(m_cb[p_instance->drv_inst_idx].state == NRFX_DRV_STATE_INITIALIZED); NRFX_ASSERT(p_data); NRFX_ASSERT(length > 0); NRFX_ASSERT(UARTE_LENGTH_VALIDATE(p_instance->drv_inst_idx, length)); nrfx_err_t err_code; // EasyDMA requires that transfer buffers are placed in DataRAM, // signal error if the are not. if (!nrfx_is_in_ram(p_data)) { err_code = NRFX_ERROR_INVALID_ADDR; NRFX_LOG_WARNING("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); return err_code; } bool second_buffer = false; if (p_cb->handler) { nrf_uarte_int_disable(p_instance->p_reg, NRF_UARTE_INT_ERROR_MASK | NRF_UARTE_INT_ENDRX_MASK); } if (p_cb->rx_buffer_length != 0) { if (p_cb->rx_secondary_buffer_length != 0) { if (p_cb->handler) { nrf_uarte_int_enable(p_instance->p_reg, NRF_UARTE_INT_ERROR_MASK | NRF_UARTE_INT_ENDRX_MASK); } err_code = NRFX_ERROR_BUSY; NRFX_LOG_WARNING("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); return err_code; } second_buffer = true; } if (!second_buffer) { p_cb->rx_buffer_length = length; p_cb->p_rx_buffer = p_data; p_cb->rx_secondary_buffer_length = 0; } else { p_cb->p_rx_secondary_buffer = p_data; p_cb->rx_secondary_buffer_length = length; } NRFX_LOG_INFO("Transfer rx_len: %d.", length); err_code = NRFX_SUCCESS; nrf_uarte_event_clear(p_instance->p_reg, NRF_UARTE_EVENT_ENDRX); nrf_uarte_event_clear(p_instance->p_reg, NRF_UARTE_EVENT_RXTO); nrf_uarte_rx_buffer_set(p_instance->p_reg, p_data, length); if (!second_buffer) { nrf_uarte_task_trigger(p_instance->p_reg, NRF_UARTE_TASK_STARTRX); } else { nrf_uarte_shorts_enable(p_instance->p_reg, NRF_UARTE_SHORT_ENDRX_STARTRX); } if (m_cb[p_instance->drv_inst_idx].handler == NULL) { bool endrx; bool rxto; bool error; do { endrx = nrf_uarte_event_check(p_instance->p_reg, NRF_UARTE_EVENT_ENDRX); rxto = nrf_uarte_event_check(p_instance->p_reg, NRF_UARTE_EVENT_RXTO); error = nrf_uarte_event_check(p_instance->p_reg, NRF_UARTE_EVENT_ERROR); } while ((!endrx) && (!rxto) && (!error)); m_cb[p_instance->drv_inst_idx].rx_buffer_length = 0; if (error) { err_code = NRFX_ERROR_INTERNAL; } if (rxto) { err_code = NRFX_ERROR_FORBIDDEN; } } else { nrf_uarte_int_enable(p_instance->p_reg, NRF_UARTE_INT_ERROR_MASK | NRF_UARTE_INT_ENDRX_MASK); } NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); return err_code; }

串口UARTE事件中断接口uarte_irq_handler

static void uarte_irq_handler(NRF_UARTE_Type * p_uarte, uarte_control_block_t * p_cb) { if (nrf_uarte_event_check(p_uarte, NRF_UARTE_EVENT_ERROR)) { nrfx_uarte_event_t event; nrf_uarte_event_clear(p_uarte, NRF_UARTE_EVENT_ERROR); event.type = NRFX_UARTE_EVT_ERROR; event.data.error.error_mask = nrf_uarte_errorsrc_get_and_clear(p_uarte); event.data.error.rxtx.bytes = nrf_uarte_rx_amount_get(p_uarte); event.data.error.rxtx.p_data = p_cb->p_rx_buffer; // Abort transfer. p_cb->rx_buffer_length = 0; p_cb->rx_secondary_buffer_length = 0; p_cb->handler(&event, p_cb->p_context); } else if (nrf_uarte_event_check(p_uarte, NRF_UARTE_EVENT_ENDRX)) { nrf_uarte_event_clear(p_uarte, NRF_UARTE_EVENT_ENDRX); size_t amount = nrf_uarte_rx_amount_get(p_uarte); // If the transfer was stopped before completion, amount of transfered bytes // will not be equal to the buffer length. Interrupted transfer is ignored. if (amount == p_cb->rx_buffer_length) { if (p_cb->rx_secondary_buffer_length) { uint8_t * p_data = p_cb->p_rx_buffer; nrf_uarte_shorts_disable(p_uarte, NRF_UARTE_SHORT_ENDRX_STARTRX); p_cb->rx_buffer_length = p_cb->rx_secondary_buffer_length; p_cb->p_rx_buffer = p_cb->p_rx_secondary_buffer; p_cb->rx_secondary_buffer_length = 0; rx_done_event(p_cb, amount, p_data); } else { p_cb->rx_buffer_length = 0; rx_done_event(p_cb, amount, p_cb->p_rx_buffer); } } } if (nrf_uarte_event_check(p_uarte, NRF_UARTE_EVENT_RXTO)) { nrf_uarte_event_clear(p_uarte, NRF_UARTE_EVENT_RXTO); if (p_cb->rx_buffer_length) { p_cb->rx_buffer_length = 0; rx_done_event(p_cb, nrf_uarte_rx_amount_get(p_uarte), p_cb->p_rx_buffer); } } if (nrf_uarte_event_check(p_uarte, NRF_UARTE_EVENT_ENDTX)) { nrf_uarte_event_clear(p_uarte, NRF_UARTE_EVENT_ENDTX); if (p_cb->tx_buffer_length) { tx_done_event(p_cb, nrf_uarte_tx_amount_get(p_uarte)); } } } 五、实例

代码实例主要是参考app_uart的工程,添加nrfx_uarte.c、app_fifo、app_uart_fifo.c,并在sdk_config.h中使能串口

#define APP_UART_ENABLED 1 /**@brief Function for handling app_uart events. * * @details This function will receive a single character from the app_uart module and append it to * a string. The string will be be sent over BLE when the last character received was a * 'new line' '\n' (hex 0x0A) or if the string has reached the maximum data length. */ /**@snippet [Handling the data received over UART] */ void uart_event_handle(app_uart_evt_t * p_event) { switch (p_event->evt_type) { case APP_UART_DATA_READY://处理接收到的数据 break; case APP_UART_COMMUNICATION_ERROR: APP_ERROR_HANDLER(p_event->data.error_communication); break; case APP_UART_FIFO_ERROR: APP_ERROR_HANDLER(p_event->data.error_code); break; default: break; } } /**@brief Function for initializing the UART module. */ /**@snippet [UART Initialization] */ static void uart_init(void)//串口初始化 { uint32_t err_code; app_uart_comm_params_t const comm_params = { .rx_pin_no = RX_PIN_NUMBER, .tx_pin_no = TX_PIN_NUMBER, .rts_pin_no = RTS_PIN_NUMBER, .cts_pin_no = CTS_PIN_NUMBER, .flow_control = APP_UART_FLOW_CONTROL_DISABLED, .use_parity = false, #if defined (UART_PRESENT) .baud_rate = NRF_UART_BAUDRATE_115200 #else .baud_rate = NRF_UARTE_BAUDRATE_115200 #endif }; APP_UART_FIFO_INIT(&comm_params, UART_RX_BUF_SIZE, UART_TX_BUF_SIZE, uart_event_handle, APP_IRQ_PRIORITY_LOWEST, err_code); APP_ERROR_CHECK(err_code); } int main(void) { app_timer_init(); // Initialize. bsp_InitLED(); uart_init(); ble_stack_init(); app_timer_create(&led_timer_id,APP_TIMER_MODE_REPEATED,led_callback); app_timer_start(led_timer_id,APP_TIMER_TICKS(1000), NULL); //1000ms while(1) { app_uart_put('A');//发送单个字节数据 nrf_delay_ms(500); } }

在这里插入图片描述 官方技术手册



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3