cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4-Discovery Real-time microphone

kperente8
Associate
Posted on April 30, 2013 at 11:53

Hello,

I would like to use the internal microphone built in the board to hear the sound from headphone jack in real time. After that I 'll be implementing filter to the sound but thats not so important at the moment. The problem is static. Firstly i used a simple very short 16bit 16khz wave to test the headphone but I hear static no matter what I did. Also I tried with microphone but I realized that by adding a breakpoint at the spi interrupt, the code runs continously without entering interrupt routine. What am I missing? Any help will be appreciated. Note: I deleted the sound file in the sample array below because it is taking up much space.


/* Includes ------------------------------------------------------------------*/

#include ''stm32f4xx.h''

#include ''stm32f4_discovery.h''

#include ''stm32f4_discovery_audio_codec.h''

#include ''stm32f4xx_it.h''

#include ''pdm_filter.h''


/* Private define ------------------------------------------------------------*/

#define SPI_SCK_PIN GPIO_Pin_10

#define SPI_SCK_GPIO_PORT GPIOB

#define SPI_SCK_GPIO_CLK RCC_AHB1Periph_GPIOB

#define SPI_SCK_SOURCE GPIO_PinSource10

#define SPI_SCK_AF GPIO_AF_SPI2

#define SPI_MOSI_PIN GPIO_Pin_3

#define SPI_MOSI_GPIO_PORT GPIOC

#define SPI_MOSI_GPIO_CLK RCC_AHB1Periph_GPIOC

#define SPI_MOSI_SOURCE GPIO_PinSource3

#define SPI_MOSI_AF GPIO_AF_SPI2

#define AUDIO_REC_SPI_IRQHANDLER SPI2_IRQHandler

#define INTERNAL_BUFF_SIZE 64

#define OUTPUT_BUFF_SIZE 16

#define SAMPLE_SIZE_IN_BYTES 32

//64


/* Private macro -------------------------------------------------------------*/

/* Private variables ---------------------------------------------------------*/

uint32_t AudioRecInited = 0;

PDMFilter_InitStruct Filter;

uint32_t AudioRecBitRes = 16;

uint32_t AudioRecChnlNbr = 1;

uint16_t* pAudioRecBuf;

uint16_t OutputBuffer[OUTPUT_BUFF_SIZE];

uint16_t InternalBuffer[INTERNAL_BUFF_SIZE];

uint32_t InternalBufferSize = 0;

__IO uint8_t vol = 70;


uint16_t sample[] = {


};


uint16_t* sampleptr = &sample[0];


/* Private function prototypes -----------------------------------------------*/

uint32_t WavePlaybackInit(uint32_t AudioFreq);

void WavePlay(void);

uint32_t WaveRecorderInit(uint32_t AudioFreq);

uint8_t WaveRecorderStart(uint16_t* pbuf, uint32_t size);

uint32_t WaveRecorderStop(void);

void AUDIO_REC_SPI_IRQHANDLER(void);

void WaveRecorder_GPIO_Init(void);

void WaveRecorder_SPI_Init(uint32_t Freq);

void WaveRecorder_NVIC_Init(void);

void Delay(__IO uint32_t nCount);


/* Main ----------------------------------------------------------------------*/


int main(void)

{

//GPIO_InitTypeDef GPIO_InitStructure;


/* GPIOD Periph clock enable */

//RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);


/* Configure PD12, PD13, PD14 and PD15 in output pushpull mode */

//GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15;

//GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;

//GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

//GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

//GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

//GPIO_Init(GPIOD, &GPIO_InitStructure);


//STM_EVAL_PBInit(BUTTON_USER, BUTTON_MODE_EXTI);


WavePlaybackInit(I2S_AudioFreq_16k); //is it ok?

WaveRecorderInit(I2S_AudioFreq_16k); //why nonsense

WaveRecorderStart(OutputBuffer,OUTPUT_BUFF_SIZE);


WavePlay();


while (1)

{

//WavePlay();

/*

GPIO_SetBits(GPIOD, GPIO_Pin_12);

Delay(0x3FFFFF);

GPIO_SetBits(GPIOD, GPIO_Pin_13);

Delay(0x3FFFFF);

GPIO_SetBits(GPIOD, GPIO_Pin_14);

Delay(0x3FFFFF);

GPIO_SetBits(GPIOD, GPIO_Pin_15);

Delay(0x7FFFFF);

GPIO_ResetBits(GPIOD, GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);

Delay(0xFFFFFF);

*/

}

}


