WiringNP: NanoPi NEO/NEO2/Air GPIO Programming with C/zh

From FriendlyARM WiKi
Jump to: navigation, search

English

WiringPi简介

wiringPi库最早是由Gordon Henderson所编写并维护的一个用C语言写成的类库,除了GPIO库,还包括了I2C库、SPI库、UART库和软件PWM库等,由于wiringPi的API函数和arduino非常相似,这也使得它广受欢迎。
wiringPi库除了提供wiringPi类库及其头文件外,还提供了一个命令行工具gpio:可以用来设置和读写GPIO管脚,以方便在Shell脚本中控制GPIO管脚。

wiringPi库最初是为BCM2835芯片编写的,后被移植到Allwinner平台,针对NanoPi的wiringPi衍生版本其项目命名为WiringNP,目前支持NanoPi M1NanoPi M1 PlusNanoPi NEONanoPi NEO AirNanoPi NEO2NanoPi NEO Plus2开发板, 最初版本是由网友wertyzp提供的版本,而针对NEO2的H5版本由FriendlyELEC提供支持。

WiringNP项目主页: https://github.com/friendlyarm/WiringNP

WiringNP在NEO/NEO Air/NEO2/NEO Plus2上的安装

通过ssh,或者串口终端进入开发板的命令行,从 github 上下载WiringNP代码并编译安装:

git clone https://github.com/friendlyarm/WiringNP
cd WiringNP/
chmod 755 build
./build

WiringNP在NanoPi M1/M1 Plus上的安装

通过ssh,或者串口终端进入开发板的命令行,从 github 上下载WiringNP代码并编译安装:

git clone https://github.com/friendlyarm/WiringNP
cd WiringNP/
git checkout nanopi-m1
chmod 755 build
./build

测试安装

WiringNP包括一套gpio命令,使用gpio命令可以控制NanoPi上的各种接口,通过以下指令可以测试WiringNP是否安装成功:

gpio readall

如果安装成功会显示NanoPI的IO图,例如NanoPI NEO2会显示如下信息:

root@FriendlyARM:~# gpio readall
 +-----+-----+----------+------+---+-NanoPi NEO/NEO2--+------+----------+-----+-----+
 | BCM | wPi |   Name   | Mode | V | Physical | V | Mode | Name     | wPi | BCM |
 +-----+-----+----------+------+---+----++----+---+------+----------+-----+-----+
 |     |     |     3.3V |      |   |  1 || 2  |   |      | 5V       |     |     |
 |  12 |   8 |  GPIOA12 |  OFF | 0 |  3 || 4  |   |      | 5V       |     |     |
 |  11 |   9 |  GPIOA11 |  OFF | 0 |  5 || 6  |   |      | 0v       |     |     |
 | 203 |   7 |  GPIOG11 |  OUT | 1 |  7 || 8  | 0 | OFF  | GPIOG6   | 15  | 198 |
 |     |     |       0v |      |   |  9 || 10 | 0 | OFF  | GPIOG7   | 16  | 199 |
 |   0 |   0 |   GPIOA0 |  OFF | 0 | 11 || 12 | 0 | OFF  | GPIOA6   | 1   | 6   |
 |   2 |   2 |   GPIOA2 |  OFF | 0 | 13 || 14 |   |      | 0v       |     |     |
 |   3 |   3 |   GPIOA3 |  OFF | 0 | 15 || 16 | 0 | OFF  | GPIOG8   | 4   | 200 |
 |     |     |     3.3v |      |   | 17 || 18 | 0 | OFF  | GPIOG9   | 5   | 201 |
 |  64 |  12 |   GPIOC0 |  OFF | 0 | 19 || 20 |   |      | 0v       |     |     |
 |  65 |  13 |   GPIOC1 |  OFF | 0 | 21 || 22 | 0 | OFF  | GPIOA1   | 6   | 1   |
 |  66 |  14 |   GPIOC2 |  OFF | 0 | 23 || 24 | 0 | OFF  | GPIOC3   | 10  | 67  |
 +-----+-----+----------+------+---+----++----+---+------+----------+-----+-----+
 | BCM | wPi |   Name   | Mode | V | Physical | V | Mode | Name     | wPi | BCM |
 +-----+-----+----------+------+---+-NanoPi NEO/NEO2--+------+----------+-----+-----+
 
 +-----+----NanoPi NEO/NEO2 Debug UART-+----+
 | BCM | wPi |   Name   | Mode | V | Ph |
 +-----+-----+----------+------+---+----+
 |   4 |  17 |   GPIOA4 | ALT5 | 0 | 37 |
 |   5 |  18 |   GPIOA5 | ALT4 | 0 | 38 |
 +-----+-----+----------+------+---+----+

WiringNP示例

以NanoPi NEO2为例,将一个Matrix - LED通过连接至NanoPi NEO2,像下图这样:
WiringNP-LED-Demo
其中,引脚的连接对应如下:

Matrix-LED NanoPi M1
S Pin7
V Pin4
G Pin6

接下来我们用WiringNP实现一个LED闪烁的例子,
在代码中使用数字7来操作Pin7这个引脚,即引脚的编号直接使用物理编号:

C语言示例

创建一个C源文件:

vi test.c

然后键入如下代码:

#include <wiringPi.h>
int main(void)
{
  wiringPiSetup() ;
  pinMode (7, OUTPUT) ;
  for(;;)
  {
    digitalWrite(7, HIGH) ;
    delay (500) ;
    digitalWrite(7,  LOW) ;
    delay (500) ;
  }
}

编译test.c并运行:

gcc -Wall -o test test.c -lwiringPi -lpthread
sudo ./test

