-1

我正在尝试将 stm32fxxx 的 16 位录音机应用程序调整为 24 位,但我偶然发现了一个#define让我感到困惑的问题。

uint16_t我已经将 16 位 DMA 更改为32 位 DMA 以及一些缓冲区uint32_t等等。不知道为什么uint32_t并且没有签名 int 但我稍后会看。没有办法通过 DMA 传递 24 位,所以我将发送 32 位并稍后丢弃一个字节。

的第三个输入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)应该做什么以及它是如何工作的!它几乎写成好像它是一个函数?xIO值在哪里?

AUDIODATA_SIZE是每个样本中的字节数:

作为 C 语言的初学者,我深表歉意,但我从未见过这样的事情,只能假设它掩盖了缓冲区的大小。但为什么?

pBufferuint16_t*指向传递给函数的指针的指针,并根据需要强制转换(uint8_t*)pBufferHAL_SAI_Transmit_DMA。我也从未见过这样的指针,但它确实有效。

4

2 回答 2

2

我想知道这个定义应该做什么以及它是如何工作的!它几乎写成好像它是一个函数?其中 x 是 IO 值?

我认为您是在询问DMA_MAX宏。是的,它几乎就像一个函数一样被编写,而且它在概念上也有点像一个函数。这就是为什么像这样的宏被称为“类函数宏”。另一种是“类对象宏”。

类函数宏仍然是宏。它的外观被给定的替换文本替换,并且其任何参数的标识符内的所有外观都被(完全宏扩展的)宏参数替换,有几个例外,我将在这里忽略。因此,这...

DMA_MAX(BufferSize / AUDIODATA_SIZE)

...扩展为:

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

这使用三元运算符来计算 和 的较小BufferSize / AUDIODATA_SIZEDMA_MAX_SZE。从提供的代码中看不出为什么以及如何(以及是否)这样做是正确的。

pBuffer 是指向传递给函数的 uint16_t* 指针的指针,并根据需要转换为 HAL_SAI_Transmit_DMA 的 (uint8_t*)pBuffer。我也从未见过这样的指针,但它确实有效。

允许从一种对象指针类型转换为另一种,有时这样做甚至是明智的。特别是,转换为诸如字符指针之类的字符指针uint8_t *是一种提供对对象表示的原始字节的访问的明确定义的方法。

于 2019-04-16T14:21:32.283 回答
1

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);
}

作为旁注,最好不要像这样编写 icky 宏,而是使用临时变量:

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

HAL_SAI_Transmit_DMA(... , size);

这将编译为与您当前拥有的相同的机器代码,但更具可读性。

于 2019-04-16T14:38:26.247 回答