这两个过程都允许我通过UART传输数据并在作业完成后调用ISR。因此,乍一看,在我看来他们做了同样的事情。你能解释一下有什么区别吗?即xxx_IT过程在内部使用DMA(设备)吗?您能否举个例子,说明xxx_DMA过程可以做什么,而xxx_IT无法做到(反之亦然)(我个人只知道M2M场景)?在哪种情况下我应该使用xxx_DMA而不是xxx_IT?
答案 0 :(得分:1)
DMA传输会在没有“后台”核心活动的情况下进行传输
每次接收或必须发送char时都会调用中断例程。在每个字节发送或接收期间,Core都处于繁忙状态。
在您的情况下,您不知道什么是DMA,这对您来说并不重要。由于您将无法从DMA传输中受益,因此应使用中断传输,因为它更易于设置。
答案 1 :(得分:1)
DMA在MCU中充当独立的单元。像这里提到的P__J__一样,传输数据和获取数据都不需要CPU时间。通常,在MCU中,dma有助于从UART,SPI等各种总线,从DAC,ADC等其他模块甚至在这些模块之间传输数据。如果需要快速从RAM传输大缓冲区,反之亦然,这非常方便。例如,示波器需要大量的ADC样品。每个irq调用可能需要一微秒,因此,如果您需要1000个采样,它会太慢,而且每个irq调用-在处理有用数据时都会中断MCU的工作流程。使用IRQ,您必须自己处理数据,放入缓冲区等,这也是额外的时间。如果您拥有TX RX,那么在IRQ上花费的时间甚至更多。 DMA只是在后台写入或读取缓冲区。这是一个小例子:
#define BufferSize 50
uint8_t SPI_Buffer_Rx[BufferSize];
uint8_t SPI_Buffer_Tx[BufferSize];
//configuring SPI
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
SPI_RxFIFOThresholdConfig(SPI2, SPI_RxFIFOThreshold_HF);
SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 0;
SPI_Init(SPI2, &SPI_InitStructure);
SPI_CalculateCRC(SPI2, DISABLE);
// RX and TX DMA configuration
/* SPI_SLAVE_Rx_DMA_Channel configuration ---------------------------------*/
RCC_AHBPeriphClockCmd(SPI_SLAVE_DMA_CLK, ENABLE);
DMA_DeInit(SPI_SLAVE_Rx_DMA_Channel);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(SPI2->DR));
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)(&SPI_Buffer_Rx[0]);
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = BufferSize;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(SPI_SLAVE_Rx_DMA_Channel, &DMA_InitStructure);
/* SPI_SLAVE_Tx_DMA_Channel configuration ---------------------------------*/
DMA_DeInit(SPI_SLAVE_Tx_DMA_Channel);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(SPI2->DR));
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)(&SPI_Buffer_Tx[0]);
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = BufferSize;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(SPI_SLAVE_Tx_DMA_Channel, &DMA_InitStructure);
不详细介绍,您可以看到DMA可以直接处理SPI数据寄存器中的数据。
DMA_InitStructure.DMA_PeripheralBaseAddr =(uint32_t)(&(SPI2-> DR));
还可以设置自己的RAM中的缓冲区。它将通过DMA从SPI RX获取数据。
DMA_InitStructure.DMA_MemoryBaseAddr =(uint32_t)(&SPI_Buffer_Rx [0]);
如您所见,与TX和RX相同。
您还可以控制大小,类型,例如FIFO等。这取决于您的情况。
当您拥有更复杂的体系结构或需要快速数据流,读取和写入时,绝对应该使用DMA。在ST32中,dma每个外围设备都有具体的通道,因此您要确定哪个外围设备应具有DMA,而没有。尤其是当您的固件复杂时,就会发生这种情况。但是通常不缺少DMA通道。因此,如果您的MCU中有DMA,并且数据传输速度适中。为什么不使用它? MCU通常卡在不同的非常方便的功能模块中。我看不到参数,为什么不使用这些功能?当有很多新的珍贵方法使之起作用时,为什么任何人都应该只采用古老的知名方法?