|
I2S Slave Прием - хелп!, Глючит |
|
|
|
Mar 4 2013, 16:26
|
Профессионал
    
Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763

|
Работал с I2S-мастером, что прием что передача в 16 битах - никаких проблем небыло. Сейчас пробую прием слейвом 24-2 бита, не могу понять где глюки. I2S3 - мастер-передатчик, с него подаю прямо на I2S2 - слейв-приемник. Передаю одно и то-же число в каждом канале, 32 бита, 48кгц., передатик тактируется внешним клоком. Контролирую осциллографом шину - там все идеально, числа соответствуют. Приемник считывает в 2 переменые - и там числа не совпадают с переданными. Причем клик на ресет - и там уже другие числа. Инициализация приемника такая: CODE void InitI2S2(void){ // slave receiver I2S_InitTypeDef I2S2_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; u32 d; RCC_I2SCLKConfig(RCC_I2S2CLKSource_Ext); /* Enable the I2S peripheral clock */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); // GPIO GPIO_PinAFConfig(GPIOB,GPIO_PinSource12, GPIO_AF_SPI2); // WCLK GPIO_PinAFConfig(GPIOB,GPIO_PinSource13, GPIO_AF_SPI2); // BCLK GPIO_PinAFConfig(GPIOB,GPIO_PinSource15, GPIO_AF_SPI2); // SDATA GPIO_StructInit(&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_15; // WCLK, BCLK, SDATA GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); //------------------------------------------------------------------------ I2S_StructInit(&I2S2_InitStructure); I2S2_InitStructure.I2S_AudioFreq =I2S_AudioFreq_Default; I2S2_InitStructure.I2S_Standard = I2S_Standard_MSB; I2S2_InitStructure.I2S_DataFormat = I2S_DataFormat_32b; I2S2_InitStructure.I2S_CPOL = I2S_CPOL_Low; I2S2_InitStructure.I2S_Mode = I2S_Mode_SlaveRx; I2S2_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Disable; I2S_Init(SPI2, &I2S2_InitStructure); // -------------- interrupt: NVIC_InitStructure.NVIC_IRQChannel = SPI2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = I2SInputPriority; NVIC_InitStructure.NVIC_IRQChannelSubPriority = I2SInputSubPriority; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); while( (GPIOB->IDR & GPIO_Pin_12) 0= 0 ); // wait for WCLK=1 while( (GPIOB->IDR & GPIO_Pin_12) != 0 );// wait for WCLK=0 d=(uint32_t)SPI3->DR; // to clear RXNE bit if was d=(uint32_t)SPI3->SR; // to clear flags, if were SPI_I2S_ITConfig(SPI2,SPI_I2S_IT_RXNE,ENABLE); // enable interrupt I2S_Cmd(SPI2, ENABLE); // enable I2S2 } прием по прерыванию делаю так: Код volatile u16 LDataRcvL, LDataRcvH, RDataRcvL, RDataRcvH; // сюда считываю void SPI2_IRQHandler(void){ static u32 chan, sequence; chan = (SPI2->SR & I2S_FLAG_CHSIDE); // read CHSIDE = 0 for LEFT, 1 for RIGHT InpData=SPI2->DR;//SPI_I2S_ReceiveData(SPI2); // read reveived data sequence <<= 1; // bit1 = old sequence &= 0x2; // leave only bit1 = old chan value if (chan) sequence |=1; // bit0 = new chan value //--------------------------------------------------------- switch (sequence){ case 0: LDataRcvL = InpData; break; // Left Low case 2: LDataRcvH = InpData; break; // Left High case 1: RDataRcvH = InpData; break; // Right High case 3: RDataRcvL = InpData; break; // Right Low, End Of 2 channel receiving } } Помогите пожалуйста, понять в чем дело. Второй день бьюсь, что я делаю не так? Чувствую что где-то какая-то детская ошибка, понять бы где...
Сообщение отредактировал IgorKossak - Mar 6 2013, 07:30
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
|
|
|
|
|
Mar 4 2013, 18:37
|
Профессионал
    
Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763

|
Цитата(drum1987 @ Mar 4 2013, 19:14)  в прерывании sequence изначально чему равно? При старте программы - нулю, разумеется. Цитата если 0 как "по умолчанию", то строки: sequence <<= 1; // bit1 = old sequence &= 0x2; // leave only bit1 = old chan value делают непонять че... 0-й бит, который был равен chan в прошлый раз, сдвигается и становиться bit1 = old value. Все остальные биты сбрасываются в ноль, затем 0-й бит становиться равным текущему значению chan. Текущий определяет какой канал сейчас, предыдущее значениенужно для определение старшее или младшее слово принято. Что тут не так? Если Вы знаете другой способ определения какое слово какого канала было принято (или должно быть передано, т.к. в передатчике у меня тот-же алгоритм, и оно прекрасно работает) - расскажите, буду весьма благодарен. Хотя в любом случае проблема у меня не в этом. В любом случае, если бы был неправильный порядок бойт (слов) было бы пол беды, но там сами байты неправильные. И периодически выскакивает frame error, ]хотя и когда не вскакивает, принятые байты все равно не правильные (т.е. белибелрда, после каждого ресета разная, но после ресета - все время одинаковая).
|
|
|
|
|
Mar 5 2013, 05:17
|

Местный
  
Группа: Участник
Сообщений: 255
Регистрация: 3-02-09
Из: Омск
Пользователь №: 44 323

|
Попробуйте в прерывании еще проверять флаг RXNE... Вот пример из либы: Код void SPI2_IRQHandler(void) { /* Check the interrupt source */ if (SPI_I2S_GetITStatus(SPI2, SPI_I2S_IT_RXNE) == SET) { /* Store the I2S2 received data in the relative data table */ I2S2_Buffer_Rx[RxIdx++] = SPI_I2S_ReceiveData(SPI2); } } у меня прерывание по АЦП срабатывало намного чаще чем происходило прерывающее событие
Сообщение отредактировал IgorKossak - Mar 6 2013, 07:30
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
|
|
|
|
|
Mar 6 2013, 22:47
|
Профессионал
    
Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763

|
Цитата(aaarrr @ Mar 6 2013, 16:58)  И охота прерываться на частоте 384кГц? И это повод для глюков?  Мне в реалтайме нужно кое-какую обработку делать, она прекрасно успевает, если только приемник нормально заработает. Проблема-то не во времени, а в кривом I2S слейве у ST. (уже за то, что они по два прерывания на каждый канал дают, да еще без бита-признака старшее/младшее полуслово, их всех расстрелять как вредителей надо  ,, неужели не могли как у NXP передавать 32-х битное слово? не говоря уже о хотя бы промежуточном регисте, илитем более фифо!) Цитата Подключили бы давно DMA. Попробую, тем более что приятель подсказал мне как совместить и ДМА и ту обработку, что мне надо. Но проблем в том, что у него с ДМА приемник-слейв в 96 работает (ему больше пока и не надо), а на 192 и у него глючит.
|
|
|
|
|
Mar 6 2013, 23:11
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(Allregia @ Mar 7 2013, 02:47)  И это повод для глюков?  Нет, просто подход показался странным: 192кГц процессором - это уже 768кГц прерываний, или ~200 тактов между прерываниями на частоте 150МГц. Даже если и успевает, прорва ресурса вылетает в трубу. Цитата(Allregia @ Mar 7 2013, 02:47)  Попробую, тем более что приятель подсказал мне как совместить и ДМА и ту обработку, что мне надо. Но проблем в том, что у него с ДМА приемник-слейв в 96 работает (ему больше пока и не надо), а на 192 и у него глючит. Попробуйте. Я гонял I2S в слейве на STM'ах, но тоже только на 96. Выше просто нужды не было.
|
|
|
|
|
Mar 7 2013, 06:01
|
Профессионал
    
Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763

|
Цитата(aaarrr @ Mar 7 2013, 01:11)  Нет, просто подход показался странным: 192кГц процессором - это уже 768кГц прерываний, или ~200 тактов между прерываниями на частоте 150МГц. На самом деле сейчас еще хуже - это ДВА прерывания, каждое из которых 768кгц. Каждое из них длиться примерно 0.25мкс. Цитата Даже если и успевает, прорва ресурса вылетает в трубу. Половина, примно  А с ДМА - четверть памяти вылетает в трубу. Но мне уже подсказали как решить эту поблему, поэтому буду итди на ДМА. Я только пока не очень понял - могут ли два стрима одного канала одного контоллера работать одновременно ? (т.е. оба i2s2 и i2s3) Цитата Попробуйте. Я гонял I2S в слейве на STM'ах, но тоже только на 96. Выше просто нужды не было. Ну придется и мне ограничиться 96, если не получится выше, но хочется использовать все возможности.
|
|
|
|
|
Mar 7 2013, 09:45
|
Профессионал
    
Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763

|
Что-то у меня не получается I2S3 Master in DMA запустить. Делаю так: CODE static void I2S3_DMAInit( void ) { DMA_InitTypeDef DMA_InitStruct; DMA_Cmd( DMA1_Stream5, DISABLE ); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE); DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(SPI3->DR); // I2S Data DMA_InitStruct.DMA_Memory0BaseAddr = (u32)&DMABUF[0]; // memory start DMA_InitStruct.DMA_BufferSize = DMABUF_SIZE; // length DMA_InitStruct.DMA_Channel = DMA_Channel_0; DMA_InitStruct.DMA_DIR = DMA_DIR_MemoryToPeripheral; // direction DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // 16 bit per DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; // 16 bit memory DMA_InitStruct.DMA_Mode = DMA_Mode_Circular; // circ DMA_InitStruct.DMA_Priority = DMA_Priority_High; // prority DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Enable; // DMA_FIFOMode_Disable; DMA_InitStruct.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_INC4; //DMA_MemoryBurst_Single; DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; while( DMA_GetCmdStatus( DMA1_Stream5 ) == ENABLE ); // wait for the last DMA end DMA_Init( DMA1_Stream5, &DMA_InitStruct ); // Init New } //далее инитю i2s точно также, кака я его инитил при работе по прерываниям, только добавил несколько строк: I2S_Init(SPI3, &I2S3_InitStructure); I2S3_DMA_Init(); // <<<<<<<<<<<<<<< добавил SPI_I2S_DMACmd( SPI3, SPI_I2S_DMAReq_Tx, ENABLE); // <<<<<<<<<<<<<<< добавил I2S_Cmd(SPI3, ENABLE); DMA_Cmd( DMA1_Stream5, ENABLE ); // <<<<<<<<<<<<<<< добавил Передача не идет, i2s молчит. Может ему какой "стартовый пинок" еще дать надо, или у меня порядок вызовов Cmd не правильный? Ой, ложная тревога, "дело было не в бобине" - все работает. Код оставлю, может кому пригодится.
Сообщение отредактировал IgorKossak - Mar 7 2013, 15:10
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|