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.

[参考译文] MSP-EXP430FR5994:SPI DMA BQ7.96万EVM

Guru**** 2535750 points
Other Parts Discussed in Thread: MSP430FR5994

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/1090450/msp-exp430fr5994-spi-dma-bq79600evm

部件号:MSP-EXP430FR5994
主题中讨论的其他部件:MSP430FR5994

我正在尝试将DMA的使用与MSP-EXP430FR5994-BQ79600EVM SPI7.96万 SPI结合起来。 尽管BQ7.96万以2MHz时钟运行,但我发现需要使用SPI Rx中断来成功自动寻址。 希望使用DMA而不是Rx中断,这是MSP430压力较小的设置。 我使用此线程的内容开始的字节:

MSP430FR5994:DMA不由I2C中断触发- MSP低功耗微控制器论坛- MSP低功耗微控制器- TI E2E支持论坛

以下是我的初步问题:

  1. 我是否可以将DMA通道3设置为仅在UCB1RXIFG上触发? UCB1TXIFG是否使用DMA,或者由于选择触发器,只能通过DMA接收SPI? 我在下面粘贴了SPI_Init,SPI传输和SPI接收函数。  DMA3SZ 1的值是否正确? 还是必须与块大小相同?
  2.  DMA3SZ 1的值是否正确? 还是必须与块大小相同?
  3.  DMA3SZ 1的值是否正确? 还是必须与块大小相同?  
  4. 我不了解使用DMA_Value的目的或方法。
  5. 如果DMA_Init中的其它内容不是很好,请告诉我。

谢谢

void DMA_Init(){
    (uintptr_t) &DMA3SA = (uintptr_t) &UCB1RXBUF;
    (uintptr_t) &DMA3DA = (uintptr_t) &dma_value;


    DMA3CTL &= ~DMAEN;
    DMACTL1 |= DMA3TSEL__UCB1RXIFG;
    DMA3CTL |= DMAARMDIS;
    DMA3CTL &= ~DMA3CTL;

    DMA3SZ = 1;

    DMA3CTL |= DMADT_4|DMADSTINCR_3|DMASRCINCR_0|DMASRCBYTE__BYTE|DMADSTBYTE__BYTE|DMA_TRIGGER_RISINGEDGE|DMAEN;


}

