如何以编程方式识别哪个微控制器连接到我的计算机
How to programatically identify which microcontroller is connected to my computer
最近买了一个NodeMCU ESP8266开始玩。尽管我为 Arduino 微控制器编写的几乎所有脚本都可以在 ESP8266 上正常工作,但还是存在一些差异。例如,从 EEPROM 读取或使用我的 Esp8266 中的内部 VREF。
我知道可以使用以下代码识别连接了哪个 Arduino 板:
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
//Code in here will only be compiled if an Arduino Mega is used.
#elseif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
//Code in here will only be compiled if an Arduino Uno (or older) is used.
#elseif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__)
//Code in here will only be compiled if an Arduino Leonardo is used.
#endif
但是,这适用于 arduino 微控制器。我如何才能为 esp8266 微控制器做到这一点?
就像您在问题中提到的那样,#if defined(__xxxxx__) 语句实际上并未 运行 在微控制器上。它们是预处理器指令。 if 语句决定将哪些代码传递给实际的编译器,以及忽略哪些代码。
您可以编写代码以从 eeprom 中读取,但是对于微控制器之间不同的代码部分(我建议为每个微控制器提供一个单独的函数),您可以在编译时选择。
例如
#ifdef AVR_MICROCONTROLLER
read_from_eeprom(...)
{
code for the avr chip
}
#else // I'm assuming there's no other options besides avr and esp
read_from_eeprom(...)
{
code for esp chip
}
#endif
然后在编译时,使用-D标志来指定你正在使用AVR
或省略 esp.
的标签
gcc ... -D AVR_MICROCONTROLLER ...
我觉得你问这个问题的原因可能是因为对 __AVR_ATmega1280__ 等标签的来源感到困惑。
基本上,它们不是编译器用来决定为哪个芯片编译的关键字。它们是由编写源文件的人创建的,它们用于可移植性,因此同一个文件可以用于许多不同的 platforms/processors。
在我的回答中,我使用命令行标记来定义 AVR_MICROCONTROLLER 标记。
其他项目(例如 Arduino 上的 Marlin 固件 运行ning)也有充满定义语句的配置文件,可用于准确配置代码的编译方式。长话短说,是的,其他微控制器也可以这样做,您可以通过编写自己的预处理器 if 语句,然后根据您想要 [=27] 的芯片选择在编译时设置哪个 parameters/variables =]代码上。
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
//Code in here will only be compiled if an Arduino Mega is used.
是否可以对其他类型的微控制器做同样的事情?例如ESP8266中的那个?我应该寻找什么?
提到的宏是内置宏provided by avr-gcc。它们用于确定编译哪个设备,例如 avr-libc。实际上,这些宏现在不再内置在编译器/预处理器中,而是由设备规范文件 device-specs/specs-<device>
提供,该文件根据 -mmcu=<device>
将相应的 -D__AVR_<DEVICE>__
注入预处理器的命令行。
您可以用于 AVR 的是
#ifdef __AVR__
为 AVR 编译时,仍然是 avr-gcc / avr-g++ 的内置宏。
ESP8266是完全不同的架构;您将使用 xtensa-g++ 为该 µC 编译代码,并且 GCC 的化身内置定义了 __xtensa__
和 __XTENSA__
(绝对是 not __AVR__
).
然而,尽管 AVR 工具中的设备支持非常复杂,并且 avr-gcc 可以识别数百个不同的 -mmcu=<device>
选项,但 xtensa 并非如此。如果您想区分不同的 xtensa 衍生物,您将必须定义自己的宏。
由于 avr 和 xtensa 是非常不同的体系结构,您还可以将体系结构特定的东西放在自己的模块中,例如 eeprom-avr.cpp
为 avr 提供 read_from_eeprom
或其他任何内容,并且仅包含在构建中当使用 avr-g++ 为 avr 构建时,以及类似的 xtensa-only 模块 eeprom-xtensa.cpp
仅在使用 xtensa-g++ 构建时才包含。
How to programmarically identify if the code is being compiled for AVR or ESP8266?
#if defined (__AVR__)
/* Code for AVR. */
#elif defined (__XTENSA__)
/* Code for ESP8266. */
#else
#error Compiling for unsupported target.
#endif
最近买了一个NodeMCU ESP8266开始玩。尽管我为 Arduino 微控制器编写的几乎所有脚本都可以在 ESP8266 上正常工作,但还是存在一些差异。例如,从 EEPROM 读取或使用我的 Esp8266 中的内部 VREF。
我知道可以使用以下代码识别连接了哪个 Arduino 板:
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
//Code in here will only be compiled if an Arduino Mega is used.
#elseif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
//Code in here will only be compiled if an Arduino Uno (or older) is used.
#elseif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__)
//Code in here will only be compiled if an Arduino Leonardo is used.
#endif
但是,这适用于 arduino 微控制器。我如何才能为 esp8266 微控制器做到这一点?
就像您在问题中提到的那样,#if defined(__xxxxx__) 语句实际上并未 运行 在微控制器上。它们是预处理器指令。 if 语句决定将哪些代码传递给实际的编译器,以及忽略哪些代码。
您可以编写代码以从 eeprom 中读取,但是对于微控制器之间不同的代码部分(我建议为每个微控制器提供一个单独的函数),您可以在编译时选择。
例如
#ifdef AVR_MICROCONTROLLER
read_from_eeprom(...)
{
code for the avr chip
}
#else // I'm assuming there's no other options besides avr and esp
read_from_eeprom(...)
{
code for esp chip
}
#endif
然后在编译时,使用-D标志来指定你正在使用AVR 或省略 esp.
的标签gcc ... -D AVR_MICROCONTROLLER ...
我觉得你问这个问题的原因可能是因为对 __AVR_ATmega1280__ 等标签的来源感到困惑。 基本上,它们不是编译器用来决定为哪个芯片编译的关键字。它们是由编写源文件的人创建的,它们用于可移植性,因此同一个文件可以用于许多不同的 platforms/processors。 在我的回答中,我使用命令行标记来定义 AVR_MICROCONTROLLER 标记。 其他项目(例如 Arduino 上的 Marlin 固件 运行ning)也有充满定义语句的配置文件,可用于准确配置代码的编译方式。长话短说,是的,其他微控制器也可以这样做,您可以通过编写自己的预处理器 if 语句,然后根据您想要 [=27] 的芯片选择在编译时设置哪个 parameters/variables =]代码上。
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
//Code in here will only be compiled if an Arduino Mega is used.
是否可以对其他类型的微控制器做同样的事情?例如ESP8266中的那个?我应该寻找什么?
提到的宏是内置宏provided by avr-gcc。它们用于确定编译哪个设备,例如 avr-libc。实际上,这些宏现在不再内置在编译器/预处理器中,而是由设备规范文件 device-specs/specs-<device>
提供,该文件根据 -mmcu=<device>
将相应的 -D__AVR_<DEVICE>__
注入预处理器的命令行。
您可以用于 AVR 的是
#ifdef __AVR__
为 AVR 编译时,仍然是 avr-gcc / avr-g++ 的内置宏。
ESP8266是完全不同的架构;您将使用 xtensa-g++ 为该 µC 编译代码,并且 GCC 的化身内置定义了 __xtensa__
和 __XTENSA__
(绝对是 not __AVR__
).
然而,尽管 AVR 工具中的设备支持非常复杂,并且 avr-gcc 可以识别数百个不同的 -mmcu=<device>
选项,但 xtensa 并非如此。如果您想区分不同的 xtensa 衍生物,您将必须定义自己的宏。
由于 avr 和 xtensa 是非常不同的体系结构,您还可以将体系结构特定的东西放在自己的模块中,例如 eeprom-avr.cpp
为 avr 提供 read_from_eeprom
或其他任何内容,并且仅包含在构建中当使用 avr-g++ 为 avr 构建时,以及类似的 xtensa-only 模块 eeprom-xtensa.cpp
仅在使用 xtensa-g++ 构建时才包含。
How to programmarically identify if the code is being compiled for AVR or ESP8266?
#if defined (__AVR__)
/* Code for AVR. */
#elif defined (__XTENSA__)
/* Code for ESP8266. */
#else
#error Compiling for unsupported target.
#endif