2017-08-01 07:39 AM
I'm trying to communicate with AD5750 over the SPI. It requires full duplex SPI, where according to the timing diagram on page 9 of 36 in the data sheet, AD5750 is a slave SPI device, which is responding to a command with a readback. I wan't to fetch this readback and I'm able to poll it. However I would like to use the DMA so that I'm not loosing any time for waiting the communication to finish. The problem is that though I'm able to transmit data over the DMA, I'm not able to receive it, because RXEN flag is never set. Here is my initialization code:
static void SPI_Config(void) {
GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; DMA_InitTypeDef DMA_Init_Structure; NVIC_InitTypeDef NVIC_InitStructure;// NVIC_InitTypeDef NVIC_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); /* Connect SPI pins to AF5 */ // GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_SPI1); //SS 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 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //SCK GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //MISO GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //MOSI GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; //SS GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, &GPIO_InitStructure); //SPI Configuration RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE); SPI_I2S_DeInit(SPI1); SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //AD5620 doku page 18 falling edge of SCLK SPI_InitStructure.SPI_CRCPolynomial = 0; //x_8+x_2+x_1+1 in python hex(2**8+2**2+2+1) SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b; //AD5620 input register is 16 bit SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_Init(SPI1, &SPI_InitStructure); //DMA Globul Interrupt NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); //DMA Globul Interrupt NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); //DMA Configuration RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); DMA_DeInit(DMA2_Stream3); DMA_DeInit(DMA2_Stream2); DMA_Init_Structure.DMA_BufferSize = 1; DMA_Init_Structure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_Init_Structure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_Init_Structure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_Init_Structure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_Init_Structure.DMA_MemoryInc = DMA_MemoryInc_Disable; DMA_Init_Structure.DMA_Mode = DMA_Mode_Normal; DMA_Init_Structure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init_Structure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_Init_Structure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_Init_Structure.DMA_Priority = DMA_Priority_High; //Configure Tx DMA DMA_Init_Structure.DMA_Channel = DMA_Channel_3; DMA_Init_Structure.DMA_Memory0BaseAddr = (uint32_t)(&spi_tx_val); DMA_Init_Structure.DMA_PeripheralBaseAddr = (uint32_t) (&(SPI1->DR)); DMA_Init_Structure.DMA_DIR = DMA_DIR_MemoryToPeripheral; DMA_Cmd(DMA2_Stream3, DISABLE); while (DMA2_Stream3->CR & DMA_SxCR_EN); DMA_Init(DMA2_Stream3,&DMA_Init_Structure); //Configure Rx DMA DMA_Init_Structure.DMA_Channel = DMA_Channel_3; DMA_Init_Structure.DMA_Memory0BaseAddr = (uint32_t)(&spi_rx_val); DMA_Init_Structure.DMA_PeripheralBaseAddr = (uint32_t) (&(SPI1->DR)); DMA_Init_Structure.DMA_DIR = DMA_DIR_PeripheralToMemory; DMA_Cmd(DMA2_Stream2, DISABLE); while (DMA2_Stream2->CR & DMA_SxCR_EN); DMA_Init(DMA2_Stream2,&DMA_Init_Structure); // DMA_ITConfig(DMA2_Stream3,DMA_IT_TC,ENABLE); DMA_ClearFlag(DMA2_Stream3, DMA_FLAG_FEIF3|DMA_FLAG_DMEIF3|DMA_FLAG_TEIF3|DMA_FLAG_HTIF3|DMA_FLAG_TCIF3); DMA_ClearFlag(DMA2_Stream2, DMA_FLAG_FEIF2|DMA_FLAG_DMEIF2|DMA_FLAG_TEIF2|DMA_FLAG_HTIF2|DMA_FLAG_TCIF2); DMA_Cmd(DMA2_Stream3, ENABLE); //DMA SPI TX stream DMA_Cmd(DMA2_Stream2, ENABLE); //DMA SPI RX stream // SPI_SSOutputCmd(SPI1, ENABLE);// SPI_NSSInternalSoftwareConfig(SPI1,SPI_NSSInternalSoft_Set); SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Tx, ENABLE); SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Rx, ENABLE); SPI_Cmd(SPI1, ENABLE); }I have a breakpoint at DMA2_Stream3_IRQHandler which is never triggered. Why is the RXEN flag never set? It should be set after the last SCLK front. Should I use the SPI_SSOutputCmd()? I've tried it both ways, but neither is working.
2017-08-01 08:17 AM
Hello!
At your NVIC initialization , you initialised twice the stream 2 interrupts.(not stream 3)
Please, provide more details about your hardware to encourage the community to help you.
2017-08-01 08:39 AM
So here is the latest code I'm trying and it's not working on stm32f405
static void SPI_Config(void) {
GPIO_InitTypeDef GPIO_InitStructure; SPI_InitTypeDef SPI_InitStructure; DMA_InitTypeDef DMA_Init_Structure; NVIC_InitTypeDef NVIC_InitStructure;// NVIC_InitTypeDef NVIC_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); /* Connect SPI pins to AF5 */ // GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_SPI1); //SS 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 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //SCK GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //MISO GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //MOSI GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; //SS GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, &GPIO_InitStructure); //SPI Configuration RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE); SPI_I2S_DeInit(SPI1); SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //AD5620 doku page 18 falling edge of SCLK SPI_InitStructure.SPI_CRCPolynomial = 0; //x_8+x_2+x_1+1 in python hex(2**8+2**2+2+1) SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b; //AD5620 input register is 16 bit SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_Init(SPI1, &SPI_InitStructure); //DMA Globul Interrupt NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream3_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); //DMA Globul Interrupt NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); //DMA Configuration RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); DMA_DeInit(DMA2_Stream3); DMA_DeInit(DMA2_Stream2); DMA_Init_Structure.DMA_BufferSize = 1; DMA_Init_Structure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_Init_Structure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_Init_Structure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_Init_Structure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_Init_Structure.DMA_MemoryInc = DMA_MemoryInc_Disable; DMA_Init_Structure.DMA_Mode = DMA_Mode_Normal; DMA_Init_Structure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init_Structure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_Init_Structure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_Init_Structure.DMA_Priority = DMA_Priority_High; //Configure Tx DMA DMA_Init_Structure.DMA_Channel = DMA_Channel_3; DMA_Init_Structure.DMA_Memory0BaseAddr = (uint32_t)(&spi_tx_val); DMA_Init_Structure.DMA_PeripheralBaseAddr = (uint32_t) (&(SPI1->DR)); DMA_Init_Structure.DMA_DIR = DMA_DIR_MemoryToPeripheral; DMA_Cmd(DMA2_Stream3, DISABLE); while (DMA2_Stream3->CR & DMA_SxCR_EN); DMA_Init(DMA2_Stream3,&DMA_Init_Structure); //Configure Rx DMA DMA_Init_Structure.DMA_Channel = DMA_Channel_3; DMA_Init_Structure.DMA_Memory0BaseAddr = (uint32_t)(&spi_rx_val); DMA_Init_Structure.DMA_PeripheralBaseAddr = (uint32_t) (&(SPI1->DR)); DMA_Init_Structure.DMA_DIR = DMA_DIR_PeripheralToMemory; DMA_Cmd(DMA2_Stream2, DISABLE); while (DMA2_Stream2->CR & DMA_SxCR_EN); DMA_Init(DMA2_Stream2,&DMA_Init_Structure); // DMA_ITConfig(DMA2_Stream3,DMA_IT_TC,ENABLE); DMA_ClearFlag(DMA2_Stream3, DMA_FLAG_FEIF3|DMA_FLAG_DMEIF3|DMA_FLAG_TEIF3|DMA_FLAG_HTIF3|DMA_FLAG_TCIF3);// DMA_ClearFlag(DMA2_Stream2, DMA_FLAG_FEIF2|DMA_FLAG_DMEIF2|DMA_FLAG_TEIF2|DMA_FLAG_HTIF2|DMA_FLAG_TCIF2); DMA_Cmd(DMA2_Stream3, ENABLE); //DMA SPI TX stream DMA_Cmd(DMA2_Stream2, ENABLE); //DMA SPI RX stream // SPI_SSOutputCmd(SPI1, ENABLE);// SPI_NSSInternalSoftwareConfig(SPI1,SPI_NSSInternalSoft_Set); SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Tx, ENABLE); SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Rx, ENABLE); SPI_Cmd(SPI1, ENABLE); }void DMA2_Stream2_IRQHandler(void)
{ /* Test on DMA Stream Transfer Complete interrupt */ if(DMA_GetITStatus(DMA2_Stream2, DMA_IT_TCIF2)) { /* Clear DMA Stream Transfer Complete interrupt pending bit */ DMA_ClearITPendingBit(DMA2_Stream2, DMA_IT_TCIF2); }}And I have a breakpoint at DMA2_Stream2_IRQHandler which never triggers, because the RXNE flag is never 1. I assume so because I can't seen it with the debugger.
2017-08-01 08:50 AM
DMA_ITConfig(DMA2_Stream2, DMA_IT_TC,ENABLE); // You enable it for Stream 2 ?
2017-08-01 08:53 AM
// SPI_NSSInternalSoftwareConfig(SPI1,SPI_NSSInternalSoft_Set);
Why did you comment it out? Do you understand the implications of
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
?
JW
2017-08-01 10:26 AM
Yes. I'm sorry about that. The microcontroller ist smt32f405.
2017-08-01 10:29 AM
So rxdma must be channel 0 or 2?
2017-08-01 10:34 AM
It should be channel 2. Why do you thing it should be 0?
2017-08-01 10:35 AM
I meant channel 3 DMA_Channel_3, DMA is 2.
2017-08-02 02:45 AM
My understanding is that SPI_NSS_Soft configure the chip select signal to be controlled by the software. I don't know why SPI_NSSInternalSoftwareConfig(SPI1,SPI_NSSInternalSoft_Set); is needed, because I see no difference when I comment it.
FORTOUNAS.EVANGELOS
DMA_ITConfig(DMA2_Stream2, DMA_IT_TC,ENABLE);
make the breakpoint in the DMA2_Stream2_IRQHandler be triggered in the beginning and then no more. Even though if I try to pull a message withif(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE)==SET)
SPI_I2S_ReceiveData(SPI1);It's working.