2025-03-12 7:46 AM
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.
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);
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/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.
Solved! Go to Solution.
2025-03-12 10:06 AM
Master Inter Data Idleness can be used to have CS pulse high between words.
2025-03-12 10:06 AM
Master Inter Data Idleness can be used to have CS pulse high between words.
2025-03-13 3:49 AM - edited 2025-03-13 3:56 AM
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.
Could you point me toward a solution or some ressources to achieve this?
Thanks again,
jmF
2025-03-13 6:29 AM
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.
2025-03-13 6:52 AM - edited 2025-03-13 7:38 AM
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