在使用树莓派时,你会发现Python和Scratch是许多任务(包括GPIO编程)中最常用的编程语言。但你知道吗,你也可以使用C++进行GPIO编程,而且这样做还有不少好处。
借助WiringPi和PiGPIO等库,C++可用于编程控制树莓派的GPIO引脚。它提供了更好的性能和控制能力,非常适合对速度和精度要求较高的硬件项目。
在树莓派社区中,关于“Python与C++哪个更适合树莓派”的讨论十分热烈。Python因其简单易用和庞大的生态系统而备受青睐,而C++则在性能和精确的硬件控制方面表现出色。这一特性使C++成为某些项目的可靠选择。
目录
先决条件
了解C/C++的不同GPIO库
搭建开发环境
搭建电路
编写GPIO程序以使LED闪烁
常见问题解答(FAQ)
先决条件
以下是使用C++进行GPIO编程所需的一些条件:
树莓派开发板:你可以使用任何符合项目资源需求的树莓派型号。本教程中,我将使用配备2GB内存的树莓派4B。
操作系统要求:任何受树莓派支持的操作系统均可。但如果你是初学者,我建议先使用树莓派操作系统(Raspberry Pi OS)。等你熟练掌握了在树莓派上使用C++编程后,再切换其他系统也不迟。
C++编译器(g++):这是C++的命令行编译器,预装在树莓派操作系统中。
所需库(WiringPi、PiGPIO):这些C++库用于与树莓派的GPIO引脚进行交互。
一个LED灯:本教程至少需要一个LED灯。
了解C/C++的不同GPIO库
在深入探讨各种可用库之前,我们先来了解一下为什么在使用GPIO引脚时需要库。
主要原因在于简化操作。库让我们无需处理复杂的底层硬件控制,就能轻松与GPIO引脚进行交互,既节省时间又降低了难度。
例如,如果我想打开/关闭一个GPIO引脚,只需使用以下这行代码:
digitalWrite(pin,HIGH);// Turn on an LED
但如果没有库,我就得直接操作内存寄存器,这要复杂得多。
WiringPi
WiringPi是树莓派上与GPIO引脚交互最受欢迎的库之一。我曾用它完成过搭建循线机器人等复杂项目,从未遇到过任何问题。
不过,在使用WiringPi之前,你应该知道它的引脚编号系统可能会让人困惑。
WiringPi并不遵循标准的BCM(GPIO)编号或树莓派的物理引脚布局。当第一款树莓派发布时,它只有少数几个可用的GPIO引脚,WiringPi以自己的方式将这些引脚编号为0到7。随着新款树莓派型号引入了更多GPIO引脚,WiringPi为了保持向后兼容性,保留了原有的编号方式。
这意味着WiringPi的引脚编号并不总是与实际的GPIO编号或电路板上的物理引脚位置相对应。不过别担心!你可以参考下表,查看每个树莓派引脚在WiringPi中的映射关系。

