Bucle invertido SPI con DMA

Estoy usando la placa de descubrimiento STM32F4 y estoy intentando obtener un bucle invertido SPI con DMA.

Obtuve con éxito un bucle invertido "solo SPI", pero ahora quiero usar DMA además de SPI, estas son las funciones que estoy usando:

Inicialización de SPI

void init_SPI1(void){    
  NVIC_InitTypeDef NVIC_InitStructure;
  GPIO_InitTypeDef GPIO_InitStruct;
  SPI_InitTypeDef SPI_InitStruct ;

  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_6 | GPIO_Pin_5|GPIO_Pin_4;
  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_PinSource4, GPIO_AF_SPI1);
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1);
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1);

  //Set chip select high 
  GPIOA->BSRRL |= GPIO_Pin_4; // set PA4 high

  // enable SPI1 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_StructInit(&SPI_InitStruct); // set default settings 
  SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // set to full duplex mode, seperate MOSI and MISO lines
  SPI_InitStruct.SPI_Mode = SPI_Mode_Master;     // transmit in master mode, NSS pin has to be always high
  SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b; // one packet of data is 8 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 ; // set the NSS management to internal and pull internal NSS high
  SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; // SPI frequency is APB2 frequency / 4
  SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;// data is transmitted MSB first
  SPI_Init(SPI1, &SPI_InitStruct); 

  NVIC_InitStructure.NVIC_IRQChannel = SPI1_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);  

  return;
}        

Configuración de DMA:

void DMA_Config()
{  
DMA_InitTypeDef DMA_InitStructure;   
NVIC_InitTypeDef NVIC_InitStructure;

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);

DMA_ClearFlag(DMA2_Stream2,        DMA_FLAG_FEIF2|DMA_FLAG_DMEIF2|DMA_FLAG_TEIF2|DMA_FLAG_HTIF2|DMA_FLAG_TCIF2);
DMA_Cmd(DMA2_Stream2, DISABLE);
while (DMA2_Stream2->CR & DMA_SxCR_EN);
DMA_DeInit(DMA2_Stream5);
DMA_StructInit(&DMA_InitStructure);

DMA_InitStructure.DMA_Channel = DMA_Channel_3;
DMA_InitStructure.DMA_PeripheralBaseAddr  = (uint32_t) &(SPI1->DR);
DMA_InitStructure.DMA_Memory0BaseAddr  = (uint32_t) &spiTxBuff;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_BufferSize  = SPI_TX_MAX;
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_Normal;
DMA_InitStructure.DMA_Priority  = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode  = DMA_FIFOMode_Disable;

DMA_Init(DMA2_Stream5, &DMA_InitStructure); 

/**
configuration of the interrupts of DMA
******************************************************/
DMA_ITConfig(DMA2_Stream5, DMA_IT_TC, ENABLE);
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);  
return;
}

Función de escritura SPI:

void SPI1_Write(uint8_t *txBuff,int length,tSPI_Callback fct)
{
 DMA2_Stream5->M0AR = (uint32_t) &spiTxBuff;
 DMA_Cmd(DMA2_Stream5, ENABLE);
 SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);
 SPI_Cmd(SPI1, ENABLE);
}

Los datos recibidos se escriben en el búfer Rx utilizando el controlador de interrupciones SPI.

void SPI1_IRQHandler()
{
 spiRxBuff[spiRxCount] = SPI_I2S_ReceiveData(SPI1);
 spiRxCount++;
}

Estoy llamando a estas funciones main()de la siguiente manera:

C Principal:

DMA_Config();
init_SPI1();
SPI1_Write(spiTxBuff,SPI_TX_MAX,(void*)0); 

Usando un depurador, descubrí que, en el registro de estado de interrupción alta de DMA, TCIF5 (Bandera de transferencia completa) y HTIF5 (Bandera de media transferencia completa) están configurados en 1, lo que significa que la transferencia se realizó con éxito, en mi opinión, sin embargo, no No obtengo ningún dato en el SPI Rx Buffer. La segunda cosa extraña es que ni DMA Interrupt ni SPI Interrupt se activan. ¿Podría ayudarme a averiguar qué está mal en mi código?

¿Qué pasa con el Tx, está funcionando? ¿Ha intentado poner un punto de interrupción en el controlador de interrupciones SPI para verificar si alguna vez se activó?

Respuestas (1)

Hay algunos errores que corregí y obtuve el resultado esperado:

1) La interrupción SPI Rx no está configurada, esta línea SPI_I2S_ITConfig(SPI1,SPI_I2S_IT_RXNE,ENABLE)se perdió

2) En la función DMA_Config, las interrupciones DMA1 están habilitadas en lugar de DMA2, esta líneaNVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream5_IRQn;

Esta es la solución de trabajo