2014-01-25 12:34 PM
Hi,
I am trying to sample some data using DMA and the internal ADC and send the same data , still using DMA to an external DAC using the SPI Internface, through an optoisolation barrier. It all works great, I need 1MS/s and this is not a problem. Still I need to qualify the data using a NSS line and TI Mode works fine, but the lack of wait states makes my task hard. The NSS is released on the 14th byte and re-issued on the 15th. Most of the DACs (I have been using DAC8311 for a while) need some time between the sync signal and the new data, so the NSS line needs to be inactive for a while between the subsequent data. I could not find any suitable DAC. Is the interface not suitable for such a task or am I missing something? Thanks Fabio2014-01-26 08:51 AM
You might want to use timer-triggered DMA.
JW2014-01-26 09:36 AM
Thanks for your suggestion,
If I understand you properly, you suggest to qualify the data via software in an IRS. I think this will not work because of the enormous amount of interrupts (@1MS/s I'll get 1 Interrupt every us). I either need DACs that support continuos mode, or I need to make somehow the transfer discontinuos to let the DAC have the necessary settling time or either build external glue logic (please noooo.....) Fabio2014-01-26 02:39 PM
No, what Jan is suggesting is that you pace the SPI DMA with a timer driven request instead of an SPI-TXE one.
That said the STM32 SPI implementation is going to be totally useless driving NSS in a useful way.2014-01-26 02:42 PM
What about a DAC using an I2S data stream?
2014-01-26 11:34 PM
> No, what Jan is suggesting is that you pace the SPI DMA with a timer driven request instead of an SPI-TXE one.
That is. The DMA transfer source/target does not necessarily needs to involve the trigger source, so you can trigger it from a timer (i.e. use stream/channel ''assigned to'' the timer) but set the SPI DR as transfer target. It's not obvious at the first reading, I guess. Of course, the timing has to be set right, and possible latency of the DMA transfer has to be taken into account. > That said the STM32 SPI implementation is going to be totally useless driving NSS in a useful way. Clive, Fabio above said he is OK with the TI mode. Alternatively, the same timer's compare could be used to generate a select signal, perhaps. > I2S That sounds like an interesting option, too, a bit less flexible perhaps, as the ''wait'' would be fixed to the same time as the transfer lasts - but it is up to Fabio to judge whether this fits his needs. JW2014-01-29 12:48 AM
2014-01-31 07:30 AM
So,
i decided to go for a timer triggered DMA transfer but I can't get it running... :( Well this is what I do, TMR3 is configured in PWM mode, works RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM3, ENABLE ); RCC_TIMCLKPresConfig(RCC_TIMPrescActivated); /* Time base configuration */ TIM_TimeBaseStructure.TIM_Period = 150; TIM_TimeBaseStructure.TIM_Prescaler = (uint16_t) (SystemCoreClock / 40000000) - 1; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); /* PWM1 Mode configuration: Channel1 */ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 5; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC1Init(TIM3, &TIM_OCInitStructure); TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update); TIM_Cmd(TIM3, ENABLE ); than I try to start DMA1 Stream 2 channel5 to get a DMA triggered everytime the timer overflows RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); DMA_DeInit(DMA1_Stream2); DMA_StructInit(&DMA_InitStructure); DMA_InitStructure.DMA_Channel = DMA_Channel_5; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI4->DR; DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&uwADC3ConvertedVoltage; DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; DMA_InitStructure.DMA_BufferSize = 1; 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_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_ITConfig(DMA1_Stream2, DMA_IT_TC, DISABLE); DMA_Init(DMA1_Stream2, &DMA_InitStructure); DMA_Cmd(DMA1_Stream2, ENABLE); TIM_DMACmd(TIM3, TIM_DMA_Update, ENABLE); Can't get it running....2014-02-02 06:14 AM
I fixed the issue,
it was trivial, as usual :(( DMA1 is not connected to APB2 and thus cannot trigger SPI4 transfers. I was trying to use the free pins on the 429discovery and didn't care much. Now TMR1 Ch3, pin PC8 is free, DMA2 on APB2 works. DMA sampling 1MS/s and sendind out SPI4, 500kS/s is not a problem. I send the data back and forth through an optoisolation barrier for kW level current control. Fabio2014-07-20 03:49 AM
Hi Fabio!
Thank you for this nice post. How did you configure the SPI? Do you require any additional code to start the transfer?Thank you for your answers,Blaz