I am trying to set up the INMP441 digital I2S microphone with the Kinetis K22F Freedom Board. The microphone data sheet is at:
http://www.invensense.com/mems/microphone/documents/INMP441.pdf
I have been able to implement the correct settings for the Bit Clock and Frame Sync (64 clocks per frame, 2 words per frame, etc...) through the 5 I2Sx_RCR registers. I am now trying to quickly obtain data from the microphone but have not been successful. Here is my code.
CHIPEN = 1;
L = 1;
//Pins Init
SIM_SCGC5 |= 0x42B82; //Enables PORTC
PORTC_PCR5 |= 0x400; //PTC5 --> I2S0_RXD0 -> DATA (coming from Microphone)
PORTC_PCR7 |= 0x400; //PTC7 --> I2S0_RX_FS -> FRAME (Sent to Microphone)
PORTC_PCR9 |= 0x400; //PTC9 --> I2S0_RX_BCLK -> BITCLOCK (Sent to Microphone)
//Clock Init
SIM_SCGC6 |= 0x8000; //Turn on I2S Clock Gate
SIM_SOPT2 |= 0x30000; //I2S Clocking Sourced from 48MHz IRC48MCLK
I2S0_MCR |= 0x43000000; //Output Enable. Mux IRC48MCLK into Fractional Divider
I2S0_RCR2 |= 0x4000000; //MCLK MSEL to BCLK
I2S0_MDR |= 0x1F07C; //Set I2S Master Clock to 12.2880MHz
I2S0_RCR2 |= 0x300000D; //DIV is 13 - > 9000kHz Sample Rate. BCD = 1
SIM_SCGC6 |= 0x8000; //Re-Enable I2S Module
//Receive Init
I2S0_RCSR = 0x0; //Disable Receive as per Datasheet
I2S0_RCR1 |= 0x1; //Sets FIFO Watermark to 1
I2S0_RCR3 |= 0x10000; //Enable Receive Data Channel
I2S0_RCR4 |= 0x11F19; //Internal Frame Sync. Early Frame Sync. 32 SYWD. FRSZ 2.
I2S0_RCR5 |= 0x1F1F1F00; //32 Bits per Word. 32 Bits in First Word. Shifted 32.
I2S0_RCSR = 0x2000000; //FIFO Reset
I2S0_RCSR |= 0x80000100; //Enable and FIFO Enable
while(1) {
if(I2S0_RCSR & 0x10000){
pr(&I2S0_RDR0); //Reads content from data register, problem is that is constantly 0
led_red = 0;
}
}
}
The problem is that the I2S0_RDR0 register is stuck at 0. So evidently I am not getting data from the microphone. Any ideas? (The microphone is indeed sending data on the right channel as confirmed with an oscilloscope)
解決済! 解決策の投稿を見る。
The FIFO was overflowing, an error flag was raised and never cleared so the FIFO didn't accept more data. The fix is setting FCONNT and clearing the error:
if(I2S0_RCSR & 0x10000){
pr(&I2S0_RDR0);
led_red = 0;
}
if (I2S0_RCSR & 0x20000){
I2S0_RCSR |= 0x20000;
}
Hi, Eduardo,
has your issue fixed yet? If not, can you use interrupt mechanism to read the I2S0_RDR0 without FIFO?
BR
XiangJun Rong
The FIFO was overflowing, an error flag was raised and never cleared so the FIFO didn't accept more data. The fix is setting FCONNT and clearing the error:
if(I2S0_RCSR & 0x10000){
pr(&I2S0_RDR0);
led_red = 0;
}
if (I2S0_RCSR & 0x20000){
I2S0_RCSR |= 0x20000;
}
Some updates: The FIFO request flag is going high, so I am able to read I2S0_RDR0. However, the FIFO then overflows. The FIFO error flag rises.
Any hints as to how to keep the FIFO from overflowing?
Hi, Eduardo,
As you know that the RFW bits in I2Sx_RCR1 register specifies the watermark level, for example, if you set RFW bits as 3, once the FRF bit in I2Sx_RCSR register is set, you can read the I2S0_RDR register 4 times to empty the FIFO.
BR
XiangJun Rong
Hi, Eduardo,
Regarding your question, I do not think you have the code to poll the status register to check if the I2S has received the data, then read the I2S0_RDR0 register.
how about using the code:
while(1){
// wait(0.01);
if(I2S0_RCSR&0x10000) //check the FIFO Request Flag
{
pr(&I2S0_RDR0); //Prints register address and contents
led_red = 0;
}
I do not debug your code, pls have a try to test the code.
BR
XiangJun Rong
Unfortunately that didn't work. The FIFO request flag is not raised, so the contents of I2S0_RDR0 are never read.
I think the issue is the micro controller not "interpreting/receiving" the data because the microphone is indeed sending it. Two possible issues come to mind:
1) The data from the microphone should be connected to I2S0_RDX0, right?
2) The data sheet talks about enabling the receive channel to access the FIFO. Am I forgetting to enable a channel, a FIFO or something along those lines?