pigpio是另一个用于控制树莓派GPIO引脚的C++库。在撰写本文时,我虽未广泛使用过它,但从有限的几次使用经验来看,我发现它比WiringPi更强大,但我强烈建议仅将其用于高级任务。
与WiringPi不同,pigpio作为后台服务(守护进程)运行,非常适合精确的GPIO控制。如果你正在进行一个需要平稳精确控制电机或伺服器的项目,那么pigpio值得考虑。
然而,这一关键特性也是它的最大缺点。由于pigpio依赖于其守护进程,在资源(CPU和内存)有限的老款树莓派型号上,它可能无法很好地工作,尤其是在运行繁重的GPIO操作时。此外,你不能将其与WiringPi等其他库同时使用,因为它们可能会产生冲突。
注意:在本教程中,我将使用WiringPi,因为我只编写一个点亮LED的小程序。WiringPi对初学者友好,是开始在树莓派上进行GPIO编程的最简单方法之一。
搭建开发环境
现在,你已经掌握了使用C++控制GPIO引脚所需的所有信息。接下来,让我们深入探讨设置过程。
安装必要的开发包
如果你使用的是树莓派操作系统完整版,它已经预装了许多开发包。但如果你使用的是树莓派操作系统精简版(Lite)或其他基于Debian的发行版,则需要手动安装C++编译器和其他依赖项。
你可以通过运行以下命令来完成安装:
sudoapt updatesudo apt install g++ build-essential
安装并设置WiringPi
你必须在树莓派上安装WiringPi才能将其用于GPIO项目。首先,通过运行以下命令更新系统:
sudoapt update
以前,你可以轻松地使用apt命令从树莓派软件源中安装WiringPi。然而,由于WiringPi已停止支持,你需要从WiringPi的GitHub仓库克隆它:
gitclonehttps://github.com/WiringPi/WiringPi.gitcdWiringPi./build debiancddebian-templatesudo apt install ./wiringpi_3.14_arm64.deb
文件名可能有所不同,请根据设备生成的文件调整最后一条命令。
完成后,你可以通过运行以下命令验证安装是否成功:
gpio-v
现在,我们已经准备好了软件需求,接下来进入设置电路的步骤。
搭建电路
下一步是搭建电路。这一步需要你亲自动手,将LED灯连接到树莓派的GPIO引脚上。
了解树莓派GPIO布局
在继续之前,你需要明白不能将LED灯连接到树莓派的任意引脚上。每个引脚都有特定的功能,且只能用于该功能。有些引脚用于输入/输出,有些用于供电(3.3V或5V),还有些用于接地。
如果你之前没有做过涉及GPIO引脚的项目,我建议你快速浏览一下我们关于树莓派GPIO引脚入门的全面文章。它将帮助你更好地理解本教程的内容。
将LED灯连接到树莓派
现在,我将直接连接LED灯到树莓派,不使用电阻。我知道这不是理想的方法,但我之前这样做过,没有出现过任何问题。而且,我知道我的LED灯额定电压为3V,处于安全范围,不会损坏树莓派。
我将使用一个扩展板,因为它更整洁、更方便,但你也可以直接将LED灯连接到树莓派的引脚上,如果你觉得这样更方便的话。我将把LED灯连接到GPIO 26和接地(GND)引脚上。
编写GPIO程序以使LED闪烁
设置好电路后,我们就可以编写代码了。你可以使用许多编辑器在树莓派上编写程序。你可以选择基于命令行的编辑器(如Nano)或基于图形界面的编辑器(如Geany)。在本教程中,我将使用nano编辑器。
首先,打开终端,使用以下命令导航到“文档”目录并创建一个程序文件:
cdDocumentsmkdirBlinkLEDProgramtouchblink_led.cpp
创建文件后,我们可以使用nano编辑器打开它:
nanoblink_led.cpp
编写代码
这将打开一个空文本编辑器,你可以在其中开始编写代码。我将把这段代码分成几个部分,以便你更好地理解。
#include#include#include#include
#include :这行代码包含了WiringPi库,使你能够控制树莓派的GPIO引脚。这是与LED等硬件交互所必需的。
#include :这用于输入输出操作。在本例中,我们将使用它来向终端打印文本。
#include :这提供了时间工具。在我们的程序中,我们将使用毫秒等工具来控制延迟。
#include :我们将使用它来暂停程序执行指定的时间。它与Python中的sleep()函数类似。
constexprintLED_PIN =25;
在这里,我们定义了一个常量LED引脚,它将与树莓派上的引脚进行交互。你会注意到,我将其设置为25,但在搭建电路时,我明确表示将把LED灯连接到GPIO 26。
这是因为WiringPi使用了不同的GPIO编号方式。如果你参考上面的表格,你会发现树莓派上的GPIO 26在WiringPi库中被映射为引脚25。
usingnamespacestd;usingnamespacestd::chrono;usingnamespacestd::this_thread;
using namespace std;:这意味着我们可以使用标准的C++特性(如cout、cerr、endl等),而无需总是使用std::前缀。
std::
using namespace std::chrono;和using namespace std::this_thread;:这些使我们能够直接使用时间相关函数(如milliseconds和sleep_for),而无需每次都写出std::milliseconds或std::sleep_for。
intmain(intargc,char* argv[])
这是程序的入口点,程序从这里开始执行。
if(wiringPiSetup() == -1){ cerr<"Failed to initialize wiringPi"?<< endl;? ? return?1;}
wiringPiSetup():这个函数初始化WiringPi库。如果它返回-1,说明出现了问题,库无法初始化。
cerr << "Failed to initialize wiringPi" << endl;:如果WiringPi设置失败,这将在终端打印一条错误信息。
return 1;:如果设置失败,这将结束程序。1表示发生了错误。
pinMode(LED_PIN, OUTPUT); //Setthe LED pinasoutput
pinMode(LED_PIN, OUTPUT);:这告诉树莓派,GPIO引脚25(连接LED灯的引脚)将用于输出。这很重要,因为引脚可以设置为输入(读取数据)或输出(发送数据)。
cout <"Blinking LED connected to GPIO pin "?<
cout:这将在终端打印一条信息,告诉你程序正在运行,并且正在GPIO引脚25上使LED灯闪烁。这就像是对用户的一个快速状态更新。
while(true){ digitalWrite(LED_PIN,HIGH); sleep_for(milliseconds(500)); digitalWrite(LED_PIN,LOW); //Correctedfrom'Low'to'LOW' sleep_for(milliseconds(500));}
while (true):这开始一个无限循环。循环内的代码将一直运行,直到你手动停止程序。这用于使LED灯持续闪烁。
digitalWrite(LED_PIN, HIGH);:这通过向GPIO引脚25发送高电平信号来打开LED灯。HIGH是一个常量,表示“开”。
sleep_for(milliseconds(500));:这暂停程序执行500毫秒(0.5秒),因此LED灯将保持亮起半秒钟。
digitalWrite(LED_PIN, LOW);:这通过向GPIO引脚25发送低电平信号来关闭LED灯。LOW表示“关”。
sleep_for(milliseconds(500));:这再次暂停程序执行500毫秒,因此LED灯将保持熄灭半秒钟。
这个循环使LED灯每半秒闪烁一次。
return0;
这行代码标志着程序的结束,并返回0表示一切运行正常。然而,由于我们有一个无限的while (true)循环,除非你手动通过键盘按下Ctrl + C停止程序,否则这行代码永远不会被执行。
最终的代码看起来与下图类似。
完成后,使用Ctrl + S保存代码并退出(Ctrl + X)。
编译并运行代码
要编译这个程序,请执行以下命令:
g++ -std=c++17-o blink_led blink_led.cpp -lwiringPi
g++:这是GNU C++编译器。
-std=c++17:指定代码应使用C++17标准进行编译。
-o blink_led:这告诉编译器创建一个名为blink_led的输出文件(可执行文件)。
blink_led.cpp:这是我们编写代码的源文件。
-lwiringPi:链接WiringPi库,这是控制树莓派GPIO引脚所必需的。
成功执行后,你可以使用以下命令运行程序:
./blink_led
下面的视频展示了我这边的输出结果。一切都很顺利,我的LED灯按预期闪烁。
排查错误
代码中的大多数错误将在编译过程中被捕获并显示在屏幕上。然而,还有其他一些问题可能会导致程序无法运行或LED灯无法闪烁。
如果你尝试运行程序时遇到类似以下错误:
wiringPiSetup:commandnot found
这意味着WiringPi没有正确安装。你可以按照上面“安装并设置WiringPi”部分中的说明重新安装它。
另一种排查问题的先进方法是使用gpio readall命令:
gpioreadall
它显示一个表格,展示所有GPIO引脚的当前引脚状态、模式和编号。你可以使用这些信息来解决LED灯不闪烁的多个问题。
检查引脚编号:由于不同的库(BCM、WiringPi和物理编号)使用不同的编号方式,gpio readall帮助你确认程序应该使用哪种编号方式。
验证引脚模式:你可以检查引脚是设置为输入、输出还是ALT模式。
检查引脚状态:该命令显示引脚当前是高电平(1)还是低电平(0)。因此,如果你的LED灯应该亮起但引脚仍然是低电平(0),那么你可能存在接线或软件问题。
检测冲突:你还可以使用这些信息来检查引脚是否被另一个进程或库使用。
就这样!你现在应该已经了解了如何在树莓派上使用C++控制GPIO引脚。在本教程中,我只使用了WiringPi库使LED灯闪烁的一个小例子。你可以通过使用更多组件和参与更复杂的项目来进一步探索。
FAQ
能否不使用任何库来编程GPIO?
是的,但难度要大得多。你将需要直接与内存寄存器或系统文件(如/sys/class/gpio/)进行交互。像WiringPi和PiGPIO这样的库使这一过程变得简单得多。
在C++中控制GPIO是否需要root权限?
这取决于你使用的库。WiringPi需要root权限(sudo)来访问GPIO引脚,因为它直接与硬件交互。PiGPIO作为后台服务(守护进程)运行,因此并不总是需要sudo,但这取决于守护进程的设置方式。
原文地址:
https://raspberrytips.com/control-gpio-with-c-on-raspberry-pi/
-
操作系统
+关注
关注
37文章
7185浏览量
126079 -
GPIO
+关注
关注
16文章
1287浏览量
54384 -
树莓派
+关注
关注
122文章
2050浏览量
107791
发布评论请先 登录
如何使用Telegram控制树莓派上的GPIO引脚

如何在树莓派上安装Ubuntu MATE ?

树莓派MCC118
如何在树莓派上装一个codesys的runtime
如何在树莓派上运行Fedora
树莓派使用C/C++基于Bcm2835操作GPIO学习记录

C++ 与 Python:树莓派上哪种语言更优?

评论