Доброго времени суток.
Пытался повторить проект с микрофоном INMP441 с ютуба со ссылкой на код на гитхабе. Проект сделан на HAL. У меня китайская плата на процессоре stm32f407zgt6. Вроде сходу начало писать информацию, но при прослушивании в audacity абсолютная ерунда. Даже не слышу что-то похожее на голос, хотя громко включал ютуб передачи на телефоне и подносил к микрофону.
У меня есть еще плата stm32f3discovery. Попробовал на ней и результат тот же. Пробовал второй микрофон и такая же ерунда.
Тогда я запарился и переделал проект на CMSIS и в результате...пишет такую же какафонию с каким-то писком. Я сделал на stm32f3discovery slave-передатчик, а на китайской мастер-приемник и все прекрасно работает. Но не с микрофоном.
Я выложу свой код здесь, может кто сталкивался и сможет чего подсказать. Принцип простейший. Значащие первые 3 байта (24 бита на 32-битное слово). Сначала принимаю информацию от микрофона по I2S в буфер(64 слова 16-битных). От первого слова беру 2 байта, а от второго 1 первый байт и заполняю буфер на отправку в UART. Как заполнится - отправляю.
Пробовал отправлять первые 2 байта (типа 16 бит на 32 разрядное слово) - без толку тоже.
main.c:
Спойлер
Код:
#include "main.h"
#include "dma.h"
#include "i2s.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------*/
/* USER CODE BEGIN Includes */
uint16_t BUF_I2S[64];
uint8_t transmit_UART4[12];
/* USER CODE END Includes */
/* Private typedef ----------*/
/* USER CODE BEGIN PTD */
void SPI2_DMA_sets(void);
void I2S_set(void);
void UART4_DMA_sets(void);
void USART4_sets(void);
/* USER CODE END PTD */
void SystemClock_Config(void);
int main(void)
{
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
I2S_set();
SPI2_DMA_sets();
USART4_sets();
UART4_DMA_sets();
while((GPIOA->IDR&0x1)!=0x1)
{;}
SPI2->I2SCFGR |= 1<<10; // включаем I2S2
DMA1_Stream3->CR |= 1; // включаем DMA
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/* USER CODE BEGIN 4 */
void I2S_set(void)
{
RCC->APB1ENR |= RCC_APB1ENR_SPI2EN; // тактирование I2S2
SPI2->I2SPR |= 0x31; // ODE = 0, DIV = 0x31
SPI2->I2SCFGR |= 1<<11; // I2SMOD: Enable (1)
SPI2->I2SCFGR |= 3<<8; // 1 1(9 8) - master recive
SPI2->I2SCFGR |= 1<<1; // DATLEN - 01(24 bit)
SPI2->I2SCFGR |= 1; // CHLEN - 01(32 bit)
SPI2->I2SCFGR |= 1<<3; // polarity high
SPI2->CR2 |= 1; // RXDMAEN: Rx buffer DMA enable
GPIO_InitTypeDef GPIO_InitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
/* USER CODE BEGIN SPI2_MspInit 0 */
/* USER CODE END SPI2_MspInit 0 */
/** Initializes the peripherals clock
*/
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S;
PeriphClkInitStruct.PLLI2S.PLLI2SN = 50;
PeriphClkInitStruct.PLLI2S.PLLI2SR = 2;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
}
void SPI2_DMA_sets(void)
{
RCC->AHB1ENR|=RCC_AHB1ENR_DMA1EN; // включаем тактирование DMA1
DMA1_Stream3->PAR=(volatile uint32_t)(&(SPI2->DR)); // (volatile uint32_t)
DMA1_Stream3->M0AR=(volatile uint32_t)BUF_I2S; //tmp;//send_spi;
DMA1_Stream3->NDTR=64;
DMA1_Stream3->CR |= 1<<16; // PL: 0 1: Medium priority
DMA1_Stream3->CR |= 1<<10; // MINC: 1: Enabled
DMA1_Stream3->CR |= 0<<4; // DIR: 0: Read from peripheria
DMA1_Stream3->CR |= 1<<13; // 16 - bit пакет (msize)
DMA1_Stream3->CR |= 1<<11; // 16 - bit пакет (psize)
DMA1_Stream3->CR |= 1<<8; // CIRC: Circular mode - Enable (1)
DMA1_Stream3->CR |= 1<<3; // включаем прерывание по приему половины пакета данных
DMA1_Stream3->CR |= 1<<4; // включаем прерывание по приему полного пакета данных данных
// Настройка порта "B"
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN; // включить тактирование порта "B"
GPIOB->MODER |= 0x280000; // Включаем PB9, PB10 - альтернативная функция
GPIOB->AFR[1] |= 0x550; // включаем альтернативную функцию для AF5 для PB9, PB10
// Настройка порта "C"
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN; // включить тактирование порта "C"
GPIOC->MODER |= 0x80; // Включаем PC3 - альтернативная функция
GPIOC->AFR[0] |= 0x5000; // включаем альтернативную функцию для AF5 для PC3
GPIOC->OSPEEDR |= 0xC0; // скорость порта 11: Very high speed
NVIC_EnableIRQ(DMA1_Stream3_IRQn); // разрешение прерывания DMA1_Stream3 в регистре прерываний
NVIC_SetPriority(DMA1_Stream3_IRQn, 1); // установка приоритета прерывания в регистре прерываний
}
void USART4_sets(void)
{
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN; // включить тактирование порта "C"
GPIOC->MODER |= 0x200000; // включаем на порту PC10 режим "альтернативная функция" AF8
GPIOC->AFR[1] |= 0x800; // включаем альтернативную функцию для AF8 (Tx) для PC10
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; // включить тактирование порта "A"
GPIOA->MODER |= 0x8; // включаем на порту PA1 режим "альтернативная функция" AF8
GPIOA->AFR[0] |= 0x80; // включаем альтернативную функцию для AF8 (Rx) для PA1
RCC->APB1ENR |=RCC_APB1ENR_UART4EN;
UART4->BRR =0x9C; // 230400 // 0x4E; 460800 //0x138; 115200 (скорость обмена) //
UART4->CR1 |= 1<<7; // включаем TXEIE
UART4->CR1 |= 1<<3; // Transmitter enable
UART4->CR1 |= 1<<13; // включаем UART
}
void UART4_DMA_sets(void)
{
RCC->AHB1ENR|=RCC_AHB1ENR_DMA1EN; // включаем тактирование DMA1
DMA1_Stream4->CR |= 1<<27; // выбираем канал 4
DMA1_Stream4->PAR = (volatile uint32_t)&(UART4->DR);
DMA1_Stream4->M0AR = (volatile uint32_t)transmit_UART4;
DMA1_Stream4->NDTR = 8; // 12;
DMA1_Stream4->CR |= 1<<16; // PL: 0 1: Medium priority
DMA1_Stream4->CR |= 1<<10; // MINC: 1: Enabled
DMA1_Stream4->CR |= 1<<6; // DIR: (7 6) 0 1: Read from memory to periph
DMA1_Stream4->CR |= 1<<4; // включаем прерывание по приему полного пакета данных данных
UART4->SR &= ~0x40;
NVIC_EnableIRQ(DMA1_Stream4_IRQn); // разрешение прерывания DMA1_Stream3 в регистре прерываний
NVIC_SetPriority(DMA1_Stream4_IRQn, 1); // установка приоритета прерывания в регистре прерываний
}
/* USER CODE END 4 */
_it.c(только мои функции):
Спойлер
Код:
/* USER CODE BEGIN TD */
extern uint16_t BUF_I2S[64];
extern uint8_t transmit_UART4[12]; // [12];
/* USER CODE END TD */
/* Private define ----------*/
/* USER CODE BEGIN PD */
uint8_t tmp=0;
uint8_t c=0;
volatile uint16_t cnt=0; // volatile
/* USER CODE END PD */
void DMA1_Stream3_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Stream3_IRQn 0 */
if((DMA1->LISR&0x8000000)==0x8000000)
{
DMA1->LIFCR |= 0x8000000;
uint8_t i,j;
for(i=0,j=0;i<16;i=i+4,j=j+3)
{
transmit_UART4[j] = (uint8_t)((BUF_I2S[i+32]&0xFF00)>>8);
transmit_UART4[j+1] = (uint8_t)(BUF_I2S[i+32]&0x00FF);
transmit_UART4[j+2] = (uint8_t)((BUF_I2S[i+33]&0xFF00)>>8);
}
DMA1_Stream4->NDTR = 12; // 12;
DMA1_Stream4->CR |= 1; // включаем DMA
UART4->CR3 |= 1<<7; // DMAT: DMA enable transmitter
}
if((DMA1->LISR&0x4000000)==0x4000000)
{
DMA1->LIFCR |= 0x4000000;
uint8_t i,j;
for(i=0,j=0;i<16;i=i+4,j=j+3)
{
transmit_UART4[j] = (uint8_t)((BUF_I2S[i]&0xFF00)>>8);
transmit_UART4[j+1] = (uint8_t)(BUF_I2S[i]&0x00FF);
transmit_UART4[j+2] = (uint8_t)((BUF_I2S[i+1]&0xFF00)>>8);
}
DMA1_Stream4->NDTR = 12; // 12;
DMA1_Stream4->CR |= 1; // включаем DMA
UART4->CR3 |= 1<<7; // DMAT: DMA enable transmitter
}
}
void DMA1_Stream4_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Stream4_IRQn 0 */
if((DMA1->HISR&0x20)==0x20)
{
UART4->CR3 &= ~0x80; // DMAT: DMA disable transmitter
DMA1_Stream4->CR &= ~1; // выключаем DMA
}
DMA1->HIFCR |= 0x30;
}