cancel
Showing results for 
Search instead for 
Did you mean: 

Configuring I2S Clock (stm32h7)

Leo M
Associate

​Hello

I am trying to establish I2S communication with external audio codec. The manual says the I2S clock (Fi2s_clk) is a function of the audio frequency. There is table with example frequencies. For example, the table provides 3 examples for frequency Fws = 48kHz, and possible Fi2s_clk are 12.288MHz, 49.152MHz, and 61.44Mhz. I was not able to get such frequencies with the CubeMX application (i am using HSE=25Mhz). 

How can I configure the audio communication if I cannot set the right input clock for the I2S?

2 REPLIES 2
MikeDB
Lead

I had the same problem - Cube kept changing the dividers to random values even though someone showed me some fractional divide ratios that should work.

My assumption was that CubeMX doesn't work with the H7 so I am doing it by hand using the datasheet. But as I need different frequencies my code won't be much good to you. In any case for best performance you need to use an external 12.288MHz crystal which is about 20 cents.

Leo M
Associate

​So I fixed the problems and now I have a working codec (i am using TLV320AIC3204) with DMA.

I am going to share what I did for anywone who got here looking for answers.

1. Setting the I2S clock

I tried using cube to find a supported clock combination and it didn't provide. My audio is 44100 kHz and there was no supported clock. So I wrote a short script in Matlab to provide for me the available clock combinations nearest to what I needed. Matlab found some clocks that are approx. 0.01% from my target and that work well enough. Here is the code for anyone who needs such:

finput		= 25000000; %HSE
ftarget		= 41000;	%audio frequency, Fws
divm2_range = [1 63];
divn2_range = [4 512];
divp2_range = [1 128];
target_multipliers = [1 18];
 
structmember = struct('diff_from_target' ,1000, "divm",0, "divn",0,"divp",0,"I2SDIV_ODD",0);
answers_arr = [structmember structmember structmember structmember structmember structmember structmember structmember structmember structmember structmember structmember structmember structmember structmember structmember structmember structmember];
 
for d1=divm2_range(1):divm2_range(2)
	for d2=divn2_range(1):divn2_range(2)
		for d3=divp2_range(1):divp2_range(2)
			for t1=target_multipliers(1):1:target_multipliers(2)
				if t1==3
					continue;
				end
				normalized_multiplier = t1*256;
				result = finput/d1*d2/d3/normalized_multiplier;
				diff_from_target = abs(ftarget-result);
				if diff_from_target<answers_arr(end).diff_from_target
					answers_arr(end).diff_from_target = diff_from_target;
					answers_arr(end).divm = d1;
					answers_arr(end).divn = d2;
					answers_arr(end).divp = d3;
					answers_arr(end).I2SDIV_ODD = t1;
					[x,idx]=sort([answers_arr.diff_from_target]);
					answers_arr = answers_arr(idx);
				end
			end
		end
		
	end	
end

2. Using the DMA

DMA should be used over the supported RAM regions for DMA0 or DMA1. DMA should be configured to

hdma_spi1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;

to support the required transaction speed.