uint32_t WavePlaybackInit(uint32_t AudioFreq)

{

EVAL_AUDIO_SetAudioInterface(AUDIO_INTERFACE_I2S);

if(EVAL_AUDIO_Init(OUTPUT_DEVICE_HEADPHONE, vol, AudioFreq)!=0)

{

return 1;

}

else

{

return 0;

}

}


void WavePlay(void)

{

EVAL_AUDIO_Play((uint16_t*)pAudioRecBuf, SAMPLE_SIZE_IN_BYTES);

//EVAL_AUDIO_Play((uint16_t*)sampleptr, 8000);

}


uint32_t WaveRecorderInit(uint32_t AudioFreq)

{

/* Check if the interface is already initialized */

if (AudioRecInited)

{

/* No need for initialization */

return 0;

}

else

{

/* Enable CRC module */

RCC->AHB1ENR |= RCC_AHB1ENR_CRCEN;


/* Filter LP & HP Init */

Filter.LP_HZ = 8000;

Filter.HP_HZ = 10;

Filter.Fs = 16000;

Filter.Out_MicChannels = 1;

Filter.In_MicChannels = 1;


PDM_Filter_Init((PDMFilter_InitStruct *)&Filter);


/* Configure the GPIOs */

WaveRecorder_GPIO_Init();


/* Configure the interrupts (for timer) */

WaveRecorder_NVIC_Init();


/* Configure the SPI */

WaveRecorder_SPI_Init(AudioFreq);


/* Set state of the audio recorder to initialized */

AudioRecInited = 1;


/* Return 0 if all operations are OK */

return 0;

}

}


uint8_t WaveRecorderStart(uint16_t* pbuf, uint32_t size)

{

/* Check if the interface has already been initialized */

if (AudioRecInited)

{

/* Store the location and size of the audio buffer */

pAudioRecBuf = pbuf;


/* Enable the Rx buffer not empty interrupt */

SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, ENABLE);

/* The Data transfer is performed in the SPI interrupt routine */

/* Enable the SPI peripheral */

I2S_Cmd(SPI2, ENABLE);


/* Return 0 if all operations are OK */

return 0;

}

else

{

/* Cannot perform operation */

return 1;

}

}


uint32_t WaveRecorderStop(void)

{

/* Check if the interface has already been initialized */

if (AudioRecInited)

{


/* Stop conversion */

I2S_Cmd(SPI2, DISABLE);


/* Return 0 if all operations are OK */

return 0;

}

else

{

/* Cannot perform operation */

return 1;

}

}


void AUDIO_REC_SPI_IRQHANDLER(void)

{

u16 volume;

u16 app;


/* Check if data are available in SPI Data register */

if (SPI_GetITStatus(SPI2, SPI_I2S_IT_RXNE) != RESET)

{

app = SPI_I2S_ReceiveData(SPI2);

InternalBuffer[InternalBufferSize++] = HTONS(app);


/* Check to prevent overflow condition */

if (InternalBufferSize >= INTERNAL_BUFF_SIZE)

{

InternalBufferSize = 0;


volume = 50;


PDM_Filter_64_LSB((uint8_t *)InternalBuffer, (uint16_t *)pAudioRecBuf, volume , (PDMFilter_InitStruct *)&Filter);

}

}

}


void WaveRecorder_GPIO_Init(void)

