cancel
Showing results for 
Search instead for 
Did you mean: 

Use DAC of STM32F103RET6 to create meaningful sound.

biswajitjobapp
Associate II
Posted on July 14, 2014 at 12:47

Hello Everyone , I am using STM32F103RETG to create a sound.I am also using elua and minicom to execute the program onto the uc. My plan is to -

*first use the DAC wave generator to create a simple noise. I will be using pin PA4 and TIM6.

*Secondly, once the code is working I would extend the same to create a noise using the DMA.

*Third I would use some wave files to integrate with the code to produce meaningful sound.

So far, i have used the codes present on the discussion board to create a simple noise. The code is listed below.However, it does not seem to be working. Please have a look at the code and tell me if i need to do it differently. Any advice will be much appreciated. Thank you.

static int omniexp_dac_pa4( lua_State *L )

{

  GPIO_InitTypeDef GPIO_InitStructure;

  DAC_InitTypeDef DAC_InitStructure;

  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);

  TIM_TimeBaseStructure.TIM_Period = 0xF;

  TIM_TimeBaseStructure.TIM_Prescaler = 0xF;

  TIM_TimeBaseStructure.TIM_ClockDivision =0x0;

  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);

  /* TIM6 TRGO selection */

  TIM_SelectOutputTrigger(TIM6, TIM_TRGOSource_Update);

 

  /* Enable DAC and GPIOC clock */

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA, ENABLE);

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC | RCC_APB1Periph_TIM6, ENABLE);

 

  /* Configure PA.04 (DAC) as output -------------------------*/

 

  *GPIO_BB_ODR(GPIOA_BASE, 4)=0;

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

 

  /* DAC channel1 Configuration */

  DAC_InitStructure.DAC_Trigger = DAC_Trigger_T2_TRGO;

  DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_Triangle;

  DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_TriangleAmplitude_4095;

  DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;

  DAC_Init(DAC_Channel_1, &DAC_InitStructure);

  DAC_Cmd(DAC_Channel_1, ENABLE);

 

 

  /* TIM6 enable counter */

  TIM_Cmd(TIM6, ENABLE);

 

 

  while (1)

  {

  }

 

 

  /* DAC channel1 Configuration */

  DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;

  DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;

  DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;

  DAC_Init(DAC_Channel_1, &DAC_InitStructure);

}

9 REPLIES 9
Posted on July 14, 2014 at 14:03

Want to use AIN mode

STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Examples\DAC\DualModeDMA_SineWave\main.c

Posted some other Sine example, but for F0 and F4 chips
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
biswajitjobapp
Associate II
Posted on July 15, 2014 at 13:12

Thank you Clive...First of all I would like to mention that you are doing a very good work, specially in guiding newbies like me...I have seen your responses n it is really good.thanks keep up the good work..

Yes i went through the file that you mentioned.I managed to change the code and at this point i am able to create a triangular waveform on the oscilloscope. I have listed my code below so that some one else could use it for reference. However i dont know how to proceed to generate a noise and the subsequently a more meaningful sound. any advice would be appreciated. Thanks

static int omniexp_dac_pa4( lua_State *L )

{

DAC_InitTypeDef            DAC_InitStructure;

DMA_InitTypeDef        DMA_InitStructure;

TIM_TimeBaseInitTypeDef    TIM_TimeBaseStructure;

GPIO_InitTypeDef        GPIO_InitStructure;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC | RCC_APB1Periph_TIM2, ENABLE);

*GPIO_BB_ODR(GPIOA_BASE, 4)=0;

*GPIO_BB_ODR(GPIOA_BASE, 5)=0;

GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_4 | GPIO_Pin_5;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;

GPIO_Init(GPIOA, &GPIO_InitStructure);

//TIM2 configuration

// Time base configuration

TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);

TIM_TimeBaseStructure.TIM_Period = 0x19;

TIM_TimeBaseStructure.TIM_Prescaler = 0x0;

TIM_TimeBaseStructure.TIM_ClockDivision =0x0;

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);

/*DAC channel1 Configuration

DAC_InitStructure.DAC_Trigger = DAC_Trigger_T2_TRGO;

DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;

DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;

DAC_Init(DAC_Channel_1, &DAC_InitStructure);

*/

// DAC channel1 Configuration with triangle wave generator

DAC_InitStructure.DAC_Trigger = DAC_Trigger_T2_TRGO;

DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_Triangle;

DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_TriangleAmplitude_4095;

DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable;

DAC_Init(DAC_Channel_1, &DAC_InitStructure);

//DAC channel2 Configuration

DAC_Init(DAC_Channel_2, &DAC_InitStructure);

 /* Fill Sine32bit table */

  for (Idx = 0; Idx < 32; Idx++)

  {

    DualSine12bit[Idx] = (Sine12bit[Idx] << 16) + (Sine12bit[Idx]);

    lua_pushinteger(L, DualSine12bit[Idx]);

  }

