3

我正在尝试使用 DMA 将数据发送到 SPI1。然后 SPI1 将控制 DAC 进行电压更新。

使用的芯片是STM32F407。因此对应的channel/stream为:channel3/stream5,如参考手册所示。但是,当 DMA 使能时,SPI1->DR 中没有数据显示,示波器中也没有显示结果。

当 SPI1->DR 由软件写入时,SPI 工作正常。谁能帮忙看看发生了什么?代码如下:

uint16_t DACData[1]; 
void InitDMA(void)
{
    DMA_InitTypeDef DMA_InitStructure;
    DMA_Cmd(DMA2_Stream2, DISABLE);
    while (DMA2_Stream2->CR & DMA_SxCR_EN);
    //SPI1 Tx DMA
    DMA_DeInit(DMA2_Stream5);
    DMA_StructInit(&DMA_InitStructure);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); //Init DMA clock
    DMA_InitStructure.DMA_Channel = DMA_Channel_3;//SPI1 Tx 
    DMA_InitStructure.DMA_PeripheralBaseAddr  = (uint32_t)&(SPI1->DR); //Set the SPI1 Tx
    DMA_InitStructure.DMA_Memory0BaseAddr  = (uint32_t)&DACData;       //Set the memory location
    DMA_InitStructure.DMA_DIR  = DMA_DIR_MemoryToPeripheral;           //
    DMA_InitStructure.DMA_BufferSize  = 1;            //Define the number of bytes to send
    DMA_InitStructure.DMA_PeripheralInc  = DMA_PeripheralInc_Disable;             
    DMA_InitStructure.DMA_MemoryInc  = DMA_MemoryInc_Disable;            
    DMA_InitStructure.DMA_PeripheralDataSize  = DMA_PeripheralDataSize_HalfWord;    
    DMA_InitStructure.DMA_MemoryDataSize  = DMA_PeripheralDataSize_HalfWord;        
    DMA_InitStructure.DMA_Mode  = DMA_Mode_Normal;               //Normal mode (not circular)
    DMA_InitStructure.DMA_Priority  = DMA_Priority_High;                
    DMA_InitStructure.DMA_FIFOMode  = DMA_FIFOMode_Disable;  //Operate in 'direct mode' 
    DMA_InitStructure.DMA_MemoryBurst =DMA_MemoryBurst_Single;
    DMA_InitStructure.DMA_PeripheralBurst =DMA_PeripheralBurst_Single;
    DMA_Init(DMA2_Stream5, &DMA_InitStructure); //DMA2, Channel 3, stream 5

    //Enable the transfer complete interrupt for DMA2 Stream5
    DMA_ITConfig(DMA2_Stream5, DMA_IT_TC, ENABLE);                                       
}

这是 SPI1 的初始化方式

void InitSPI1(void) 
 {
    GPIO_InitTypeDef GPIO_InitStruct;
    SPI_InitTypeDef SPI_InitStruct;
    // enable clock for used IO pins
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_6 | GPIO_Pin_5;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOA, &GPIO_InitStruct);

    // connect SPI1 pins to SPI alternate function
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1); //SCK
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1); //MISO
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1); //MOSI
    // enable peripheral clock
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

    /* configure SPI1 in Mode 0 
     * CPOL = 0 --> clock is low when idle
     * CPHA = 0 --> data is sampled at the first edge
     */
    SPI_InitStruct.SPI_Direction = SPI_Direction_1Line_Tx; // one line transmission
    SPI_InitStruct.SPI_Mode = SPI_Mode_Master;     // transmit in master mode, NSS pin has to be always high
    SPI_InitStruct.SPI_DataSize = SPI_DataSize_16b; // one packet of data is 16 bits wide
    SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;        // clock is low when idle
    SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;      // data sampled at first edge
    SPI_InitStruct.SPI_NSS = SPI_NSS_Soft | SPI_NSSInternalSoft_Set;; // set the NSS management to hardware
    SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; // SPI frequency is APB2 frequency / 4 = 21MHz
    SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;// data is transmitted MSB first

    SPI_Init(SPI1, &SPI_InitStruct); 
    SPI_Cmd(SPI1, ENABLE); // enable SPI1
}

我尝试使用这些命令来启动 DMA:

DACData[0]=0xff00;
DMA_Cmd(DMA2_Stream5, ENABLE);

如果它可能有帮助,这里是 DMA2 的寄存器值,流 5 在此处输入图像描述 在此处输入图像描述

4

4 回答 4

5

错过了这样的一行:

SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Tx,启用);

它使 SPI1 能够使用 DMA。

于 2014-06-02T08:44:37.557 回答
1

只需添加:

如果您想重新启动 DMA,似乎您不仅需要调用:

DMA_Cmd(DMA2_Stream5, ENABLE);

DMA_ClearFlag(DMA1_Stream5, DMA_FLAG_TCIF5);

也是。即使我没有启用中断,这似乎仍然是必需的。

于 2015-01-19T16:49:41.100 回答
0

Based on a quick look, the first thing that stands out is that you try to use parts of the DMA peripheral before enabling it. Try moving the

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);

call before

DMA_Cmd(DMA2_Stream2, DISABLE);
while (DMA2_Stream2->CR & DMA_SxCR_EN);

as it could be eg. getting stuck in the loop. (I'm not sure which way the bits get read if the peripheral is not enabled when reading its registers)

If that doesn't help, leave a comment and I can try looking at it a bit more closely later.

于 2014-06-02T06:10:06.813 回答
0

我有一个问题,但互联网上没有任何东西可以帮助我,我的解决方案是改变它;

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;

除此之外,我的代码几乎是相似的,我不明白为什么你的代码会起作用。

于 2014-09-27T02:26:40.063 回答