试图理解这个#define

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了试图理解这个#define相关的知识,希望对你有一定的参考价值。

我正在尝试将stm32fxxx的16位录音机应用程序调整为24位,我偶然发现了令我困惑的#define

我已经将16位DMA更改为32位DMA以及一些缓冲区uint16_tuint32_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)应该做什么以及它是如何工作的!它几乎写成好像它的功能?其中x是IO值?

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

我为成为C的初学者而道歉但是我从未见过这样的事情而且只能假设其掩盖了缓冲区的大小。但为什么?

pBuffer是指向传递给函数的uint16_t*指针的指针,并根据需要投射到(uint8_t*)pBuffer以获取HAL_SAI_Transmit_DMA。我从来没有见过这样的指针,但是它有效。

答案

我想知道这个定义应该做什么以及它是如何工作的!它几乎写成好像它的功能?其中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 *指针的指针,并根据需要转换为(uint8_t *)pBuffer,用于HAL_SAI_Transmit_DMA。我从来没有见过这样的指针,但是它有效。

允许从一个对象指针类型转换为另一个,有时甚至是明智的。特别是,转换为字符指针(如uint8_t *)是一种定义明确的方法,用于访问对象表示的原始字节。

另一答案

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

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

以上是关于试图理解这个#define的主要内容,如果未能解决你的问题,请参考以下文章

试图理解这个链表插入代码

试图理解这个简单的 TensorFlow 代码

试图理解这个汇编 x86 代码

试图替换片段,但它一直显示相同的片段

为啥这个带有 shebang #!/bin/sh 和 exec python 的片段在 4 个单引号内起作用?

金蝶handler中 collection 代码片段理解