2026-05-11 6:21 AM - last edited on 2026-05-11 8:16 AM by mƎALLEm
Hello,
I have implemented a DDS sine wave generator where I use a timer interrupt to update DDS phase word and also use the same timer triggering a SPI transmission via DMA to an external DAC using a nucleo-g431rb. I am now doing the same thing with a nucleoh723zg on a different pcb, but cannot achieve the same performance. I've only uploaded 1 spectrum image of the H7 output but the problem is the image I uploaded is not the constant spectrum, it's center frequency changes -20 to 20 Hz every sweep.
I am using ~16MHz SPI speed and I have checked hardware of both pcbs, there is no problem with the communication and DAC CS jitter is very low (or none) for both MCUs.
I also checked the phase word variables on the run via uart in H7 and saw that there are reoccurring (not periodic though) jumps in phase word. But I use uart so cannot be exactly sure about that.
I'm sure there are no missing interrupts which I'm controlling by flipping a GPIO pin.
I can use a direct write to SPI data register or use a buffer and update it and give that buffer to the DMA triggered by the same timer, both approaches worked in G4 board and both are giving the same results in H7.
My code and DDS output spectrums and scope images are below. I am using LL functions everywhere except for some initialization stuff that are turned off shortly after.
For reference
I've tried lowering SPI clock and lowering system clock
I've had problems with DMA when I used Dcache then I closed it, now using DMA and directly writing to SPI DR gives the same results.
Another thing that might be useful:
Last time I uploaded code to G4 was ~3 weeks ago, from the images I can see that there is no problem with the uploaded code or LUT in the ROM. However when I disconnect and reconnect H7, before uploading code again the signal in the scope is distorted, probably meaning some ROM corruption occurs when disconnecting or just powering up)
I'm thinking there is a problem with accessing phase accumulator variable (pa) in RAM but I turned off caching and also made all relevant variables volatile. Also I'm not using any optimization, and other things I'm supposed to do (sampling an external ADC via SPI etc.) are turned off, interrupt timings are not missed for sure.
//bi++; //buffer index (uint8_t)
pa += pp; //pa: phase accumulator, pp: phase word
di = (pa >> 17) & bm; // LUT size is 2^15 so 17 bit shift
//txBuffer[bi] = ((uint16_t) (amp*LUT[di])); //buffer used in G4 DMA
SPI5->TXDR = (uint16_t) (amp*LUT[di]);
/* //uart phase accumulator variable test,
if (dac_i == dac_test_size_i){ //pa is stored in a seperate bufferand then sent in
uart_start = 1; //another place to not interfere with interrupt
}
else{
dac_test_arr[dac_i] = pa;
dac_i++;
}
//*/
LL_GPIO_TogglePin(GPIOB,GPIO_PIN_8); //interrupt control GPIO
G4 spectrum
H7 spectrum
H7 scope before uploading new code
G4 scope
H7 scope
Phase Accumulator values at every update
2026-05-11 7:53 AM - edited 2026-05-11 7:54 AM
Hi,
whats the update rate of DDS ?
and which DAC ?
+
you should run on an H7 always with optimizer, i use -O2 always.
+ with d-cache off , helping .
BUT i would do it different on an H7 : to reduce time with INT
- make circular DMA , 2 x 1 K ; clocked by a timer ; DMA sending to SPI -> dac output ;
- in callbacks write the calculated phase values (1000 values)
So about 99% less busy with interrupt handling.
2026-05-11 8:13 AM
Hi,
I'm using AD5640 14-bit DAC,
DDS update rate is around 300kHz for G4, I tried from 500kHz to very low frequencies for H7, none of which work.
I have to sample 2 external ADCs via SPI very accurately and I use IIR filtering so I don't want to use bursts for data acquisition or DDS. I was able to do everything timed very accurately on G4, I bought an H7 for data processing speed so that I can sample faster.
Using any optimization was somehow messing with my recieve only master SPI channels (idk why) so that's why I'm not using them.