硬汉嵌入式论坛

 找回密码
 立即注册
查看: 492|回复: 4
收起左侧

[有问必答] 关于DMA发送的问题

[复制链接]

7

主题

37

回帖

58

积分

初级会员

积分
58
发表于 2025-3-30 17:01:23 | 显示全部楼层 |阅读模式
在用空闲中断回调函数以及DMA发送时出现的问题,调试是已经进入了回调函数里面,数组里面的值以及数据长度都是对的,但是数据只发送出来一次
uint8_t g_usart_rx_buf[USART_REC_LEN];

uint16_t g_usart_rx_sta = 0;

uint8_t g_rx_buffer[RXBUFFERSIZE];  /* HAL库使用的串口接收缓冲 */

UART_HandleTypeDef g_uart1_handle;

void usart_init(uint32_t baudrate)
{
    g_uart1_handle.Instance = USART1;                                       /* USART_UX */
    g_uart1_handle.Init.BaudRate = baudrate;                                  /* 波特率 */
    g_uart1_handle.Init.WordLength = UART_WORDLENGTH_8B;                      /* 字长为8位数据格式 */
    g_uart1_handle.Init.StopBits = UART_STOPBITS_1;                           /* 一个停止位 */
    g_uart1_handle.Init.Parity = UART_PARITY_NONE;                            /* 无奇偶校验位 */
    g_uart1_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;                      /* 无硬件流控 */
    g_uart1_handle.Init.Mode = UART_MODE_TX_RX;                               /* 收发模式 */
    HAL_UART_Init(&g_uart1_handle);                                           /* HAL_UART_Init()会使能UART1 */
       
}

void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
    GPIO_InitTypeDef gpio_init_struct;

    if (huart->Instance == USART_UX)                            /* 如果是串口1,进行串口1 MSP初始化 */
    {
        __HAL_RCC_GPIOA_CLK_ENABLE();                             /* 使能串口TX脚时钟 */
        __HAL_RCC_USART1_CLK_ENABLE();                                  /* 使能串口时钟 */

        gpio_init_struct.Pin = GPIO_PIN_9;               /* 串口发送引脚号 */
        gpio_init_struct.Mode = GPIO_MODE_AF_PP;                /* 复用推挽输出 */
        gpio_init_struct.Pull = GPIO_PULLUP;                    /* 上拉 */
        gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;          /* IO速度设置为高速 */
        HAL_GPIO_Init(GPIOA, &gpio_init_struct);

        gpio_init_struct.Pin = GPIO_PIN_10;               /* 串口RX脚 模式设置 */
        gpio_init_struct.Mode = GPIO_MODE_AF_INPUT;   
        HAL_GPIO_Init(GPIOA, &gpio_init_struct);   /* 串口RX脚 必须设置成输入模式 */

        HAL_NVIC_EnableIRQ(USART1_IRQn);                      /* 使能USART1中断通道 */
        HAL_NVIC_SetPriority(USART1_IRQn, 3, 3);              /* 组2,最低优先级:抢占优先级3,子优先级3 */
    }
}

DMA_HandleTypeDef dma_rx_handle;
DMA_HandleTypeDef dma_tx_handle;
void dma_init(void)
{
        __HAL_RCC_DMA1_CLK_ENABLE();

        dma_rx_handle.Instance = DMA1_Channel5;             //指令基地址
        dma_rx_handle.Init.Direction = DMA_PERIPH_TO_MEMORY; //外设到内存
        dma_rx_handle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;//8字节对齐
        dma_rx_handle.Init.MemInc           = DMA_MINC_ENABLE;
        dma_rx_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;//8字节对齐
        dma_rx_handle.Init.PeriphInc           = DMA_PINC_DISABLE;
        dma_rx_handle.Init.Priority            = DMA_PRIORITY_MEDIUM;
        dma_rx_handle.Init.Mode                = DMA_NORMAL;
        HAL_DMA_Init(&dma_rx_handle);
       
        __HAL_LINKDMA(&g_uart1_handle,hdmarx,dma_rx_handle);//在函数中将句柄与dma建立关联
        HAL_UARTEx_ReceiveToIdle_DMA(&g_uart1_handle,g_usart_rx_buf,USART_REC_LEN);
       
        dma_tx_handle.Instance = DMA1_Channel4;             //指令基地址
        dma_tx_handle.Init.Direction = DMA_MEMORY_TO_PERIPH; //外设到内存
        dma_tx_handle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;//8字节对齐
        dma_tx_handle.Init.MemInc           = DMA_MINC_ENABLE;
        dma_tx_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;//8字节对齐
        dma_tx_handle.Init.PeriphInc           = DMA_PINC_DISABLE;
        dma_tx_handle.Init.Priority            = DMA_PRIORITY_MEDIUM;
        dma_tx_handle.Init.Mode                = DMA_NORMAL;
        HAL_DMA_Init(&dma_tx_handle);
       
        __HAL_LINKDMA(&g_uart1_handle,hdmatx,dma_tx_handle);//在函数中将句柄与dma建立关联

}


void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
        if(huart->Instance==USART1)
        {
                HAL_UART_Transmit_DMA(&g_uart1_handle,g_usart_rx_buf,Size);
                HAL_UARTEx_ReceiveToIdle_DMA(&g_uart1_handle,g_usart_rx_buf,USART_REC_LEN);
        }
}

void USART1_IRQHandler(void)
{
#if SYS_SUPPORT_OS                          /* 使用OS */
    OSIntEnter();   
#endif
        HAL_UART_IRQHandler(&g_uart1_handle);


#if SYS_SUPPORT_OS                          /* 使用OS */
    OSIntExit();
#endif
}

回复

使用道具 举报

7

主题

37

回帖

58

积分

初级会员

积分
58
 楼主| 发表于 2025-3-30 18:14:30 | 显示全部楼层
找到问题了,是因为在DMA发送之前没有进行关闭DMA的操作,需要加入一行HAL_UART_DMAStop(&g_uart1_handle);虽然问题找到了,但是没有明白为啥一定要加入这个才能进行发送
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117516
QQ
发表于 2025-3-31 09:24:00 | 显示全部楼层
南湖悲 发表于 2025-3-30 18:14
找到问题了,是因为在DMA发送之前没有进行关闭DMA的操作,需要加入一行HAL_UART_DMAStop(&g_uart1_handle); ...

养成好习惯,判断返回值,这两个函数都要判断。

HAL_UART_Transmit_DMA(&g_uart1_handle,g_usart_rx_buf,Size);
HAL_UARTEx_ReceiveToIdle_DMA(&g_uart1_handle,g_usart_rx_buf,USART_REC_LEN);
回复

使用道具 举报

7

主题

37

回帖

58

积分

初级会员

积分
58
 楼主| 发表于 2025-3-31 18:49:10 | 显示全部楼层
好的,多谢硬汉哥
回复

使用道具 举报

7

主题

37

回帖

58

积分

初级会员

积分
58
 楼主| 发表于 2025-3-31 18:53:41 | 显示全部楼层
eric2013 发表于 2025-3-31 09:24
养成好习惯,判断返回值,这两个函数都要判断。

HAL_UART_Transmit_DMA(&g_uart1_handle,g_usart_rx_ ...

硬汉哥,这个地方为什么一定要先关闭DMA才可以
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-8-12 09:25 , Processed in 0.040695 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表