This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS570LC4357: 如何实现SCI用DMA发送不同长度的数据包

Part Number: TMS570LC4357


目前SCI加上DMA可以多次传输固定长度的数据。但是我们再使用串口发送数据时不可能总是发送固定长度的数据,有时我们要发送10字节数据,有时又发送20字节数据。这时DMA应该如何配置,来达到发送不同长度的数据。

  • 我初步尝试了一下:可以多次发送固定长度数据,程序和结果如下:

    #include"HL_sci.h"
    #include"HL_reg_sci.h"
    #include "HL_reg_dma.h"
    #include "HL_sys_dma.h"
    g_dmaCTRL g_dmaCTRLPKT_SCI1_TX;
    uint8 SCI1_TX_DATA[40]={0};
    void SCI_DMA_Init(void)
    {
    dmaReqAssign(DMA_CH19, DMA_REQ29);
    g_dmaCTRLPKT_SCI1_TX.SADD = (uint32)(SCI1_TX_DATA) ;
    g_dmaCTRLPKT_SCI1_TX.DADD = ((uint32_t)(&(sciREG1->TD))+3);
    g_dmaCTRLPKT_SCI1_TX.CHCTRL = 0;
    g_dmaCTRLPKT_SCI1_TX.FRCNT = 10;
    g_dmaCTRLPKT_SCI1_TX.ELCNT = 1;
    g_dmaCTRLPKT_SCI1_TX.ELDOFFSET = 0;
    g_dmaCTRLPKT_SCI1_TX.ELSOFFSET = 0;
    g_dmaCTRLPKT_SCI1_TX.FRDOFFSET = 0;
    g_dmaCTRLPKT_SCI1_TX.FRSOFFSET = 0;
    g_dmaCTRLPKT_SCI1_TX.PORTASGN = PORTA_READ_PORTB_WRITE;
    g_dmaCTRLPKT_SCI1_TX.RDSIZE = ACCESS_8_BIT;
    g_dmaCTRLPKT_SCI1_TX.WRSIZE = ACCESS_8_BIT;
    g_dmaCTRLPKT_SCI1_TX.TTYPE = FRAME_TRANSFER ;
    g_dmaCTRLPKT_SCI1_TX.ADDMODERD = ADDR_INC1;
    g_dmaCTRLPKT_SCI1_TX.ADDMODEWR = ADDR_FIXED;
    g_dmaCTRLPKT_SCI1_TX.AUTOINIT = AUTOINIT_OFF;
    dmaSetCtrlPacket(DMA_CH19,g_dmaCTRLPKT_SCI1_TX);
    dmaSetChEnable(DMA_CH19, DMA_HW);
    sciREG1->SETINT |= (1<<16U) ;
    }
    void SCI_DMA_SEND(uint8 length)
    {
    // dmaRAMREG->PCP[DMA_CH19].ITCOUNT =(0x00000001 | length<<16);
    dmaSetChEnable(DMA_CH19, DMA_HW);
    }
    uint32 timen=50000;
    int user_main(void)
    {
    uint8 i=0;
    sciInit();
    dmaEnable();

    for(i=0;i<40;i++)
    {
    SCI1_TX_DATA[i]=i;
    }
    SCI_DMA_Init();

    while(1)
    {
    while(timen--);
    timen=50000;
    SCI_DMA_SEND(20);
    }
    }

    可以实现。

    发送不同长度数据,失败,程序做以下修改和结果如下:

    void SCI_DMA_SEND(uint8 length)
    {
    dmaRAMREG->PCP[DMA_CH19].ITCOUNT =(0x00000001 | length<<16);
    dmaSetChEnable(DMA_CH19, DMA_HW);
    }

    只有第一次发送出来了,后面的就发送不出来了。 求解答。

  • 好的我们已收到您的问题并升级到英文论坛,如有答复将尽快回复您。谢谢!

  • 谢谢,期待您的好消息

  • 您好,需要重新配置 MibSPI DMA :

    mibspiREG1->DMACTRL[0] |= (3 << 20) | (2 << 16);
    mibspiREG1->DMACTRL[0] |= 0x8000C000;

    同时启用传输组:

    mibspiREG1->TGCTRL[0] |= 0x80000000U;

  • 我不太明白我用的时SCI,为什么要对mispi 进行修改。

  • 收到您的问题,已跟进给工程师,如有答复会尽快给到您。

  • 谢谢,期待您的好消息

  • sciREG1->CLEARINT |= SCI_SET_TX_DMA;

    g_dmaCTRLPKT.FRCNT = size/2;         -->new FRCNT
    g_dmaCTRLPKT.ELCNT = 1;
    dmaRAMREG->PCP[0].ITCOUNT = (g_dmaCTRLPKT.FRCNT << 16U) | g_dmaCTRLPKT.ELCNT;

    /*将 DMA 通道 0 和 1 设置为在硬件请求上触发*/
    dmaSetChEnable(DMA_CH0, DMA_HW);

    sciREG1->SETINT |= SCI_SET_TX_DMA; 

    1. 清除 SCI TX DMA 位

    2. 重新配置帧计数和元素计数

    3. 设置硬件通道使能位

    4. 设置 SCI TX DMA 位 ti 触发传输

    希望以上回答对您有所帮助,如有其他问题请随时联系我们。

  • 这种问题我也遇到过,我的解决方法如下

    只需在下次发送时清除标志位即可

    sciREG1->CLEARINT |= (1 << 16U);

    函数封装如下:

    void scidmaSend(uint8 *source_address,uint8 len)
    {
    g_dmaCTRL g_dmaCTRLPKT;
    sciREG1->CLEARINT |= (1 << 16U);
    dmaEnable();
    /* - configuring dma control packets */
    g_dmaCTRLPKT.SADD = (uint32)source_address; /* source address */
    g_dmaCTRLPKT.DADD = (uint32_t)(&(sciREG1->TD)); /* destination address */
    g_dmaCTRLPKT.CHCTRL = 0; /* channel control */
    g_dmaCTRLPKT.FRCNT = len; /* frame count */
    g_dmaCTRLPKT.ELCNT =1 ; /* element count */
    g_dmaCTRLPKT.ELDOFFSET = 0; /* element destination offset - is required? */
    g_dmaCTRLPKT.ELSOFFSET = 0; /* element source offset - is required? */
    g_dmaCTRLPKT.FRDOFFSET = 0; /* frame detination offset - is required? */
    g_dmaCTRLPKT.FRSOFFSET = 0; /* frame source offset - is required? */
    g_dmaCTRLPKT.PORTASGN = PORTA_READ_PORTB_WRITE; /* port b */
    g_dmaCTRLPKT.RDSIZE = ACCESS_8_BIT; /* read size */
    g_dmaCTRLPKT.WRSIZE = ACCESS_8_BIT; /* write size */
    g_dmaCTRLPKT.TTYPE = FRAME_TRANSFER ; /* transfer type */
    g_dmaCTRLPKT.ADDMODERD = ADDR_INC1; /* address mode read */
    g_dmaCTRLPKT.ADDMODEWR = ADDR_FIXED; /* address mode write */
    g_dmaCTRLPKT.AUTOINIT = AUTOINIT_OFF; /* autoinit (loop) */

    /* - setting dma control packets for transmit */
    dmaSetCtrlPacket(DMA_CH0,g_dmaCTRLPKT);
    dmaSetChEnable(DMA_CH0, DMA_HW);
    sciREG1->SETINT |= (1 << 16U);
    }

  • 谢谢。非常感谢您的回复。

  • 这个正是我需要的!