Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STM32F4, Serial Audio Interface
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Atlantis-
Здравствуйте!
В stm32f429 есть блок SAI и в нем, судя по описанию, есть 32-битный регистр данных. То есть в режиме I2S можно оперировать 32-битными значениями. Однако в библиотеке HAL в функции передачи данных нужно передавать 16-битные значения. Например
CODE

HAL_StatusTypeDef HAL_SAI_Transmit_IT(SAI_HandleTypeDef *hsai, uint16_t *pData, uint16_t Size)
{
if(hsai->State == HAL_SAI_STATE_READY)
{
if((pData == NULL) || (Size == 0))
{
return HAL_ERROR;
}

hsai->pTxBuffPtr = pData;
hsai->TxXferSize = Size;
hsai->TxXferCount = Size;

/* Process Locked */
__HAL_LOCK(hsai);

hsai->State = HAL_SAI_STATE_BUSY_TX;

/* Transmit data */
hsai->Instance->DR = (*hsai->pTxBuffPtr++);
hsai->TxXferCount--;

/* Process Unlocked */
__HAL_UNLOCK(hsai);

/* Enable FRQ and OVRUDR interrupts */
__HAL_SAI_ENABLE_IT(hsai, (SAI_IT_FREQ | SAI_IT_OVRUDR));

/* Check if the SAI is already enabled */
if((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != SAI_xCR1_SAIEN)
{
/* Enable SAI peripheral */
__HAL_SAI_ENABLE(hsai);
}


return HAL_OK;
}
else if(hsai->State == HAL_SAI_STATE_BUSY_TX)
{
/* Process Locked */
__HAL_LOCK(hsai);

/* Transmit data */
hsai->Instance->DR = (*hsai->pTxBuffPtr++);

hsai->TxXferCount--;

if(hsai->TxXferCount == 0)
{
/* Disable FREQ and OVRUDR interrupts */
__HAL_SAI_DISABLE_IT(hsai, (SAI_IT_FREQ | SAI_IT_OVRUDR));

hsai->State = HAL_SAI_STATE_READY;

HAL_SAI_TxCpltCallback(hsai);
}

/* Process Unlocked */
__HAL_UNLOCK(hsai);

return HAL_OK;
}

else
{
return HAL_BUSY;
}
}


Непонятно, почему так сделано? И можно ли как то обмануть библиотеку и работать с int-ами?
Genadi Zawidowski
Предлагаю написать свой вариант функции. Да, проверьте ещё значения битов при программировании прескалера - должно быть так:

Код
#define  SAI_xCR1_MCKDIV                  ((uint32_t)0x00F00000)        /*!<MCKDIV[3:0] (Master ClocK Divider)  */
#define  SAI_xCR1_MCKDIV_0                ((uint32_t)0x00100000)        /*!<Bit 0  */
#define  SAI_xCR1_MCKDIV_1                ((uint32_t)0x00200000)        /*!<Bit 1  */
#define  SAI_xCR1_MCKDIV_2                ((uint32_t)0x00400000)        /*!<Bit 2  */
#define  SAI_xCR1_MCKDIV_3                ((uint32_t)0x00800000)        /*!<Bit 3  */


В старых хедерах была ошибка.
Atlantis-
Еще мне с его настройками не совсем понятно, там их больше чем обычно. Мне нужно настроить передачу 24 бит на канал в 32-х битном фрейме. При настройке Cube не дает делать 32-битный фрейм в отличие от настроек I2S. В итоге у меня получилось так: Frame Length 64 bits, Data size 24 bits, Slot size 32 bits; Frame Synchro Definition: Channel Identification, Number of Slots 2, Frame Synchro Active Level Length 32. Все правильно?
Немного смущает, при 24-битном слоте и 32-битном регистре данных, что он будет отсылать в оставшихся 8 битах. То есть будет ли заменять их на нули.
Genadi Zawidowski
Ну там ещё зависит от того, что у вас - LJ или I2S режим стоит. Он должен кодековскому соответствовать.
ЧТо передается в кодек в оставшихся битах, имеет ли значение?

Не кубом, а руками я настраивал на 32 бита.
В режиме LJ работал с 24-бит кодеком и в I2S - с FPGA, в режиме 32 бит. В обоих случаях SAI настраивался на 32 бита.
Принятое из кодека 24-х битное значение сдвигается вправо на 8 бит как знаковое - и получаем число для дальнейшей обработки.
Atlantis-
Цитата
ЧТо передается в кодек в оставшихся битах, имеет ли значение?

Хороший вопрос...может быть ЦАП и проигнорирует лишние биты.
Цитата
Не кубом, а руками я настраивал на 32 бита.

Куб пишет ошибку, говорит если использовать FS как Channel Identification, то должно быть больше одного слота. В их примере тоже настроено 64 битный фрейм, я попробовал так - частоту правильную выдает.

Следующий вопрос, насколько я понял, данные выводятся из встроенного FIFO на 8 слов (похоже имеются ввиду 32-битные слова). Прерывание возникает в зависимости от степени заполненности FIFO. Допустим мне нужно писать данные каждые 2 фрейма (отправляю данные для двух каналов и пишу новые два канала и т.д.). Тогда я настраиваю прерывание на условие пустого FIFO, пишу в FIFO 2 слова, отправляю -> генерируется прерывание в котором я снова пишу 2 слова и так далее. Все верно?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.