看到LED灯一闪一闪的,就表示成功了。

PWM示例

PWM在NanoPi NEO/NEO2上的针脚与SerialPort0是复用的,所以你需要先执行 sudo npi-config 命令,进入Advanced Options菜单,执行其中的Enable/Disable PWM操作,将PWM针脚启用后,方可使用PWM功能,注意,在启用PWM之后,SerialPort0接口将不可使用,所以你需要使用ssh终端来进行操作。

以NanoPi NEO2为例,参照下图将一个Matrix - Buzzer配置连接至NanoPi NEO2:
WiringNP-PWM-Demo

然后,创建一个C源文件:

vi pwmtest.c

然后键入如下代码:

#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main (void)
{
  int l ;
  printf ("PWM test program\n") ;
 
  //using wiringPi Pin Number
  int pin = 18;              
  if (wiringPiSetup () == -1)
    exit (1) ;               
 
  /*
  //using Physical Pin Number
  int pin = 38;              
  if (wiringPiSetupPhys() == -1)
    exit (1) ;                  
  */                            
 
  /*
  //using BCM Pin Number
  int pin = 5;          
  if (wiringPiSetupGpio() == -1)
    exit (1);                   
  */                            
 
  pinMode (pin, PWM_OUTPUT);
  for (;;) {                      
    for (l = 0 ; l < 1024 ; ++l) {
      pwmWrite (pin, l) ;         
      delay (1) ;        
    }                              
    for (l = 1023 ; l >= 0 ; --l) {
      pwmWrite (pin, l) ;          
      delay (1) ;        
    }            
  }         
  return 0 ;
}

编译pwmtest.c并运行:

gcc -Wall -o pwmtest pwmtest.c -lwiringPi -lpthread
sudo ./pwmtest

可听到PWM蜂鸣器响起。

Shell示例

创建一个shell脚本:

vi test.sh

然后键入如下代码:

LED=7
gpio mode $LED out
while true; do
  gpio write $LED 1
  sleep 0.5
  gpio write $LED 0
  sleep 0.5
done

运行脚本:

sudo source test.sh

会看到LED闪烁了。

WiringNP 常用API速查

初始化函数

wiringPiSetup (void)

该函数初始化wiringPi,并假定程序将使用wiringPi的管脚定义图。具体管脚映射,可以通过gpio readall命令来查看。
该函数需要root权限。

int wiringPiSetupGpio(void)

该函数和wiringPiSetup函数类似,区别在于假定程序使用的是CPU的GPIO管脚定义,而没有重新映射。
该函数需要root权限。

int wiringPiSetupPhys (void)

该函数和wiringPiSetup函数类似,区别在于不允许程序使用物理管脚定义,仅支持P1接口。
该函数需要root权限。

int wiringPiSetupSys (void)

该函数初始化wiringPi,使用/sys/class/gpio接口,而不是直接通过操作硬件来实现。
该函数可以使用非root权限用户,在此种模式下的管脚号是CPU的GPIO管脚号,和wiringPiSetupGpio函数类似。
在此种模式下,在运行程序前,您需要通过/sys/class/gpio接口导出要使用的管脚。
你可以在一个独立的shell脚本中来导出将要使用的管脚,或者使用系统的system()函数来调用GPIO命令。

核心函数

void pinMode (int pin, int mode)

使用该函数可以将某个引脚配置为INPUT(输入) OUTPUT(输出)PWM_OUTPUT(脉冲输出)或者GPIO_CLOCK(时钟)。
在Sys模式下,这个函数没有影响。
你可以通过调用GPIO命令在shell脚本中来设置管脚的模式。

void pullUpDnControl (int pin, int pud)

使用该函数可以设置指定管脚使用上拉或者下拉电阻模式,通常当需要管脚作为输入引脚时,需要设定此项。
不同于Arduino,CPU有内部上拉和下拉电阻这两种模式。
参数pud可以为PUD_OFF(无上拉或下拉电阻)、PUD_DOWN(内部下拉至地线)或者PUD_UP(内部上拉至3.3V)。
在NanoPi M1上,内部上拉和下拉电阻有接近100KΩ。
该函数在Sys模式下无作用。
如果你需要激活上拉或下拉电阻的话,在启动程序前,可以通过在脚本中调用GPIO命令来实现。

void digitalWrite (int pin, int value)

使用该函数可以向指定的管脚写入HIGH(高)或者LOW(低),写入前,需要将管脚设置为输出模式。
wiringPi将任何的非0值作为HIGH(高)来对待,因此,0是唯一能够代表LOW(低)的数值。

void pwmWrite (int pin, int value)

使用该函数可以将值写入指定管脚的PWM寄存器中,可设置的值为0~1024,其他PWM讴备可能有不同的PWM范围。
当在Sys模式时,该函数不可用来控制板上PWM。

digitalRead(int pin);

使用该函数可以读取指定管脚的值,读取到的值为HIGH(1)或者LOW(0),该值取决于该管脚的逻辑电平的高低。

analogRead (int pin) ;

该函数返回所指定的模拟输入管脚的值。你需要添加额外的模拟模块来使用该函数,比如Gertboard,quick2Wire模拟板等。

analogWrite (int pin, int value) ;

该函数将指定的值写入到指定的管脚。你需要添加额外的模拟模块来使用该函数,比如Gertboard等。


更新日志

2017-05-24

补充配件连接的图片

2017-05-17

补充NanoPi M1的安装说明,NEO/NEO2与M1使用不同的代码分支

2017-05-16

1) 增加 NEO2 的支持 2) 增加PWM操作的示例代码