乐鑫技术交流
直播中

甘满盛

7年用户 1237经验值
擅长:386660
私信 关注
[问答]

如何将ESP32端AT串口接收改为DMA方式?

如题,当前有此需求要将ESP32端AT串口接收改为DMA方式,从而减小MCU端负荷。
芯片: ESP32-PICO-D4
ESP-AT: release/v2.1.0.0_esp32
ESP-IDF: release/v4.0
参考文档:https://www.espressif.com.cn/sites/defa ... n.pdf#uart
框图:                                                                                                                                                udma.PNG (25.09 KiB) Viewed 4245 times                                                                                                        
查看文档得知大概链路是UART->UHCI->UDMA, 但不清楚如何更改。
未在ESP-IDFV4.0中找到相关示例及库文件。希望可以提供相关资料。
谢谢!
                  

回帖(1)

莎莎miu~

2024-6-27 16:55:11
要将ESP32端AT串口接收改为DMA方式,可以按照以下步骤进行:

1. 首先,确保你已经安装了ESP-IDF开发环境。如果没有,请访问以下链接进行安装:https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/index.html

2. 打开ESP-IDF项目,找到`main`文件夹下的`app_main.c`文件。

3. 在`app_main.c`文件中,找到`app_main()`函数。这是应用程序的主入口函数。

4. 在`app_main()`函数中,首先初始化UART接口。使用`uart_config_t`结构体配置UART参数,例如波特率、数据位、停止位等。然后调用`uart_driver_install()`函数安装UART驱动。

```c
uart_config_t uart_config = {
    .baud_rate = 115200,
    .data_bits = UART_DATA_8_BITS,
    .parity = UART_PARITY_DISABLE,
    .stop_bits = UART_STOP_BITS_1,
    .flow_ctrl = UART_HW_FLOWCTRL_DISABLE
};
uart_param_config(UART_NUM_1, &uart_config);
uart_driver_install(UART_NUM_1, 4096, 4096, 0, NULL, 0);
```

5. 接下来,配置DMA。在ESP32中,可以使用`esp_intr_alloc()`函数分配中断,然后使用`esp_intr_disable()`和`esp_intr_enable()`函数控制中断的使能和禁止。

6. 在`app_main()`函数中,创建一个用于接收数据的缓冲区,例如:

```c
uint8_t rx_buffer[1024];
```

7. 配置DMA传输。使用`esp_dma_malloc()`函数分配DMA传输所需的内存。然后,使用`esp_dma_get_channel()`函数获取DMA通道,并使用`esp_dma_set_source()`和`esp_dma_set_dest()`函数设置DMA的源地址和目标地址。

8. 配置DMA传输的属性,例如传输大小、传输方向等。然后,使用`esp_dma_start()`函数启动DMA传输。

9. 在DMA传输完成后,使用`esp_intr_set_handler()`函数设置中断处理函数,以便在DMA传输完成后进行相应的处理。

10. 最后,使用`esp_intr_enable()`函数使能中断,以便在DMA传输完成后触发中断。

以下是一个简化的示例代码,展示了如何使用DMA进行UART接收:

```c
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/uart.h"
#include "driver/dma.h"
#include "esp_intr_alloc.h"

#define UART_NUM UART_NUM_1
#define RX_BUFFER_SIZE 1024

static uint8_t rx_buffer[RX_BUFFER_SIZE];
static intr_handle_t uart_intr_handle = NULL;

static void IRAM_ATTR uart_isr_handler(void *arg)
{
    // 处理中断
}

void app_main()
{
    uart_config_t uart_config = {
        .baud_rate = 115200,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE
    };
    uart_param_config(UART_NUM, &uart_config);
    uart_driver_install(UART_NUM, RX_BUFFER_SIZE * 2, 0, 0, NULL, 0);

    esp_err_t ret = esp_intr_alloc(ETS_UART0_INTR_SOURCE, 0, &uart_isr_handler, NULL, &uart_intr_handle);
    if (ret != ESP_OK) {
        printf("esp_intr_alloc failed: %dn", ret);
        return;
    }

    esp_intr_disable(uart_intr_handle);

    // 配置DMA
    void *dma_buffer = heap_caps_malloc(RX_BUFFER_SIZE, MALLOC_CAP_DMA);
    DMA_Channel_Handle_t dma_handle = DMA_GetChannel(1);
    DMA_SetSource(dma_handle, &UART1->FIFO.RW_DATA);
    DMA_SetDest(dma_handle, dma_buffer);
    DMA_SetDataWidth(dma_handle, DMA_DATA_WIDTH_BYTE);
    DMA_SetTransferSize(dma_handle, RX_BUFFER_SIZE);
    DMA_SetSrcInc(dma_handle, DMA_SRC_INC_NONE);
    DMA_SetDestInc(dma_handle, DMA_DEST_INC_NONE);
    DMA_SetIntrType(dma_handle, DMA_INTR_TYPE_END_DONE);

    DMA_Start(dma_handle);

    esp_intr_enable(uart_intr_handle);

    // 等待DMA传输完成
    while (1) {
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}
```

请注意,这只是一个简化的示例,实际应用中可能需要根据具体需求进行调整。希望这对你有所帮助!
举报

更多回帖

发帖
×
20
完善资料,
赚取积分