{

GPIO_InitTypeDef GPIO_InitStructure;


/* Enable GPIO clocks */

RCC_AHB1PeriphClockCmd(SPI_SCK_GPIO_CLK | SPI_MOSI_GPIO_CLK, ENABLE);


/* Enable GPIO clocks */

RCC_AHB1PeriphClockCmd(SPI_SCK_GPIO_CLK | SPI_MOSI_GPIO_CLK, ENABLE);


GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;


/* SPI SCK pin configuration */

GPIO_InitStructure.GPIO_Pin = SPI_SCK_PIN;

GPIO_Init(SPI_SCK_GPIO_PORT, &GPIO_InitStructure);


/* Connect SPI pins to AF5 */

GPIO_PinAFConfig(SPI_SCK_GPIO_PORT, SPI_SCK_SOURCE, SPI_SCK_AF);


/* SPI MOSI pin configuration */

GPIO_InitStructure.GPIO_Pin = SPI_MOSI_PIN;

GPIO_Init(SPI_MOSI_GPIO_PORT, &GPIO_InitStructure);

GPIO_PinAFConfig(SPI_MOSI_GPIO_PORT, SPI_MOSI_SOURCE, SPI_MOSI_AF);

}


void WaveRecorder_SPI_Init(uint32_t Freq)

{

I2S_InitTypeDef I2S_InitStructure;


/* Enable the SPI clock */

RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);


/* SPI configuration */

SPI_I2S_DeInit(SPI2);

I2S_InitStructure.I2S_AudioFreq = Freq;

I2S_InitStructure.I2S_Standard = I2S_Standard_LSB;

I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b;

I2S_InitStructure.I2S_CPOL = I2S_CPOL_High;

I2S_InitStructure.I2S_Mode = I2S_Mode_MasterRx;

I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Disable;

/* Initialize the I2S peripheral with the structure above */

I2S_Init(SPI2, &I2S_InitStructure);


/* Enable the Rx buffer not empty interrupt */

SPI_I2S_ITConfig(SPI2, SPI_I2S_IT_RXNE, ENABLE);

}


void WaveRecorder_NVIC_Init(void)

{

NVIC_InitTypeDef NVIC_InitStructure;


NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);

/* Configure the SPI interrupt priority */

NVIC_InitStructure.NVIC_IRQChannel = SPI2_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

}


void Delay(__IO uint32_t nCount)

{

while(nCount--)

{

}

}


void EVAL_AUDIO_TransferComplete_CallBack(uint32_t pBuffer, uint32_t Size)

{

EVAL_AUDIO_Play((uint16_t*)pAudioRecBuf, SAMPLE_SIZE_IN_BYTES);

//EVAL_AUDIO_Play((uint16_t*)sampleptr, 8000);

}


uint16_t EVAL_AUDIO_GetSampleCallBack(void)

{

return 0;

}


uint32_t Codec_TIMEOUT_UserCallback(void)

{

return 0;

}

#stm32f4-discovery-microphone #hll-delay-loop #audio
6 REPLIES 6
Posted on April 30, 2013 at 15:18

''Firstly i used a simple very short 16bit 16khz wave to test the headphone but I hear static''

16kHz is pretty high - Are you sure your hearing is actually good for 16kHz? Are you sure your headphonesare actually good for 16kHz? Are you sure that the ret of the Audio path is good for 16kHz? Have you used a scope to see what the signal actually looks like? What, exactly, is this ''short 16bit 16khz wave'' - a file? static data? or what?



void Delay(__IO uint32_t nCount)

{

while(nCount--)

{

}

}

HLL delay loops - never a good idea!

See:

http://www.8com/forum/read/162556

And:

http://e2e.ti.com/support/microcontrollers/msp430/f/166/p/242306/8486aspx#848664

kperente8
Associate
Posted on April 30, 2013 at 18:33

Thanks for the reply. 16 kHz is the sampling rate actually. The array is filled with 440 Hz sine wave which I extracted from a wave file. The duration is 250ms.

I usedEVAL_AUDIO_TransferComplete_CallBack to play the file continously but as I've mentioned earlier I hear static. A portion of the sound file is as follows; (The numbers are hexadecimal and in two's complement form. I am not sure whether I need to arrange numbers for little endian structure of the microcontroller. In that case the least significant and the most significant bytes must be swapped.)

