找回密码
 立即注册
查看: 143|回复: 2

为什么AI8H8K64U使用DMA发送时DMA_URnT_DONE始终为0

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:501
  • 最近打卡:2025-06-17 09:45:37
已绑定手机

29

主题

349

回帖

1995

积分

金牌会员

机长

积分
1995
发表于 2025-5-31 00:29:53 | 显示全部楼层 |阅读模式
#include <stdint.h>
#include <stdio.h>

#include "stdio_dma.h"

#ifdef configDMA_STDIO_UART_TX

static int8_t dmaUartTxBuffer[configDMA_STDIO_UART_TX_SIZE];
__data static volatile uint8_t dmaUartTxHead = 0x00;
__data static volatile uint8_t dmaUartTxTail = 0x00;
static volatile __bit dmaUartTxBusy          = 0;

void vInitalizeUart(void)
{
#if (configCPU_CLOCK_1T == 1)
    AUXR |= 0x02; // 定时器时钟1T模式
    const uint16_t uiTick = MCU_MAJOR_FOC / configUART_BAUDRATE / 4;
#else
    AUXR &= 0xFB; // 定时器时钟12T模式
    const uint16_t uiTick = MCU_MAJOR_FOC / configUART_BAUDRATE / 4 / 12;
#endif
    const uint16_t uiInit = 0x10000 - uiTick;

    TMR2  = uiInit;
    S2CON = 0x10;
    AUXR |= 0x10;
}

void prvDmaUartTxStart(void)
{
    dmaUartTxBusy    = 1;
    uint16_t ptr     = (uint16_t)&dmaUartTxBuffer[dmaUartTxHead];
    DMA_UART_TX_TXAH = (uint8_t)(ptr >> 8);
    DMA_UART_TX_TXAL = (uint8_t)(ptr & 0xff);
    uint8_t len      = 0;
    if (dmaUartTxHead < dmaUartTxTail) {
        len = dmaUartTxTail - dmaUartTxHead;
    } else {
        len = configDMA_STDIO_UART_TX_SIZE - dmaUartTxHead;
    }
    DMA_UART_TX_AMNT = len;

    DMA_UART_TX_STAT = 0;
    DMA_UART_TX_CONF = 0x8f;
    DMA_UART_TX_CTRL = 0xC0;
    EA               = 1;
}

void vDmaUartTxISR(void) __interrupt(VECTOR_DMA_UART_TX)
{
    P6 = 0xf0;
    // 清除DMA_UART_TX中断标志
    DMA_UART_TX_STAT = 0;
    // 更新发送缓冲区头指针
    dmaUartTxHead = dmaUartTxHead + DMA_UART_TX_DONE + 1;
    dmaUartTxHead = dmaUartTxHead % configDMA_STDIO_UART_TX_SIZE;
    // 清除自定义DMA繁忙标志
    dmaUartTxBusy = 0;

    // 如果还有数据待发送,则重新启动DMA传输
    if (dmaUartTxHead != dmaUartTxTail) {
        prvDmaUartTxStart();
    }
}

int putchar(int ch)
{
    // 等待DMA发送缓冲区有空间
    uint8_t next;
    do {
        next = dmaUartTxTail + 1;
        next = next % configDMA_STDIO_UART_TX_SIZE;
    } while (next == dmaUartTxHead);

    dmaUartTxBuffer[dmaUartTxTail] = ch;
    dmaUartTxTail                  = next;

    // 如果DMA传输未在进行中,则启动DMA传输
    if (!dmaUartTxBusy) {
        prvDmaUartTxStart();
    }
    return ch;
}

#endif // configSTDIO_UART_TX_DMA

如以上代码所示,我尝试在AI8H8K64U上使用DMA传输串口数据,但是串口助手中收到的数据如图所示:
image.png

经反复调试发现,是DMA发送中断中,DMA_UR2T_DONE始终为0导致。换了其它几个串口也是一样的效果……
现在求教大家,所有示例中似乎都没找到 DMA_UR2T_DONE用法,是我 DMA_UR2T_DONE使用姿势不太对吗?


(为了切换串口方便,我重新定义了XSFR)

upload 附件:stdio_dma.hupload 附件:stdio_dma.c

业余撸代码,专业开飞机 https://gitee.com/STC-MCU
回复

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:210
  • 最近打卡:2025-06-18 08:45:53
已绑定手机

68

主题

1926

回帖

4314

积分

荣誉版主

无情的代码机器

积分
4314
发表于 2025-6-3 09:23:19 | 显示全部楼层
DMA_UR2T_DONE这个寄存器问题我也遇到过,还是先不要使用这个~
使用DMA_UR2x_AMT设置的传输长度和DMA中断传输完成Flag.

https://www.stcaimcu.com/forum.p ... =1&extra=#pid157073

点评

好的。我还以为是我业余的用法不对呢  发表于 2025-6-3 09:54
三天不学习,赶不上刘少奇~
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-6-18 08:51 , Processed in 0.124723 second(s), 60 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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