hsrzq 发表于 2025-5-31 00:29:53

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

<pre><code class="language-c">#include &lt;stdint.h&gt;
#include &lt;stdio.h&gt;

#include &quot;stdio_dma.h&quot;

#ifdef configDMA_STDIO_UART_TX

static int8_t dmaUartTxBuffer;
__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 &amp;= 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)&amp;dmaUartTxBuffer;
    DMA_UART_TX_TXAH = (uint8_t)(ptr &gt;&gt; 8);
    DMA_UART_TX_TXAL = (uint8_t)(ptr &amp; 0xff);
    uint8_t len      = 0;
    if (dmaUartTxHead &lt; 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 = ch;
    dmaUartTxTail                  = next;

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

#endif // configSTDIO_UART_TX_DMA
</code></pre>
<p>如以上代码所示,我尝试在AI8H8K64U上使用DMA传输串口数据,但是串口助手中收到的数据如图所示:<br />
<img src="data/attachment/forum/202505/31/002457szedmssk2sed0z1k.png" alt="image.png" title="image.png" /></p>
<p>经反复调试发现,是DMA发送中断中,<code>DMA_UR2T_DONE</code>始终为0导致。换了其它几个串口也是一样的效果……<br />
现在求教大家,所有示例中似乎都没找到 <code>DMA_UR2T_DONE</code>用法,是我 <code>DMA_UR2T_DONE</code>使用姿势不太对吗?</p>
<hr />
<p>(为了切换串口方便,我重新定义了XSFR)</p>
<p><a href="forum.php?mod=attachment&amp;aid=102140" title="attachment"><img src="/source/plugin/zhanmishu_markdown/template/editor/images/upload.svg" alt="upload" /> 附件:stdio_dma.h</a><a href="forum.php?mod=attachment&amp;aid=102141" title="attachment"><img src="/source/plugin/zhanmishu_markdown/template/editor/images/upload.svg" alt="upload" /> 附件:stdio_dma.c</a></p>

ercircle 发表于 2025-6-3 09:23:19

DMA_UR2T_DONE这个寄存器问题我也遇到过,还是先不要使用这个~
使用DMA_UR2x_AMT设置的传输长度和DMA中断传输完成Flag.

https://www.stcaimcu.com/forum.p ... =1&extra=#pid157073
页: [1]
查看完整版本: 为什么AI8H8K64U使用DMA发送时DMA_URnT_DONE始终为0