cancel
Showing results for 
Search instead for 
Did you mean: 

External DAC SPI interface speed optimization

jmF
Associate II

Hi,

I'm using the NUCLEO-H743ZI2 board and I'm trying to interface it with an external DAC MCP4922 via SPI.

As explained in the documentation, the CS pin is very important because it is used to mark the end of a transmission for the DAC to put the received value on its output.

jmF_0-1741702725267.png

The problem with this CS validation pin is that I can't use a SPI circular DMA with multiple values as I first imagined to do because in this case, the Hadrware NSS Output Signal configurable in the .ioc doesn't work as I would like (between each data).

My actuel program is then working like this:

I use a timer that I configure to my aimed sampling rate. I use his PeriodElapsedCallback to send a SPI frame to my DAC.

Here are some snippets of what I've done:

 

// My timer callback
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  if (htim == &htim6) {
	  pwmDAC();
  }
}

// Function to alternate the sample sent to the DAC to output a PWM
void pwmDAC() {
	uint16_t sample = pwm_level ? 0xFFFF : 0x0000;
	sendDAC(CHANNEL_A, sample);
	pwm_level ^= 1;
}

// Generic function to send a value to my DAC
void sendDAC(mcp4922_channel_t channel, uint16_t sample){
	uint8_t param = (channel << 7);
	param |= (0x03 << 4);
	uint16_t cmd = (param << 8) | ((sample >> 4) & 0x0FFF);

    HAL_SPI_Transmit(&hspi2, (uint8_t*)&cmd, 1, HAL_MAX_DELAY);
}

// In the main() I just start my timer with
// HAL_TIM_Base_Start_IT(&htim6);

 

CONFIGURATION:
SYSCLOCK fixed to 480MHz
APB Timer clock fixed to 120MHz
 jmF_1-1741788222878.pngjmF_2-1741788257304.png
Really easy but way to slow! When I configure my timer to go >≈ 130kHz ( 300kHz on the above screenshot)
SPI transmit doesn't follow and I have a huge gap between every sending!

jmF_3-1741788660744.pngjmF_4-1741788664546.png

     Figure 1 shows the SR limit I reach                  Figure 2 shows a typical SPI transmit with a 20Mhz speed

yellow: CS / purple: SCK / blue: MOSI / green: CHANNEL_A DAC output.

I made some research on the forum and found several discussions with similar issues. I've tried implementing some of them but I haven't been able to get them to work... As I'm still junior, I might be misunderstanding certain aspects and there are many things I still have to learn! I'de really appreciate any help!

Here are the discussions I've consulted:

https://community.st.com/t5/stm32-mcus-products/interface-with-external-adc-via-spi-at-1ms-s/td-p/74331

https://community.st.com/t5/stm32-mcus-products/spi-too-slow/m-p/251638

 

Don't hesitate to ask me if you need more ressources!

Thanks in advance for your help!

jmF

 

PS: Maybe there is a DAC that can be controlled without this CS mecanic. It would allow me to use SPI DMA circular with a pingpong buffer and use HalfCplt and Cplt flag.

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru

Master Inter Data Idleness can be used to have CS pulse high between words.

TDK_0-1741799171930.png

 

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

4 REPLIES 4
TDK
Guru

Master Inter Data Idleness can be used to have CS pulse high between words.

TDK_0-1741799171930.png

 

If you feel a post has answered your question, please click "Accept as Solution".
jmF
Associate II

Thank you very much @TDK, I managed to reach the aimed SR with this solution!

I would have a second question:

Including your solution, I have set up circular DMA on my SPI connection. Because I want to precisely be master of the SR of my DAC, I use synchronization signal of a timer. The problem is that I don't have other choice than TIM12.

I would like to be able to use an other timer (TIM6 for exemple), maybe I could use proposed DMAMUX but I really don't know how it works.

jmF_0-1741862826898.png

Could you point me toward a solution or some ressources to achieve this?

Thanks again,

jmF

What's the problem with using TIM12?

If you want the update rate to be constant, one method would be to set the SPI data rate and MIDI value such that you achieve the desired speed at 100% utilization. This is bulletproof.

If you put priority to max, synchronization signal may not be necessary.

If you feel a post has answered your question, please click "Accept as Solution".
jmF
Associate II

Thanks for your answer I'm going to try this as soon I can. 

If I understand well, if I need a 1MHz SR to transmit 16 bits frame, I have to put my SPI data rate at (1*(16+1))MHz  with a MIDI value set to 01 cycle? 

I'll keep you in touch whenever I'll have time to test this, have a very nice day,

jmF