为什么我把DDRB加到json时IntelliSense说找不到DDRB定义,还让我看定义? Visual Studio代码

Why does IntelliSense say it cannot find DDRB definition when I added it to json and it can even let me peek the definition? Visual Studio Code

我有 blinky.c 用于 AVR 微控制器的简单代码。它编译并且 运行 没问题。但是我 vscode 中的 Intellisense 有点疯狂

#define F_CPU 16000000UL
#define LED_PIN 0

#include <avr/io.h>
#include <util/delay.h>

void main()
{
    DDRB |= (1 << LED_PIN);
    while(1)
    {
        PORTB ^= (1 << LED_PIN);
        _delay_ms(500);
    }
}

首先,我编辑了 json 以添加所需的路径:

{
    "configurations": [
        {
            "name": "Linux",
            "includePath": [
                "${workspaceFolder}/**",
                "/usr/avr/include",
                "/usr/avr/include/avr"
            ],
            "defines": [],
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "c11",
            "cppStandard": "c++14",
            "intelliSenseMode": "gcc-x86",
            "compilerArgs": [
                "-Wall "
            ]
        }
    ],
    "version": 4
}

它看到函数等,除了 DDRBPORTB:

但是当我去"Go to definition"时,它甚至让我看到了。那么它怎么会给我这个 IntelliSense 错误呢?

明确地说,我现在在 Linux (Manjaro)。我已经为 avrpamac 安装了所有需要的库,它们可以工作。

好的,我找到了解决办法。它是由 avr/io.h 文件的内部结构引起的。它包含一个特定文件,其定义基于源代码中给定微控制器的 #define。因此,当我不指定控制器时,它不会 #include 它在 io.h 因此它对 IntelliSense 不可见,但编译可以看到它,因为我指定了它。因此,为了使 io.h 包含我们需要的定义。我们必须告诉它我们将使用哪个控制器。像那样:

#define __AVR_ATmega328P__

所以现在我的代码如下所示:

#define F_CPU 16000000UL
#define LED_PIN 0
#define __AVR_ATmega328P__


#include <avr/io.h>
#include <util/delay.h>

void main()
{
    DDRB |= (1 << LED_PIN);
    while(1)
    {
        PORTB ^= (1 << LED_PIN);
        _delay_ms(500);
    }
}

你查io.h文件就可以清楚地看到:

#if defined (__AVR_AT94K__)
#  include <avr/ioat94k.h>
#elif defined (__AVR_AT43USB320__)
#  include <avr/io43u32x.h>
#elif defined (__AVR_AT43USB355__)
#  include <avr/io43u35x.h>
#elif defined (__AVR_AT76C711__)
#  include <avr/io76c711.h>
#elif defined (__AVR_AT86RF401__)
#  include <avr/io86r401.h>
#elif defined (__AVR_AT90PWM1__)
#  include <avr/io90pwm1.h>
...

它基本上是 500 行检查我们正在使用的控制器。如果你转到这个文件并使用 ctrl+f 或类似的东西,你可以很容易地找到你的控制器是如何定义的并包含它。这解决了问题,因为现在定义了 DDRBPORTB,这要归功于已解决的预处理器语句。

似乎因为你的编译成功了,所以你的编译器在一些编译器选项中定义了__AVR_ATmega328P__。也许在 -mmcu=<mcu>.

当您在源代码中定义它时,它可能会与那些编译器选项混淆。

“更好”的方法是正确设置 IntelliSense 配置文件,这样它就不会影响编译。

c_cpp_properties.json:

{
"configurations": [
    {
        ...
        "defines": ["__AVR_ATmega328P__"],
        ...
    }
],
"version": 4
}