cancel
Showing results for 
Search instead for 
Did you mean: 

Audio ADC/DAC timing/sampling questions

mikemillernow
Associate II
Posted on April 25, 2014 at 11:00

All,

1.) I took 128,  16-bit data points and created a sine wave:

const uint16_t Sine12bit[128] = {

  2047, 2447, 2831, 3185,

  3498, 3750, 3939, 4056,

  4095, 4056, 3939, 3750,

  3495, 3185, 2831, 2447,

  2047, 1647, 1263,  909,

  599,  344,  155,   38,

  ....

   4095, 4056, 3939, 3750,

  3495, 3185, 2831, 2447,

  2047, 1647, 1263,  909,

   599,  344,  155,   38,

     0,   38,  155,  344,

   599,  909, 1263, 1647};

2.) I broke this into 256 bytes (8-bits) and wrote out to a page (1 page = 256 bytes) of my SPI based serial flash.

3.) I then wrote out this same data to all the other pages of my SPI based serial flash. There are a total of 16,384 pages.

4.) I am then reading each page at a time playing a tone (the waveform) out with the DAC. Using a combination of the

DAC,Timer2, DMA, and interrupts.

5.) When I measure the frequency of the generated waveform, it looks nice an clean with a frequency of 6.25kHz.

6.) For the Timer2 configuration the period is setup usign the following line:

 Period = (SystemCoreClock / 200000); //  6.25 KHz Sine

 

 The SystemCoreClock is 48 MHz.

7.) When I play this tone reading for all the pages of memory it only lasts about 10 seconds.

8.) I am not clear on a few things:

- I don't see how I can get 6.25 kHz based on the line above.  48MHz / 200000 = 240. 1/240 = 0.0041?

- Based on the size of the pages of memory (256), total memory size (16,384 pages) and the timer2 settings above how long should it take to read through the entire memory? The 10 seconds seems too short.

- For recording and playign back voice I want to be operating at a 16 kHz for the sample rate.  If I am sampling 128 (16-bit) values from the ADC and write out 256 bytes to my SPI flash how should the timer be setup?  What should the divider be?

- How much recording time should I get with a sample rate of 16 kHz?

- Any other suggestions to help my understanding?

Thanks.

-Mike

8 REPLIES 8
Posted on April 25, 2014 at 13:26

6.) For the Timer2 configuration the period is setup using the following line:

 

 

 Period = (SystemCoreClock / 200000); //  6.25 KHz Sine

 

 

 

 The SystemCoreClock is 48 MHz.

 

 

 

7.) When I play this tone reading for all the pages of memory it only lasts about 10 seconds.

 

 

 

8.) I am not clear on a few things:

 

 

 

- I don't see how I can get 6.25 kHz based on the line above.  48MHz / 200000 = 240. 1/240 = 0.0041?

The original example this was lifted from has a 200 KHz sample rate, and a 32 entry sine table.

The line sets the period of the timer to 200 KHZ.

200000 / 32 = 6250

48000000 / 200000 = 240

Conversely

48000000 / 240 = 200000

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
mikemillernow
Associate II
Posted on April 29, 2014 at 07:25

Thanks for the post.

Okay so if I want a 16 kHz sampling this is a period of 6.25e^-5 seconds (0.0000625 seconds).

Does this look correct?

Period = (SystemCoreClock / 768000000000);   // 16 kHz timing?

48,000,000 / 768000000000 = 0.0000625seconds.

Thank you.

-Mike

mikemillernow
Associate II
Posted on April 29, 2014 at 08:04

I updated the code as shown below to try and get the 16 kHz sampling rate. The numbers don't look right to me.

 Period = (SystemCoreClock / 768000000000 );

After execution the variable period is zero. (Period = 0).

Then there is the configuration lines:

  /* Time base configuration */

  TIM_TimeBaseStructure.TIM_Period = Period - 1;

  TIM_TimeBaseStructure.TIM_Prescaler = 0;

  TIM_TimeBaseStructure.TIM_ClockDivision = 0; // not relevant here

  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

TIM_Period is equal to 4294967295

TIM_Prescaler is equal to 0

TIM_ClockDivision is equal to 0

TIM_CounterMode is equal to 0

What am I doing wrong?

Thank you.

-Mike

Posted on April 29, 2014 at 08:54

Good grief

 Period = (SystemCoreClock / (32 * 6250)); //  6.25 KHz Sine from 32 point table

 Period = (SystemCoreClock / 200000); //  200 KHz Sample Rate

 Period = (SystemCoreClock / 16000); //  16 KHz Sample Rate

You are attempting to compute the number of ticks in SystemCoreClock units that relate to the frequency you are trying to generate. Depending on the size of the timer in question this would need to fit in a 16-bit or 32-bit variable, where it cannot you'd need to factor the number between the Period and Prescaler.

For 1 Hz the clock would need to tick SystemCoreClock units, perhaps expressed as 48000 * 1000

For 16 KHz, we have 48000000 / 16000, or 3000, and the value is programmed into the TIM as an N-1 number as the counter will tick 0..2999 before updating, and triggering the ADC and/or DAC
Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
mikemillernow
Associate II
Posted on April 29, 2014 at 09:16

Thanks again for the post. ''Good grief'' - well how do you think I feel! Ha. 🙂

1.) To verify the frequency I went back to the following line for 200 kHz. Period = (SystemCoreClock / 200000); // 200 KHz timebase 2.) Added line to update the interrupt TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); 3.) Configure the NVIC to use the TIM2_IRQn. 4.) In the interrupt handler for TIM2 I take PA3 high and then low so I can measure this on my oscilloscope.

void TIM2_IRQHandler()
{
int flag = 0;
GPIO_SetBits(GPIOA, GPIO_Pin_3); // set PA3 chip select high. for timing.
flag = 1;
GPIO_ResetBits(GPIOA, GPIO_Pin_3); // set PA3 chip select low for timing.
}

5.) I was expecting to see 200 kHz but I am measuring a frequency of 99 kHz instead. Any ideas? Thank you. -Mike.
Posted on April 29, 2014 at 09:27

You'd want to clear the Update interrupt as you enter the service routine. The 925 KHz represents the saturation point of the CPU as it constantly re-enters the uncleared IRQ.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Posted on April 29, 2014 at 09:32

void TIM2_IRQHandler()
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) // Qualify (Optional but preferred)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update); // Clear
GPIO_SetBits(GPIOA, GPIO_Pin_3); // set PA3 chip select high. for timing.
GPIO_ResetBits(GPIOA, GPIO_Pin_3); // set PA3 chip select low for timing.
}
}

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
mikemillernow
Associate II
Posted on April 29, 2014 at 09:33

Dang you are good! Thanks! I will do this!

-Mike