0x0000,0x0000,0x1602,0x1602,0x2B5B,0x2B5B,0x3F6B,0x3F6B,0x5196,0x5196,
0x6154,0x6154,0x6E2C,0x6E2C,0x77BC,0x77BC,0x7DBB,0x7DBB,0x7FFB,0x7FFB,
0x7E6C,0x7E6C,0x7918,0x7918,0x702A,0x702A,0x63E4,0x63E4,0x54A5,0x54A5,
0x42E1,0x42E1,0x2F1E,0x2F1E,0x19F5,0x19F5,0x0405,0x0405,0xEDF7,0xEDF7,
0xD872,0xD872,0xC41B,0xC41B,0xB18D,0xB18D,0xA155,0xA155,0x93EE,0x93EE,
0x89BF,0x89BF,0x8316,0x8316,0x8025,0x8025,0x8103,0x8103,0x85AA,0x85AA,
0x8DF4,0x8DF4,0x99A5,0x99A5,0xA861,0xA861,0xB9BA,0xB9BA,0xCD2B,0xCD2B,
0xE21F,0xE21F,0xF7F7,0xF7F7,0x0E0C,0x0E0C,0x23B6,0x23B6,0x384F,0x384F,
0x4B3C,0x4B3C,0x5BEB,0x5BEB,0x69DD,0x69DD,0x74A8,0x74A8,0x7BFA,0x7BFA,
0x7F9A,0x7F9A,0x7F6E,0x7F6E,0x7B76,0x7B76,0x73D0,0x73D0,0x68B8,0x68B8,
0x5A82,0x5A82,0x4999,0x4999,0x3680,0x3680,0x21C6,0x21C6,0x0C0C,0x0C0C,
0xF5F5,0xF5F5,0xE02B,0xE02B,0xCB54,0xCB54,0xB80E,0xB80E,0xA6ED,0xA6ED,
0x9873,0x9873,0x8D0E,0x8D0E,0x8516,0x8516,0x80C7,0x80C7,0x8042,0x8042,
0x838A,0x838A,0x8A88,0x8A88,0x9505,0x9505,0xA2B2,0xA2B2,0xB326,0xB326,
0xC5E4,0xC5E4,0xDA5D,0xDA5D,0xEFF5,0xEFF5,0x0608,0x0608,0x1BEC,0x1BEC,
0x30FB,0x30FB,0x4495,0x4495,0x5625,0x5625,0x6523,0x6523,0x711E,0x711E,
0x79BB,0x79BB,0x7EB8,0x7EB8,0x7FEF,0x7FEF,0x7D56,0x7D56,0x7702,0x7702

Posted on May 01, 2013 at 15:18

''The array is filled with 440 Hz sine wave which I extracted from a wave file. The duration is 250ms''

 

1 cycle of 440Hz is 2.27ms.

250ms is not a clean multiple of 2.27ms, so you're going to get a discontinuity at the end - ie, noise (aka ''static'').

As I said before, Have you used a scope to see what the signal actually looks like? That should give you a clue (possibly a BIG clue) as to what's going wrong...

''I am not sure whether I need to arrange numbers for little endian structure of the microcontroller''

You'd better find out, then! Again, the scope would help here.

As it's just 440Hz, you could possibly jut use a soundcard input if you don't have a scope...

sevketkahya
Associate II
Posted on February 06, 2014 at 10:25

Hi 

krmp8

,

I am net at embedded programming and I have started wit stm32f4. 

Now, I am trying to learn by making different projects. 

I want to make a project that you mentioned but I couldn't find appropriate resource for beginners. Can you upload your that project what you have done so far.

sevketkahya
Associate II
Posted on February 06, 2014 at 10:40

Hi 

krmp8

I am new at embedded programming and I have started wit stm32f4. 

Now, I am trying to learn by making different projects. 

I want to make a project like that you mentioned but I couldn't find appropriate resource for beginners. Can you upload your that project what you have done so far.

frankmeyer9
Associate II
Posted on February 06, 2014 at 15:00

You are posting to a thread almost one year old, were the original poster had done just 2 post up to now. Seems he is not a frequent user of this forum, so don't expect an answer.

If you look for STM32F4 ressources, try there for instance: 

http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/PF252419

(which is for the F4-Discovery board, featuring this MCU)

or here for the MCU, with links to related  tools and example code downloads: 

http://www.st.com/web/catalog/mmc/FM141/SC1169/SS1577/LN11/PF252140#

Using your favourite search engine, you might find much more.