пытаясь разобраться в этом #define - PullRequest
0 голосов
/ 16 апреля 2019

Я пытаюсь адаптировать 16-битное приложение для записи звука для stm32fxxx к 24-битному, и я наткнулся на #define, что меня смущает.

Я изменил 16-битный DMA на 32-битный DMA вместе с некоторыми буферами uint16_t до uint32_t и т. Д., Не знаю, почему uint32_t и не подписано int, но об этом я расскажу позже.Невозможно передать 24 бита через DMA, поэтому я отправлю 32 бита и сбрасываю один байт позже.

3-й вход HAL_SAI_Transmit_DMA() фактически ожидает значение размера в uint16_t.

#define AUDIO_OUT_BUFFER_SIZE       16384 
#define AUDIODATA_SIZE 2
#define DMA_MAX_SZE    0xFFFF
#define DMA_MAX(x)  (((x) <= DMA_MAX_SZE)? (x):DMA_MAX_SZE)

uint8_t BSP_AUDIO_OUT_Play(uint16_t* pBuffer, uint16_t Size)
{
    // send audio samples over DMA from buffer to audio port 
    HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pBuffer, 
        DMA_MAX(AUDIO_OUT_BUFFER_SIZE / AUDIODATA_SIZE));

    return AUDIO_OK;
}

Полагаю, мне нужно перейти на

AUDIODATA_SIZE 4
#define DMA_MAX_SZE    0xFFFFFFFF // 32bit

Но я бы хотел знать, что должен делать #define DMA_MAX(x) (((x) <= DMA_MAX_SZE)? (x):DMA_MAX_SZE) и как это вообще работает!почти написано, как будто это функция?где x - это значение IO?

AUDIODATA_SIZE - это число байтов в каждом образце:

Я прошу прощения за то, что я новичок в C, но я никогда не видел ничего подобного и могуПредполагается только его маскировка размером буфера.Но почему?

pBuffer - указатель на указатель uint16_t*, переданный в функцию, и преобразуется в (uint8_t*)pBuffer для HAL_SAI_Transmit_DMA, как это требуется.Я никогда не видел, чтобы указатели так же использовались, но это работает.

Ответы [ 2 ]

2 голосов
/ 16 апреля 2019

Я хотел бы знать, что это определение должно делать и как оно вообще работает! почти написано, как будто это функция? где х значение IO?

Я так понимаю, вы спрашиваете о макросе DMA_MAX. Да, он написан почти так же, как если бы это была функция, и концептуально он работает так же, как и один. Вот почему такие макросы называются «функциональными макросами». Другой вид - это «объектоподобные макросы».

Функциональный макрос по-прежнему является макросом. Его появления заменяются заданным текстом замены, и все появления в пределах идентификаторов любого из его параметров заменяются (полностью макрорасширенными) макро-аргументами, с несколькими исключениями, которые я здесь проигнорирую. Таким образом, это ...

DMA_MAX(BufferSize / AUDIODATA_SIZE)

... расширяется до этого:

(((BufferSize / AUDIODATA_SIZE) <= DMA_MAX_SZE)? (BufferSize / AUDIODATA_SIZE):DMA_MAX_SZE)

Использует троичный оператор для вычисления меньших из BufferSize / AUDIODATA_SIZE и DMA_MAX_SZE. Почему и как (и действительно ли) это правильно, не видно из представленного кода.

pBuffer - указатель на указатель uint16_t *, переданный в функция и приводится к (uint8_t *) pBuffer для HAL_SAI_Transmit_DMA как того требует Я никогда не видел, чтобы указатели были так это работает.

Разрешается конвертировать из одного типа указателя объекта в другой, и иногда это даже целесообразно сделать. В частности, приведение к символьному указателю, такому как uint8_t *, является четко определенным средством, обеспечивающим доступ к необработанным байтам представления объекта.

1 голос
/ 16 апреля 2019

0xFFFF представляется не битовой маской, а максимальным размером 65535.

Макрос DMA_MAX(x) просто проверяет, меньше ли переданный параметр, чем максимум, и если нет, ограничивает значение максимально допустимым. Может, какая-то проверка переполнения?

Логически эквивалентно этому псевдокоду:

if( (BufferSize / AUDIODATA_SIZE) <= DMA_MAX_SZE)
{
  HAL_SAI_Transmit_DMA(... , BufferSize / AUDIODATA_SIZE);
}
else
{
  HAL_SAI_Transmit_DMA(... , DMA_MAX_SZE);
}

В качестве дополнительного примечания было бы лучше не писать такие непристойные макросы, как это, а вместо этого использовать временную переменную:

uint16_t size; 
if(BufferSize / AUDIODATA_SIZE <= DMA_MAX_SZE)
{
  size = BufferSize / AUDIODATA_SIZE;
}
else
{
  size = DMA_MAX_SZE;
}

HAL_SAI_Transmit_DMA(... , size);

Это скомпилирует тот же машинный код, что и у вас, но гораздо более читабелен.

...