
本篇是建立在已经安装了 wiringOP 库之后的 C/C++ 编程教学,对于 wiringOP 库中的函数不统一介绍,而是结合使用场景再解释函数的用法和含义。
一、新建一个 .c 文件
博主使用的 LED 是自己焊接的板子,为低电平触发,即板子的控制引脚输入高电平时(香橙派输出高电平),LED 熄灭,板子的控制引脚输入低电平时(香橙派输出低电平),LED 点亮。没有灯的小伙伴可以用蜂鸣器模块代替,如下图所示,这个模块也是低电平触发的,不过它的工作电压为3.3v
。
为了之后方便管理代码,建议在主目录下新建一个文件夹,用于存放各种外设硬件与 wiringOP 库相关的代码文件和可执行文件。我这里新建了一个Peripheral
的文件夹。
mkdir Peripheral
用cd
命令进入Peripheral
文件夹,使用 vim 编辑器来新建一个 .c 文件编写程序:
vim lighting.c
这里会用到三个 wiringOP 库的函数,一个硬件初始化函数和两个通用GPIO控制函数。
int wiringPiSetup (void)
void pinMode (int pin, int mode)
void digitalWrite (int pin, int value)
使用 wiringOP 库时,必须在执行任何操作前初始化香橙派的 GPIO,否则程序不能正常工作。通常调用wiringPiSetup
函数进行初始化,成功初始化都会返回一个 int 值(表示当前执行状态), 返回 -1 表示初始化失败。
硬件初始化函数原型 | 函数返回值 | 函数说明 |
---|---|---|
int wiringPiSetup (void) | 返回:执行状态,-1表示失败 | 当使用这个函数初始化香橙派引脚时,程序使用的是wiringPi 引脚编号表。 |
控制 GPIO 引脚之前需要先设置 GPIO 引脚的模式,再进行读写操作。
通用GPIO控制函数原型 | 函数参数 | 函数说明 |
---|---|---|
void pinMode (int pin, int mode) | pin:配置的引脚 mode:指定引脚的IO模式 可取的值:INPUT、OUTPUT、PWM_OUTPUT,GPIO_CLOCK | 作用:配置引脚的IO模式 |
void digitalWrite (int pin, int value) | pin:控制的引脚 value:引脚输出的电平值。 可取的值:HIGH,LOW分别代表高低电平 | 让对一个已近配置为输出模式的引脚输出指定的电平信号 |
根据 wiringOP 库的示例(路径:wiringOP/examples),编写如下程序:
#include <stdio.h>
#include <wiringPi.h>
#define LED 2 //对应 26Pin接口引脚的 7 号引脚,该引脚的 wPi 序号为 2。
int main(void)
{
wiringPiSetup(); //wiringOP 库初始化。
pinMode(LED, OUTPUT); //把引脚设置为输出模式。
digitalWrite(LED, LOW); //把引脚电平拉低,点亮 LED。
return 0;
}
编辑好后输入:x
或:wq
保存退出。
二、编译并运行
写好代码后就是编译了,如果你直接用gcc
编译器编译,会直接报错(如下图)。根据报错的提示,是gcc
编译器"不认识"下面红框圈起来的三个函数。
原因就是 wiringOP 库属于第三方库,在编译时要用-l
链接库才能编译。这时就需要我们先找到 wiringOP 的 Makefile 文件了,这个文件在wiringOP/examples
这个路径下,可以用 vim 编辑器打开这个 Makefile 文件。打开之后,可以看到编译时要链接的全部第三方库。
把这段编译时要用到的第三方库复制出来,在编译时加上就可以编译成功了,具体如下:
gcc lighting.c -o light -lwiringPi -lwiringPiDev -lpthread -lcrypt -lrt
这样就可以编译成功了。
接好线之后,如果直接输入./lighting
运行,又会出现下面的错误。这个错误把程序给中止了,因为没有权限访问 GPIO,下面还提示了配合sudo
一起运行试试。其实就是要在前面加上sudo
才能运行。
所以正确的操作,应该是输入sudo ./lighting
运行,这时就可以看到 LED 亮起来了(或者蜂鸣器响起了)。
如果想要熄灭 LED,在刚刚的程序中,把“digitalWrite(LED, LOW);”改成“digitalWrite(LED, HIGH);”,再编译运行即可。
三、shell 脚本创建 .c 文件以及编译 .c 文件
在刚刚编写 .c 文件和编译 .c 文件的时候,都输入很多之后会重复用到的字符,例如像编译 .c 文件时,都有固定的main
函数格式。编译带有 wiringOP 库的 .c 文件时,要输入很多链接库。以上种种都使用整个国产变得十分的麻烦,所以为了之后方便,我特意编写了两个 shell 脚本,来解决这些事情。
第一个 shell 脚本用于新建固定格式且使用了 wiringOP 库的 .c 文件,使用 vim 编辑器新建这个脚本。
vim create_C_wPi.sh
把下面的内容复制粘贴进去并保存:
#!/bin/bash
name=$1.c
#echo "name=$name"
echo "#include <stdio.h>" > $name
echo "#include <wiringPi.h>" >> $name
echo "" >> $name
echo "int main(void)" >> $name
echo "{" >> $name
echo " " >> $name
echo " return 0;" >> $name
echo "}" >> $name
echo "" >> $name
vim $name
新建好的 shell 脚本不具备可执行的权限,通过ls -l
命令,或者ll
命令可以查看文件的权限信息。可以看出,我们新建的 shell 并没有可执行的权限。
可以用chmod
命令给我们的脚本加权限。
chmod +x create_C_wPi.sh
加完可执行权限后,就可以使用了。
如果我现在要编写一个 LED 一秒间隔亮灭的程序,用这个脚本的具体方式,只要输入下面的命令即可,基本后面跟着的是要创建的文件名(此处的 blink 就是我要创建的文件名)。
./create_C_wPi.sh blink
生成的效果如下:
中间的间隔时间,我们可以使用 wiringOP 库提供的时间控制函数进行等待操作。函数原型如下:
void delay (unsigned int howLong)
void delayMicroseconds (unsigned int howLong)
具体说明可参考下表:
时间控制函数原型 | 函数说明 |
---|---|
void delay (unsigned int howLong) | 将当前执行流暂停 指定的毫秒数。因为Linux本身是多线程的,所以实际暂停时间可能会长一些。 参数是 unsigned int 类型,最大延时时间可达 49 天。 |
void delayMicroseconds (unsigned int howLong) | 将执行流暂停 指定的微秒数(1000 微秒 = 1 毫秒 = 0.001 秒)。 因为 Linux 本身是多线程的,所以实际暂停时间可能会长一些。参数是 unsigned int 类型,最大延时时间可达 71 分钟。 |
我这里使用delay
函数,延时等待 1000 ms,也就是 1 秒。输入完整的程序后,并保存退出。
#include <stdio.h>
#include <wiringPi.h>
#define LED 2
int main(void)
{
wiringPiSetup();
pinMode(LED, OUTPUT);
while (1) {
digitalWrite(LED, HIGH);
delay(1000);
digitalWrite(LED, LOW);
delay(1000);
}
return 0;
}
输入ls
命令可以看到多了个名为“blink.c”的文件。
接下来就是编译了,我们再新建第二个 shell 脚本来帮我们编译代码,就命名为 build.sh。
vim build.sh
同样粘贴下面的代码并保存,权限问题和第一个脚本一样处理,这里不过赘述。
#!/bin/bash
if [ $# -ne 1 ]; then
echo "Usage: $0 <c_file>"
exit 1
fi
if [ ! -f "$1" ]; then
echo "Error: File '$1' does not exist."
exit 1
fi
src_dir=$(dirname "$1")
filename=$(basename "$1")
filename_no_ext="${filename%.*}"
extension="${filename##*.}"
gcc "$1" -Wall -lwiringPi -lwiringPiDev -lpthread -lcrypt -lrt -o "${src_dir}/${filename_no_ext}"
if [ $? -ne 0 ]; then
echo "Error: Compilation failed."
exit 1
fi
echo "Compilation successful. Executable file created: ${src_dir}/${filename_no_ext}"
以编译刚刚新建的 blink.c 为例,编译方法如下:
./build.sh blink.c
编译成功会出现下图,并告诉我们生成的可执行文件为 blink。
输入ls
命令可以看到多了个名为“blink”的文件。
输入sudo ./blink
运行,这时就可以看到 LED 闪烁起来了。由于 while 循环的原因,程序会一直跑下去,停止程序可以按组合键CTRL + z
结束。
本篇是建立在已经安装了 wiringOP 库之后的 C/C++ 编程教学,对于 wiringOP 库中的函数不统一介绍,而是结合使用场景再解释函数的用法和含义。