STM32H7 ADC DAC Timer
I have a timer that generates an event out on:
1. DAC to generate sine wave.
2. ADC to read the sine wave and do FFT.
Question 1:
I find that the fundamental frequency of the sine wave is as follows:
Counter value = ((Timer peripheral clock/desired frequency) / block size) * 2
where is this derived from?
Question 2:
I have a hard time to read back the generated sine wave. When doing FFT, I can see that the coefficients are oscillating, instead of flat. While the absolute value of coefficients sis the same, I assume it's phase shifted. Please correct me.
Upon tuning the ADC 14-bit with a oversampling ratio and sampling time, I've managed to get a stable FFT output (honestly by try and error). Changing the timer counter value requires another tuning. Is there a general idea/formula to get the sampling time right?
volatile int freq_array[number_of_frequencies] = {
10,
15,
20,
25,
30,
35
};
float freq_gain[number_of_frequencies] = {
0.9,
0.9,
0.9,
0.9,
0.9,
0.9
};
void generate_waveform() {
for (int i = 0; i < tx_waveform_size; i++) {
for (int j = 0; j < number_of_frequencies; j++) {
tx_waveform[i] = tx_waveform[i] + (freq_gain[j] * sin(freq_array[j] * (2 * M_PI) * i / tx_waveform_size));
}
tx_waveform[i] = tx_waveform[i] / number_of_frequencies;
val[i] = (2048 * tx_waveform[i]) + 2048; //Need t0 times by 2^12 as it is 12 bit DAC and then add 2048 so negative becomes positive
tx_waveform_buffer[i] = val[i]; //assign tx_waveform_buffer as it needs a uint value.
}
SCB_CleanDCache(); //clean out all of the d-cache to ensure the waveform is in the ram and not cache
}
void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef * adc) {
//checks to see if DMA1_stream0 is the dma transfer is complete, if so copy data and change status
if (HAL_NVIC_GetActive(DMA1_Stream0_IRQn) == 1) {
adc_buf_status[0] = true;
}
}
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef * adc) {
//checks to see if DMA1_stream0 is the dma transfer is complete, if so copy data and change status
if (HAL_NVIC_GetActive(DMA1_Stream0_IRQn) == 1) {
adc_buf_status[1] = true;
}
}
int adc_fft_function(void) {
//First if adc1 or 2 is half full. Will use 1 buffer as there will always be just one results processed at a time
if (adc_buf_status[0] == true) {
// do fft
}
}
