教你用树莓派的GPIO接口控制发光二极管
通过Raspberry Pi的GPIO口来控制发光二极管已经不是什么新鲜事了,网上有大量的教程和资源可查。为了测试一下控制GPIO输出的功能,我也实践了一次。首先声明,我对硬件并不了解,所以下文可能有错误,如果你发现了,请留言告诉我,非常感谢。
1、实验目的
写一个简单的程序,控制Raspberry Pi的GPIO口输出高、低电平,从而让接在GPIO口上的发光二极管闪烁。
2、材料准备
首先,你当然要购买一些发光二极管,电阻,导线,面包板之类的必需
电子元器件。看一下我接好线的实物图:
3、关于GPIO
GPIO是通用输入输出(General Purpose Input Output)的简称,可以通过软件控制芯片上的GPIO口来定义它是输出还是输出接口。
GPIO接口没有定义特殊的功能,并且通常是不使用的。之所以有GPIO,是因为系统有时需要一些额外的控制线路以便于提供一些额外的功能。
Raspberry Pi上的GPIO接口在哪里?它是怎么定义的?我在网上找到这样两幅图:
以及另外一幅稍有不同的图:
特别要注意的是:尽管你在网上找到的大多数是类似上面两幅图的接口分布图,但是树莓派的GPIO口有两种不同的命名方式,最后这幅图就提供了一个对比。
然后我们再来看看Pi上的接口实物图(红框中):
但是,这有一个问题:我怎么知道上面两幅图对应的方向是一致的?也就是说,我如何确定哪个针脚是1,哪个针脚是2,等等?我请教了一个做嵌入式开发的朋友,他告诉我,将Pi的
电路板翻到反面,在26个针脚中,焊点为方形的那个针脚就是“1”,在它旁边同一排(两个针脚一排)的那一个就是“2”,依此类推。
在此,我特意拍摄了一张反面焊点的图来说明:
根据这个判断,我得到了Pi的GPIO接口顺序图:
同时,为了保险,还需要用万用表测量一下我们的判断对不对:在Raspberry Pi的工作状态下,将万用表的“+”接到“1”口上,万用表的“-”接到“6”口上,在看看万用表的显示是不是大约为正3.3V,如果不是,那么说明我们弄错了针脚顺序,需要回头再检查!
下图是我在树莓派的工作状态下,用万用表测量的实物图:
顺便说一句,Youtube上有一个关于GPIO的视频教程,看完它你会觉得非常有帮助。
在确认了接口序号无误后,我们就可以开始接线了。在这里,我随意选了一个GPIO口——GPIO 23(即端口16)来接LED。电路图如下:
就算是这么简单的一个电路,像我一样忘了曾经学过的模拟电路知识的人也会问一句:树莓派的输出电流可以驱动得了发光二极管吗?首先,我在这个链接查到树莓派的3.3V输出口可以提供的最大电流是50mA,并且从这个链接我知道不应让树莓派的单针脚的输出电流>10mA,然后我又查到发光二极管的驱动电流一般是5~20mA。因此,驱动发光二极管是不成问题的。在电流为10mA时,可计算得电阻应为3.3V/0.01A=330Ω,考虑到工作状态下的发光二极管的正向电阻一般为几十到几百欧姆,因此我们拿发光二极管串联一个270Ω的电阻就差不多了。
补充一句,我使用了一个非常好用的开源软件来画上面的电路图:Fritzing。感谢开源世界的开发者们!
那么按照我们的猜测,在接好线的情况下,只要我们用软件控制GPIO 23输出高/低电平,就可以让发光二级管闪烁了,那么,软件如何编写呢?
4、编写控制GPIO的程序
我使用C来写这个程序。在这里要非常感谢
@drogon 为树莓派的用户提供了一个非常好用的库:WiringPi。通过这个库,我们可以很容易地控制GPIO。
WiringPi的安装方法:
①首先确保你已经安装了make,如果没装,很简单:
②下载安装包,解压,编译,安装:
- mkdir temp
- cd temp
- wget http://project-downloads.drogon.net/files/wiringPi.tgz
- tar xf wiringPi.tgz
- cd wiringPi/wiringPi/
- make
- make install
这样就算安装完了。
③下面写程序测试:
- // led.c
-
- #include
- #include
- #include
-
- int main (int argc,char* argv[])
- {
- if (argc < 2) {
- printf("Usage example: ./led 4 n");
- return 1;
- }
- int pinNumber = atoi(argv[1]);
-
- if (-1 == wiringPiSetup()) {
- printf("Setup wiringPi failed!");
- return 1;
- }
-
- pinMode(pinNumber, OUTPUT); // set mode to output
- while(1) {
- digitalWrite(pinNumber, 1); // output a high level
- delay(800);
- digitalWrite(pinNumber, 0); // output a low level
- delay(800);
- }
-
- return 0;
- }
需要注意的是,一旦你用digitalWrite()函数置了高电平,那么只要你不把它置为低电平,它将一直维持在高电平。
编译程序:
- gcc led.c -o led -lwiringPi
运行程序:
可以看到LED开始闪烁了(如下面的Youku视频所示)。这里向程序传入了一个参数4,它代表你要置高电平的是GPIO几。为什么是4呢?因为上面已经说了,树莓派的GPIO口有两种命名方式,一种是树莓派的方式,另一种是Broadcom的方式,当使用WiringPi时,应参考前者,因此,对应到Broadcom方式的GPIO 23上,那就应该是GPIO 4,所以应该向程序输入参数4。