void SPI_Init()
{
    //BQ79600 SPI1_B1
    UCB1CTLW0 = UCSWRST;                                 // **Put state machine in reset**
    UCB1CTLW0 |=  UCCKPH | UCCKPL_0 | UCMSB | UCSYNC
                | UCMST | UCSSEL__SMCLK;                 // 3-pin, 8-bit MAB SPI master SMCLK=1M
    UCB1BRW = 0x00;                                      //UCB1CLK=SMCLK=1M
    UCB1CTLW0 &= ~UCSWRST;                               // **Initialize USCI state machine**
}
void spiTransmitData(uint32_t blocksize)
{
    TransmitIndex=0;

    P4OUT  = ~BIT4;
    while(blocksize != 0U)
    {
        UCB1TXBUF=spiFrame[TransmitIndex];
        while((UCB1STAT&UCBUSY));
        dummy=UCB1RXBUF;
        TransmitIndex++;
        blocksize--;
    }
    P4OUT  = BIT4;
    return;
}
void spiTransmitAndReceiveData(uint32_t blocksize,uint16_t * destbuff)
{
    ReceiveIndex = 0;

    P4OUT  &= ~BIT4;
    while(blocksize != 0U)
    {
        UCB1TXBUF=dummy;
        while((UCB1STAT&UCBUSY));
        destbuff[ReceiveIndex]=UCB1RXBUF;
        ReceiveIndex++;
        blocksize--;
    }
    P4OUT |= BIT4;

    return;
}


  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好,Priya:

    运行此代码时会发生什么情况? 我想知道您是否看到了预期结果。

    问题的答案:

    1.是的。 我不确定我是否理解您问题的第二部分。 您可以让DMA响应UCB1RX1FG,也可以触发中断。

    2/3。 我相信DMA3SZ1 = 1就是你想要的

    4. DMA3DA是目的地址。 这是DMA将放置来自SPI RX的数据

    5.为何清拆第9行的DMA3CTL。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您的回复。

    请确认我对以下内容的理解:

    1. DMA通道3只能设置为一个触发器,正确为 DMA3Tsel__UCB1RXIFG或 DMA3Tsel__UCB1TXIFG。 MSP430FR5994/5962仅5962仅在一个DMA通道上提供UCB1。

    2.设置 DMA3SZ1 =1将处理整个块大小,即使块大小 随每次传输而变化。

    3. 是否需要设置DMA ISR并在 DMAIV_DMA3IFG执行以下操作?  

    DMA3CTL &=~DMAEN;

    DMA3CTL |= DMAARMDIS;
    //DMA3CTL &=~DMA3CTL;

    DMA3SZ = 1;

    DMA3CTL |= DMADT_4|DMADSTINCR_3|DMASRCINCR_0|DMASRCBYTE__byte|DMADSTBYTE__byte|DMA_TRIGG_RIISINGEDGE|DMAEN;

    这将替换 spiTransmitAndReceiveData函数,对吗? 我需要将SPI芯片选择控件包括在内。

    4. DMAInit功能将是:

    (uintptr_t)&DMA3SA =(uintpttr_t)&UCB1RXBUF;
    (uintpttr_t)&DMA3DA =(uintpttr_t)&DMA_Value;

    DMACTL1 |= DMA3Tsel__UCB1RXIFG;

    我还没有运行此代码。 我想先了解一下。

    感谢您及时回复。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您的澄清。

    1.是的。 如果您尝试同时为TX和RX使用DMA,您将无法使用UCB1,但UCB0应该正常。

    2. SPI RX一次将接收一个字节,因此DMA3SZ =1

    3.不需要,下面列出的代码仅用于配置DMA,不需要为每个ISR运行该代码

    4.否,见我的答复3。 DMAInit函数中应包含DMA配置代码。

    如果您的设计需要两个方向的DMA,则可能值得考虑。 如果您不打算传输太多数据,则可能只需要RX端的DMA,或者根本不需要DMA。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    除了在DMA_Init中配置DMA外  ,是否需要更改spiTransmitAndReceiveData函数?  (下面粘贴的函数)。 是否需要DMA_ISR? DMA ISR将处理什么? 由于BQ设备堆栈发回测量数据,SPI接收方向发生的传输比传输更多,最大值为128-192字节。 与每个字节的SPI Rx中断相比,DMA是否具有优势?  

    void spiTransmitAndReceiveData(uint32_t blocksize,uint16_t * destbuff)
    {
        ReceiveIndex = 0;
    
        P4OUT  &= ~BIT4;
        while(blocksize != 0U)
        {
            UCB1TXBUF=dummy;
            while((UCB1STAT&UCBUSY));
            destbuff[ReceiveIndex]=UCB1RXBUF;
            ReceiveIndex++;
            blocksize--;
        }
        P4OUT |= BIT4;
    
        return;
    }

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    DMASZ =1是个坏主意。

    DMA控制器将在每次传输后生成中断,从而增加大量额外负载。 这是您尝试通过使用DMA消除的问题。 更糟糕的是,临时地址寄存器是从DMASA和DMADA重新加载的。 这意味着读取的所有数据都存储在一个位置。

    如果要接收多个字节的数据,请将DMASZ设置为该计数。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我尝试了第一次运行此代码。 一堆0xFF。 DMA中断未触发。

    void DMA_Init(){
        __data20_write_long((uintptr_t)&DMA3SA, (uintptr_t)&UCB1RXBUF);
        __data20_write_long((uintptr_t)&DMA3DA, (uintptr_t)&dma_value);
    
    
        DMA3CTL &= ~DMAEN;
        DMACTL1 |= DMA3TSEL__UCB1RXIFG;
        DMA3CTL |= DMARMWDIS;
    
        DMA3SZ = MAXBYTES;
    
        DMA3CTL |= DMADT_4|DMADSTINCR_3|DMASRCINCR_0|DMASRCBYTE__BYTE|DMADSTBYTE__BYTE|DMA_TRIGGER_RISINGEDGE|DMAEN;
    
    
    }
    /*******************************************************************************
      SPI_Init *********************************************************************
     *******************************************************************************
    * Function: Initialize SPI_B1andA3
    ********************************************************************************/
    void SPI_Init()
    {
        //BQ79600 SPI1_B1
        UCB1CTLW0 = UCSWRST;                                 // **Put state machine in reset**
        UCB1CTLW0 |=  UCCKPH | UCCKPL_0 | UCMSB | UCSYNC
                    | UCMST | UCSSEL__SMCLK;                 // 3-pin, 8-bit MAB SPI master SMCLK=1M
        UCB1BRW = 0x00;                                      //UCB1CLK=SMCLK=1M
        UCB1CTLW0 &= ~UCSWRST;                               // **Initialize USCI state machine**
    //    UCB1IE |= UCRXIE;                                    // Enable USCI0 RX interrupt
    
    }
    
    void spiTransmitAndReceiveData(uint32_t blocksize,uint16_t * destbuff)
    {
        ReceiveIndex = 0;
    
        P4OUT  &= ~BIT4;
        DMA3CTL |= DMAIE;
    
        while(dmaDone == 0);
        memcpy(destbuff, dma_value, blocksize);
        dmaDone = 0;
    
        return;
    }
    
    #pragma vector=DMA_VECTOR
    __interrupt void dmaIsrHandler(void)
    {
        switch(__even_in_range(DMAIV, DMAIV_DMA3IFG))
        {
        case DMAIV_DMA3IFG:
            DMA3CTL |= DMAEN;
            P4OUT |= BIT4;
            DMA3CTL &= ~(DMAIE);
            DMA3CTL &= ~DMAEN;
            dmaDone = 1;
            // Exit low power mode on wake-up
            __bic_SR_register_on_exit(LPM4_bits);
            break;
        case DMAIV_DMA0IFG:
            break;
    
        case DMAIV_DMA1IFG:
            break;
    
        case DMAIV_DMA2IFG:
            break;
    
        case DMAIV_DMA4IFG:
            break;
    
        case DMAIV_DMA5IFG:
            break;
    
        default: break;
        }
    }

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    整5994整套7.96万套0xFF403.9832万0xFF。403.9832万。 我认为转移应该从一次中断开始,然后一直运行到完成。[/QUOT]

    从一个中断开始是什么意思? 您指的是哪种中断?

    我注意到以下几点:

    1.在上一篇文章的第8行中,您正在DMA3CTL中设置DMARMWDIS,但是DMARMWDIS是DMACTL4中的一个字段。 您正在使用此行广告来启用中断(您可能希望这样做,因此可能不是问题,但您应该更正它)

    2.在我的环境中没有定义dma_trigger_RISINGEDGE,不确定是否在您的环境中定义了

    3.您尚未显示DMA ISR。 您有吗? 如果没有ISR,CPU可能会被发送到ISR陷阱。

    4.如果传输比MAXBYTES短,DMA将不会生成中断。 它只会在收到MAX_Bytes时生成中断。

    此致,

    Evan

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    下面是建议编辑的代码。 如果我设置DMASZ=1,DMA中断将最终触发。 我不知道如何最好地捕获SPI接收端,因为块大小随不同的传输而变化。 我可以看到byteCnt正在递增,但dma_value没有收集不同位置的字节;第一个元素是FF,其余元素为0。

    已编辑以添加dma.h具有以下内容:

    //*************************************************************************************************
    //
    //以下是可以传递到triggerTypeSelect的值
    //函数的参数:dma_init();函数的参数:
    // dma_init()。
    //
    //*************************************************************************************************
    #define DMA_TRIGG_RISINGEDGE (!(DMALEVEL))
    #define DMA_TRIGG_HIGH (DMALEVEL)

    void DMA_Init(){
        __data20_write_long((uintptr_t)&DMA3SA, (uintptr_t)&UCB1RXBUF);
        __data20_write_long((uintptr_t)&DMA3DA, (uintptr_t)&dma_value);
    
    
        DMA3CTL &= ~DMAEN;
        DMACTL1 |= DMA3TSEL__UCB1RXIFG;
        DMACTL4 |= DMARMWDIS;
    
        DMA3SZ = 1;
    
        DMA3CTL |= DMADT_4|DMADSTINCR_3|DMASRCINCR_0|DMASRCBYTE__BYTE|DMADSTBYTE__BYTE|DMA_TRIGGER_RISINGEDGE|DMAEN;
    
    
    }
    /*******************************************************************************
      SPI_Init *********************************************************************
     *******************************************************************************
    * Function: Initialize SPI_B1andA3
    ********************************************************************************/
    void SPI_Init()
    {
        //BQ79600 SPI1_B1
        UCB1CTLW0 = UCSWRST;                                 // **Put state machine in reset**
        UCB1CTLW0 |=  UCCKPH | UCCKPL_0 | UCMSB | UCSYNC
                    | UCMST | UCSSEL__SMCLK;                 // 3-pin, 8-bit MAB SPI master SMCLK=1M
        UCB1BRW = 0x00;                                      //UCB1CLK=SMCLK=1M
        UCB1CTLW0 &= ~UCSWRST;                               // **Initialize USCI state machine**
    }
    
    /*******************************************************************************
      spiTransmitAndReceiveData ****************************************************
     *******************************************************************************
    * blocksize:   length of data.
    * destbuff:    data
    * ******************************************************************************
    * Function: SPI receive data
    ********************************************************************************/
    void spiTransmitAndReceiveData(uint32_t blocksize,uint16_t * destbuff)
    {
    
        P4OUT  &= ~BIT4;
        byteCnt = 0;
        DMA3CTL |= DMAEN;
        DMA3CTL |= DMAIE;
    
    
        if (byteCnt == blocksize-1){
            DMA3CTL &= ~DMAIE;
            memcpy(destbuff, dma_value, blocksize);
            P4OUT |= BIT4;
        }
    
        return;
    }
    
    #pragma vector=DMA_VECTOR
    __interrupt void dmaIsrHandler(void)
    {
        switch(__even_in_range(DMAIV, DMAIV_DMA3IFG))
        {
        case DMAIV_DMA3IFG:
            byteCnt++;
    
            // Exit low power mode on wake-up
            __bic_SR_register_on_exit(LPM4_bits);
            break;
        case DMAIV_DMA0IFG:
            break;
    
        case DMAIV_DMA1IFG:
            break;
    
        case DMAIV_DMA2IFG:
            break;
    
        case DMAIV_DMA4IFG:
            break;
    
        case DMAIV_DMA5IFG:
            break;
    
        default: break;
        }
    }
    
    /*******************************************************************************
      spiTransmitData **************************************************************
     *******************************************************************************
    * blocksize:      length of data.
    * srcbuff :       data
    * ******************************************************************************
    * Function: transmit data
    ********************************************************************************/
    void spiTransmitData(uint32_t blocksize)
    {
        TransmitIndex=0;
    
        P4OUT  = ~BIT4;
        while(blocksize != 0U)
        {
            UCB1TXBUF=spiFrame[TransmitIndex];
            while((UCB1STAT&UCBUSY));
            dummy=UCB1RXBUF;
            TransmitIndex++;
            blocksize--;
        }
        P4OUT  = BIT4;
    
    
        return;
    }

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您的更新。 正如David所提到的,DMA3SZ=1可能不是您想要的。 我认为最好的起点是确定DMA的行为方式。

    1.是否要在收到所有RX字词后中断? 影响:

    答 所有传输内容都将存储在连续的缓冲区中

    B. 您必须知道要设置DMAxSZ所传输的总字数

    2.还是希望每次传输后中断? 影响:

    答 您必须在传输之间重新配置DMAxSZ

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我正在启动DMA传输之前设置DMASZ。 我仍在获取数据的FFs。 将两个字节作为16位值写入每个DMA_Value位置。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    是否已确认SPI RX数据不是0xFF? 您期望数据是什么?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    以下是预期良好数据的示例。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    使用不带DMA的SPI时,在接收字节时必须进行"虚拟"传输。 在将DMA与SPI配合使用时,这是如何工作的?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    SPI端口不会生成接收数据所需的时钟,除非它有要发送的数据。 或者,它被配置为从属设备,其它设备提供时钟。 DMA或非DMA。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我向SPI接收功能添加了SPI Tx边缘转换。 我可以在示波器上看到SPI_CLK上的活动,但还没有有意义的SPI Rx数据。

    这是否意味着必须为SPI Rx和SPI Tx设置DMA通道? 我仅限于UCB0

    void DMA_Init(){
        __data20_write_long((uintptr_t)&DMA3SA, (uintptr_t)&UCB1RXBUF);
        __data20_write_long((uintptr_t)&DMA3DA, (uintptr_t) dma_value);
    
    
        DMA3CTL &= ~DMAEN;
        DMACTL1 |= DMA3TSEL__UCB1RXIFG;
        DMACTL4 |= DMARMWDIS;
    
    
    
        DMA3CTL |= DMADT_0|DMADSTINCR_3|DMASRCINCR_0|DMASRCBYTE__BYTE|DMADSTBYTE__BYTE|DMA_TRIGGER_RISINGEDGE|DMAEN;
    
    
    }
    /*******************************************************************************
      SPI_Init *********************************************************************
     *******************************************************************************
    * Function: Initialize SPI_B1andA3
    ********************************************************************************/
    void SPI_Init()
    {
        //BQ79600 SPI1_B1
        UCB1CTLW0 = UCSWRST;                                 // **Put state machine in reset**
        UCB1CTLW0 |=  UCCKPH | UCCKPL_0 | UCMSB | UCSYNC
                    | UCMST | UCSSEL__SMCLK;                 // 3-pin, 8-bit MAB SPI master SMCLK=1M
        UCB1BRW = 0x00;                                      //UCB1CLK=SMCLK=1M
        UCB1CTLW0 &= ~UCSWRST;                               // **Initialize USCI state machine**
    }
    
    /*******************************************************************************
      spiTransmitAndReceiveData ****************************************************
     *******************************************************************************
    * blocksize:   length of data.
    * destbuff:    data
    * ******************************************************************************
    * Function: SPI receive data
    ********************************************************************************/
    void spiTransmitAndReceiveData(uint32_t blocksize,uint16_t * destbuff)
    {
    
        P4OUT  &= ~BIT4;
        DMA3SZ = blocksize;
        rxComplete = 0;
        DMA3CTL |= DMAEN;
        DMA3CTL |= DMAIE;
        UCB1IFG &= ~UCTXIFG;
        UCB1IFG |= UCTXIFG;
    
        return;
    }
    
    #pragma vector=DMA_VECTOR
    __interrupt void dmaIsrHandler(void)
    {
        switch(__even_in_range(DMAIV, DMAIV_DMA3IFG))
        {
        case DMAIV_DMA3IFG:
            DMA3CTL &= ~DMAIE;
            P4OUT |= BIT4;
            rxComplete = 1;
    
            // Exit low power mode on wake-up
            __bic_SR_register_on_exit(LPM4_bits);
            break;
        case DMAIV_DMA0IFG:
            break;
    
        case DMAIV_DMA1IFG:
            break;
    
        case DMAIV_DMA2IFG:
            break;
    
        case DMAIV_DMA4IFG:
            break;
    
        case DMAIV_DMA5IFG:
            break;
    
        default: break;
        }
    }

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    要接收[blocksize]字节,您需要发送这么多字节(如果仅接收,则发送0xFF)。 通常,这将使用第二个(Tx) DMA通道来完成,但正如您指出的那样,DMA触发器分配不允许对UCB1执行此操作。

    因此,我希望您必须在程序中循环将(虚拟) Tx字节写入TXBUF (由TXIFG门控)。 这会在一定程度上降低此情况下DMA的值。

    关于您正在获取的Rx数据(全部为0xFF):您是否在某处发送读取命令? 如果您尚未在FIFO中首先执行读取请求,我认为设备会发回0xFF。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    是的,在MSP430 SPI接收数据之前有详细的BQ SPI读取命令。 读取命令被发送到BQ器件,它以SPI_RDY信号响应,然后MSP430调用其SPI接收例程。

    是的,我意识到我需要将DMA传输大小限制为1字节,以便使用UCB1传输伪SPI字节。 这与简单地在SPI Rx中断上接收没有什么区别。 这是当前固件的设置方式。 我可以请求将来的硬件使用不同的SPI外围设备,以便可以为Tx和Rx设置DMA通道。 即使此设置也会有字节级开销。 我没有找到两个DMA通道的所有细节。

    我已收集到足够的信息来评论DMA的使用。 除非TI有不同的解决方案。  

    谢谢

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    如果你要这样做,你仍然需要DMAXSZ=[blocksize],因为David提到的原因。

    但是是的,您仍然会有一个轮询循环,因此在这种情况下,您不会从DMA中获得太多收益。 DMA对于仅Tx事务(您忽略Rx端)仍然有用,但对于BQ设备,这些帧似乎很短。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    根据用户指南 SLAU367P,DMA需要2个MCLK周期来传输一个字节。 我看不出来使用两个DMA通道如何能用于同步SPI传输/接收。 看起来唯一的选项是使用一个DMA通道作为接收触发器,同时为块大小中的每个字节生成一个伪TX字节。 此字节开销降低了DMA的吞吐量优势。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    由于存在双重缓冲,因此它可以正常工作。 TXBUF清空时,TXIFG将触发TX DMA。 它为您提供了8个SPI时钟(通常比MCLK慢),以便在移位寄存器中的数据消失之前重新填充,并且它再次需要TXBUF中的数据。

    传输和接收数据请求的操作不是同步的,但这不重要,因为数据是同步的。