#define DAC_DHR12RD_Address      0x40007420

DMA_DeInit(DMA2_Channel4);

DMA_InitStructure.DMA_PeripheralBaseAddr = DAC_DHR12RD_Address;

DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&DualSine12bit;

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;

DMA_InitStructure.DMA_BufferSize = 32;

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;

DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

DMA_InitStructure.DMA_Priority = DMA_Priority_High;

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

#if !defined STM32F10X_LD_VL && !defined STM32F10X_MD_VL

  DMA_Init(DMA2_Channel4, &DMA_InitStructure);

  /* Enable DMA2 Channel4 */

  DMA_Cmd(DMA2_Channel4, ENABLE);

#else

  DMA_Init(DMA1_Channel4, &DMA_InitStructure);

  /* Enable DMA1 Channel4 */

  DMA_Cmd(DMA1_Channel4, ENABLE);

#endif

  /* Enable DAC Channel1: Once the DAC channel1 is enabled, PA.04 is

     automatically connected to the DAC converter. */

DAC_Cmd(DAC_Channel_1, ENABLE);

  /* Enable DAC Channel2: Once the DAC channel2 is enabled, PA.05 is

     automatically connected to the DAC converter. */

DAC_Cmd(DAC_Channel_2, ENABLE);

  /* Enable DMA for DAC Channel2 */

DAC_DMACmd(DAC_Channel_2, ENABLE);

  /* TIM2 enable counter */

TIM_Cmd(TIM2, ENABLE);

}

biswajitjobapp
Associate II
Posted on July 16, 2014 at 11:17

Hello everyone,

Further to the discussion above, I connected a small speaker obtain from one the musical greetings card and connected it to pin PA4 and ground. There was no response.

I did the same for some other project using pin PA8, it did work then.

So am I doing something wrong here. Please advice me as I don't know how to proceed from this point onwards..Thanks

frankmeyer9
Associate II
Posted on July 16, 2014 at 11:46

I connected a small speaker obtain from one the musical greetings card and connected it to pin PA4 and ground. There was no response.

 

Look for the datasheet, check the DAC output impedance in unbuffered/buffered mode.

biswajitjobapp
Associate II
Posted on July 17, 2014 at 11:52

Thank you for the reply. Yes I did go through the datasheet and I have enabled the output buffer. Now i have a very low intensity humming on the speaker. Is it possible to increase the pitch of the humming without any amplifier? Also how is it possible to play a valid sound file. I am posting the code where the buffer has been enabled for others to have a reference.

DAC_InitStructure.DAC_Trigger = DAC_Trigger_T2_TRGO;

DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_Triangle;

DAC_InitStructure.DAC_LFSRUnmask_TriangleAmplitude = DAC_TriangleAmplitude_4095;

DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;

DAC_Init(DAC_Channel_1, &DAC_InitStructure);

DAC_Cmd(DAC_Channel_1, ENABLE);

Thankss!!

frankmeyer9
Associate II
Posted on July 17, 2014 at 13:01

Is it possible to increase the pitch of the humming without any amplifier?

 

No.

With DAC buffer, you get 15kOhm output impedance. For 3V, this means 200uA, i.e. 0.6 milliWatt. You will need a power amplification of about two orders of magnitude.

Also how is it possible to play a valid sound file.

 

Just configure a timer with the sample frequency of the waveform, and on each timer interrupt, write the next sample point to the DAC.

biswajitjobapp
Associate II
Posted on July 21, 2014 at 11:01

Thank you for your reply fm..

I found a solution to the low pitch. I cut down a headphone speaker and connected it to the pins instead of the greetings card speaker. As long as i hear the noise it doesn’t matter if its through heard phone or not.

However I am still confused about

 

Just configure a timer with the sample frequency of the waveform, and on each timer interrupt, write the next sample point to the DAC.

what sample frequency are we talking about?How do i use a .wav file and pass it onto the dac for output on the headphone. As I am very weak in programming so any sample code would be much appreciated.If not please advice me where to make changes to included these files and how... thanks once again.

frankmeyer9
Associate II
Posted on July 21, 2014 at 12:50

what sample frequency are we talking about?

 

The wav file represents sound, sampled at a certain frequency.

The WAV file format is a subset of the RIFF file, as used by Microsoft.

There are plenty of documentation and libraries + code examples for WAV decoding. I never tried that on a Cortex M, but I guess there are already libs around.

Once you know the sampling frequency, size and format of the data, one just needs to copy the audio data to the DAC data register, perhaps from the timer interrupt handler. For the latter, code examples are in several firmware libs and standard peripheral libs.

I never tried any Cube code...

biswajitjobapp
Associate II
Posted on July 24, 2014 at 13:13

Thank you fm ,,cheerss!!