cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F439 I2S double the audio frequency

Jtron.11
Senior

Hi all,

I reach out to you all to give some pointers or advice for me where to look into to solve this mystery.

I set up my Nuc-STM32F439ZI eval board i2s peripheral to play my audio sine wav file.

I used Audacity to generate 13KHz sine wave audio file with 48KHz sampling, 16-bit PCM wav file, then using Wav2Code to generate the array binary.

For STM32, I set I2S with 48KHz Sampling rate, Half-Duplex Master, Mode Master Transmit, I2S Philips, 16 bits data on 16 bits frame, DMA half word, Circular mode.

I2S generated correct signal, bit clock, frame rate, data valid but when I feed this sine wave to an amplifier and monitor the output of the amplifier on the scope, I saw my sine wave double in frequency which is 22KHz to 26KHz.

I then tried different way to create the sine wave with the look up table from the sine wave math function with the frequency of 1KHz, and the result is the same at the amplifier output, I got 2KHz sine wave.

Does anyone else this behavior or anything you experienced?

2 REPLIES 2

> I2S generated correct signal, bit clock, frame rate,

How did you verify that?

> data valid

What's that?

> then tried different way to create the sine wave with the look up table from the sine wave math function with the frequency of 1KHz, and the result is the same at the amplifier output, I got 2KHz sine wave.

There are many ways how to do a mistake when generating signal. Show how do you do it.

JW

> I2S generated correct signal, bit clock, frame rate,

How did you verify that?

I used logic analyzer to check the I2S signal from STM32's I2S pins, bit clock, frame, data all decoded from the array data.

>data valid meaning my I2S signals matching with my prepared data array.

For the manual way to generate the data for sine wave, you are correct there are so many way, and I used the references online showing how to generate the buffer of data using sine wave in math.h header file.

The details is here

https://www.phippselectronics.com/i2s-audio-tutorial-variable-frequency-sine-wave-output/?srsltid=AfmBOooTV4wQHR4cb-eJ_hegJ-KJ6lrh3qPybHbS98dyWNejJAjF8iUq

In short

#include "limits.h"
#include "math.h"

const int Fs = 48000; // sample rate (Hz)
const int LUT_SIZE = 1024; // lookup table size

int16_t LUT[LUT_SIZE]; // our sine wave LUT

for (int i = 0; i < LUT_SIZE; ++i)
{
LUT[i] = (int16_t)roundf(SHRT_MAX * sinf(2.0f * M_PI * (float)i / LUT_SIZE));
} // fill LUT with 16 bit sine wave sample values

// frequency we want to generate (Hz)
int f = 1000;
 
// Generate sine wave with chosen frequency
const int BUFF_SIZE = 4096;  // size of output buffer (samples)
int16_t buff[BUFF_SIZE];     // output buffer
 
// frequency we want to generate (Hz)
 
const float delta_phi = (float) f / Fs * LUT_SIZE;
                               // phase increment
 
float phase = 0.0f;          // phase accumulator
 
// generate buffer of output
for (int i = 0; i < BUFF_SIZE; ++i)
{
    int phase_i = (int)phase;        // get integer part of our phase
    buff[i] = LUT[phase_i];          // get sample value from LUT
    phase += delta_phi;              // increment phase
    if (phase >= (float)LUT_SIZE)    // handle wrap around
        phase -= (float)LUT_SIZE;
}
 
Once you have the buffer data (or array of data) just send it to start it with HAL_I2S_Transmit_DMA function call
 
@waclawek.jan, may I ask which method you used to create your sine wave and how did you configured your I2S and how would you verify your signal so maybe I can follow and try to follow your steps to create a sine wave with the correct frequency?