реклама на сайте
подробности

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
Allregia
сообщение Mar 4 2013, 16:26
Сообщение #1


Профессионал
*****

Группа: Свой
Сообщений: 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] - для короткого!!!
Go to the top of the page
 
+Quote Post
drum1987
сообщение Mar 4 2013, 17:14
Сообщение #2


Местный
***

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



в прерывании sequence изначально чему равно?
если 0 как "по умолчанию", то строки:
sequence <<= 1; // bit1 = old
sequence &= 0x2; // leave only bit1 = old chan value
делают непонять че...
если не нулю, а случайным числам, то тоже все понятно.
Go to the top of the page
 
+Quote Post
Allregia
сообщение Mar 4 2013, 18:37
Сообщение #3


Профессионал
*****

Группа: Свой
Сообщений: 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, ]хотя и когда не вскакивает, принятые байты все равно не правильные (т.е. белибелрда, после каждого ресета разная, но после ресета - все время одинаковая).
Go to the top of the page
 
+Quote Post
drum1987
сообщение Mar 4 2013, 19:07
Сообщение #4


Местный
***

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



сори не заметил строку
sequence |=1;
Go to the top of the page
 
+Quote Post
Allregia
сообщение Mar 4 2013, 19:28
Сообщение #5


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763



Кстати, я еше не пойму важно ли в каком порядке считывать статус (SR) и данные (DR) ?
Go to the top of the page
 
+Quote Post
drum1987
сообщение Mar 5 2013, 05:17
Сообщение #6


Местный
***

Группа: Участник
Сообщений: 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] - для короткого!!!
Go to the top of the page
 
+Quote Post
Allregia
сообщение Mar 5 2013, 06:10
Сообщение #7


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763



Попробую, хотя - другие источники преывания коме RXNE у меня не вкюлчены, не должно срабатывать.
Go to the top of the page
 
+Quote Post
Allregia
сообщение Mar 5 2013, 21:31
Сообщение #8


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763



Что-то страннно, сделал перекомпиляцию всей программы - на 48к заработало, без единого сбоя!
Попробовал переключить на 96к и выше - периодически выскакивает frame error, т.е. получается приемник не успевает где-то вовремя почитать принятое, и синхронизация сбивается. Передача по прежнему идет правильно (судя по сигналам на шине).

Приоритет прерываний - у передатчика 0, у приемника 1.
Завтра попробую наоборот, хотя по идее времени и летенси должно хватать в любом случае.
Go to the top of the page
 
+Quote Post
Allregia
сообщение Mar 6 2013, 14:29
Сообщение #9


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763



Пришлось в конце прерывания поставить
__ISB();

с ним заработало на 96, а вот на 192 все равно глючит.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Mar 6 2013, 14:58
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Allregia @ Mar 6 2013, 18:29) *
с ним заработало на 96, а вот на 192 все равно глючит.

И охота прерываться на частоте 384кГц? Подключили бы давно DMA.
Go to the top of the page
 
+Quote Post
Allregia
сообщение Mar 6 2013, 22:47
Сообщение #11


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763



Цитата(aaarrr @ Mar 6 2013, 16:58) *
И охота прерываться на частоте 384кГц?


И это повод для глюков? sm.gif
Мне в реалтайме нужно кое-какую обработку делать, она прекрасно успевает, если только приемник нормально заработает.
Проблема-то не во времени, а в кривом I2S слейве у ST.
(уже за то, что они по два прерывания на каждый канал дают, да еще без бита-признака старшее/младшее полуслово, их всех расстрелять как вредителей надо sm.gif,, неужели не могли как у NXP передавать 32-х битное слово? не говоря уже о хотя бы промежуточном регисте, илитем более фифо!)

Цитата
Подключили бы давно DMA.


Попробую, тем более что приятель подсказал мне как совместить и ДМА и ту обработку, что мне надо. Но проблем в том, что у него с ДМА приемник-слейв в 96 работает (ему больше пока и не надо), а на 192 и у него глючит.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Mar 6 2013, 23:11
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Allregia @ Mar 7 2013, 02:47) *
И это повод для глюков? sm.gif

Нет, просто подход показался странным: 192кГц процессором - это уже 768кГц прерываний, или ~200 тактов между прерываниями на частоте 150МГц.
Даже если и успевает, прорва ресурса вылетает в трубу.

Цитата(Allregia @ Mar 7 2013, 02:47) *
Попробую, тем более что приятель подсказал мне как совместить и ДМА и ту обработку, что мне надо. Но проблем в том, что у него с ДМА приемник-слейв в 96 работает (ему больше пока и не надо), а на 192 и у него глючит.

Попробуйте. Я гонял I2S в слейве на STM'ах, но тоже только на 96. Выше просто нужды не было.
Go to the top of the page
 
+Quote Post
Allregia
сообщение Mar 7 2013, 06:01
Сообщение #13


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763



Цитата(aaarrr @ Mar 7 2013, 01:11) *
Нет, просто подход показался странным: 192кГц процессором - это уже 768кГц прерываний, или ~200 тактов между прерываниями на частоте 150МГц.


На самом деле сейчас еще хуже - это ДВА прерывания, каждое из которых 768кгц.
Каждое из них длиться примерно 0.25мкс.

Цитата
Даже если и успевает, прорва ресурса вылетает в трубу.

Половина, примно sad.gif А с ДМА - четверть памяти вылетает в трубу. Но мне уже подсказали как решить эту поблему, поэтому буду итди на ДМА.
Я только пока не очень понял - могут ли два стрима одного канала одного контоллера работать одновременно ? (т.е. оба i2s2 и i2s3)

Цитата
Попробуйте. Я гонял I2S в слейве на STM'ах, но тоже только на 96. Выше просто нужды не было.

Ну придется и мне ограничиться 96, если не получится выше, но хочется использовать все возможности.
Go to the top of the page
 
+Quote Post
Allregia
сообщение Mar 7 2013, 09:45
Сообщение #14


Профессионал
*****

Группа: Свой
Сообщений: 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] - для короткого!!!
Go to the top of the page
 
+Quote Post
Allregia
сообщение Mar 7 2013, 11:25
Сообщение #15


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763



Но обнаружил другую проблему - случайно проинитил все два раза подряд, и... сдвинулись передаваемые слова между каналами!
Старшее слово левого стало младшим правого и т.д.
Почему при переинициализации все не сбросилось?
Но достаточно было поставить между двумя оинаковыми инициализациями задержку 5мс - глюк пропал. Почему?
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st June 2025 - 04:01
Рейтинг@Mail.ru


Страница сгенерированна за 0.01512 секунд с 7
ELECTRONIX ©2004-2016