我正在为 Raspberry Pico 微控制器开发一个 C 项目。我已经在 Raspberry Pi 5(“完整的”Debian Linux 系统)上安装了“Pico SDK”,并且运行良好。 SDK 中包含的示例程序之一是一个名为
bus_scan
(此处源代码) 的小型应用程序 - 它扫描 I2C 总线以查看哪些地址响应读取请求,并打印结果摘要。
我遇到的问题/问题是WRT代码的以下部分 - 包含在
main()
中:
#if !defined(i2c_default) || !defined(PICO_DEFAULT_I2C_SDA_PIN) || !defined(PICO_DEFAULT_I2C_SCL_PIN)
#warning i2c/bus_scan example requires a board with I2C pins
puts("Default I2C pins were not defined");
#else
// This example will use I2C0 on the default SDA and SCL pins (GP4, GP5 on a Pico)
i2c_init(i2c_default, 100 * 1000);
gpio_set_function(PICO_DEFAULT_I2C_SDA_PIN, GPIO_FUNC_I2C);
gpio_set_function(PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C);
gpio_pull_up(PICO_DEFAULT_I2C_SDA_PIN);
gpio_pull_up(PICO_DEFAULT_I2C_SCL_PIN);
// Make the I2C pins available to picotool
bi_decl(bi_2pins_with_func(PICO_DEFAULT_I2C_SDA_PIN, PICO_DEFAULT_I2C_SCL_PIN, GPIO_FUNC_I2C));
我的印象是预处理器指令可以出现在程序中的任何地方。但是,我不喜欢它位于
main()
中,因此我将其移至 #include
下方。当我重新编译时,产生了很多错误。
我不明白这种类型的代码...“预处理器指令”下的一些语句看起来像函数调用(可能是头文件中定义的函数??)。
这是我尝试过的:
main()
重新编译成功了,但这给我留下了一个问题:
将预处理器指令与函数调用混合有什么意义?鉴于这是一个示例程序(即学习),正在教授什么编码技术?这是一个严肃的问题 - 并不是试图让任何人成为坏榜样或任何东西 - 但我真的很想知道这是否是我应该尝试学习的技术。
#if !defined ...
和 #warning
等是预处理器指令。它们下面的东西不是,那是纯 C 代码,确实是函数调用,因此它属于函数内部,而不是在 main() 的顶部。
#if defined
/#ifndef
等模式有时被称为“编译器开关”(一种令人困惑的术语),意思是“如果有的话,使用此代码,否则使用其他代码” - 在编译时评估。你不能将这些东西移动到任意位置,也不能随心所欲地删除它们。
#include
、#define
、#if
等都是非常基本的东西,你真的应该先研究它们的作用。至于此代码的作用:它检查您是否使用了几个“板支持”默认项目,然后假设 I2C 引脚是否路由到连接器。如果板上有 I2C 支持,它会初始化 I2C 硬件外设并相应地设置引脚布线和拉电阻。
我可能会建议不要使用预制的库,而是自己手动破解 I2C 驱动程序。这将需要更长的时间,但通过这样做,您将真正了解事情是如何运作的。