wiringPi library for Raspberry Pi

Reprinted from:

http://www.cnblogs.com/lulipro/p/5992172.html

wiringPi is a great IO control library for Raspberry Pi, developed in C language, providing rich interfaces: GPIO control, interrupts, multithreading, etc. The pi4j project of java is also based on wiringPi. I am also looking at the source code recently, and it will be released when it is sorted out.

Install

Go to wiringPi's github (https://git.drogon.net/?p=wiringPi;a=summary) to download the installation package. Click the snapshot on the right of the first link on the page to download and install the compressed package.

Then enter the directory where the installation package is located and execute the following command:

>tar xfz wiringPi-98bcb20.tar.gz    //98bcb20 is the version number, which may be different
 >cd wiringPi - 98bcb20
>./build

To verify whether the wiringPi is installed successfully, enter gpio -v, and the related wiringPi information will be output in the terminal. Otherwise the installation fails.

 

compile and run

If you write a project of LEDtest.c, it is as follows.

copy code
Compile:

g++ -Wall -o LEDtest LEDtest.cpp -lwiringPi          // use C++ programming, -Wall is to enable all warnings to find problems in the program

gcc -Wall -o LEDtest LEDtest.c -lwiringPi           // Program in C language


run:

sudo ./LEDtest
copy code

View pin number table

Use the following console command

> gpio readall

 See also the figure below.

Note: When viewing, face the USB port of the Raspberry Pi towards you, so that you can see it correctly.

 

 

WiringPi library API Daquan

When using the wiringPi library, you need to include the header file #include<wiringPi.h>. All programs that write wiringPi include this header file.

 

hardware initialization function

When using wiringPi, you must initialize the Raspberry Pi before performing any operations, otherwise the program will not work properly.

You can call one of the following functions to initialize, they all return an int, and return -1 to indicate that the initialization failed.

 

int wiringPiSetup (void) Return: execution status, -1 means failure

When using this function to initialize the Raspberry Pi pins, the program uses the wiringPi pin number table. The pins are numbered 0~16

Requires root privileges

int wiringPiSetupGpio (void) Returns the execution status, -1 means failure

When using this function to initialize the Raspberry Pi pins, the program uses the BCM GPIO pin number table.

Requires root privileges

wiringPiSetupPhys(void)  Not commonly used, no introduction  /
wiringPiSetupSys (void) ;  Not commonly used, no introduction  /


General GPIO control function

void pinMode (int pin, int mode)

pin: configured pin

mode: the IO mode of the specified pin

Possible values: INPUT, OUTPUT, PWM_OUTPUT, GPIO_CLOCK

     


Function: configure the IO mode of the pin

Note:
Only pin 1 under the wiringPi pin number (pin 18 under BCM) supports PWM output

Only 7 under wiringPi number (4 under BCM) supports GPIO_CLOCK output

void digitalWrite (int pin, int value)

pin: the pin to control

value: The level value of the pin output.

 Available values: HIGH, LOW represent high and low levels respectively

Let the specified level signal output to a pin that has been configured as output mode
int digitalRead (int pin)

pin: the pin to read

Returns: the level on the pin, can be one of LOW HIGH

Read the level value of a pin LOW HIGH , return
void analogWrite(int pin, int value)

pin: pin

value: the output analog

Analog output

The pins of the Raspberry Pi itself do not support AD conversion, that is, the analog API cannot be used.

Additional modules need to be added
int analogRead (int pin)

pin: pin

Return: the analog quantity read on the pin

Analog input

The pins of the Raspberry Pi itself do not support AD conversion, that is, the analog API cannot be used.

Additional modules need to be added

void pwmWrite (int pin, int value)

pin: pin

value: The value written to the PWM register, ranging from 0 to 1024.

Output a value to the PWM register to control the PWM output.
The pin can only be pin 1 under the wiringPi pin number (pin 18 under BCM)
void pullUpDnControl (int pin, int pud)

 pin: pin

pud: pull-resistor mode

Possible values: PUD-OFF off pull-up resistor
             PUD_DOWN pin level pulled to 3.3v
             PUD_UP pin level pulled to 0v ground

Set pull-resistor mode for an input pin whose IO mode is set to INPUT.

Unlike Arduino, Raspberry Pi supports more pull-resistor modes.

The pull-up resistors inside the Raspberry Pi are up to 50K ohms


 LED blinking procedure

#include<iostream>
#include<cstdlib>
#include<wiringPi.h>   

const  int LEDpin = 1 ;

intmain ()
{
      if(-1==wiringPiSetup())
      {
             cerr<<"setup error\n";
             exit(-1);
      }
      pinMode(LEDpin,OUTPUT);      


      for(size_t i=0;i<10;++i)
      {
                digitalWrite(LEDpin,HIGH); 
                delay(600);
                digitalWrite(LEDpin,LOW);
                delay(600);
   
      }
        
      cout<<"------------bye-------------"<<endl;
      return 0;   
}

 PWM输出控制LED呼吸灯的例子

#include<iostream>
#include<wiringPi.h>
#include<cstdlib>
using namespace std;


const int PWMpin = 1;   //只有wiringPi编号下的1脚(BCM标号下的18脚)支持
void setup();

int main()
{

    setup();
    int val = 0;
    int step = 2;
    while(true)
    {
        if(val>1024)
        {
            step = -step;    
            val = 1024;
        }
        else if(val<0)
        {
            step = -step;
            val = 0;
        }

        pwmWrite(PWMpin,val);
        val+=step;
        delay(10);
    }

    return 0;
}

void setup()
{
    if(-1==wiringPiSetup())
    {
        cerr<<"setup error\n";
        exit(-1);
    }
    pinMode(PWMpin,PWM_OUTPUT);
}

 

时间控制函数

unsigned int millis (void)
这个函数返回 一个 从你的程序执行 wiringPiSetup  初始化函数(或者wiringPiSetupGpio ) 到 当前时间 经过的 毫秒数。
返回类型是unsigned int,最大可记录 大约49天的毫秒时长。
unsigned int micros (void) 这个函数返回 一个 从你的程序执行 wiringPiSetup  初始化函数(或者wiringPiSetupGpio ) 到 当前时间 经过的 微秒数。
返回类型是unsigned int,最大可记录 大约71分钟的时长。
void delay (unsigned int howLong) 将当前执行流暂停 指定的毫秒数。因为Linux本身是多线程的,所以实际暂停时间可能会长一些。参数是unsigned int 类型,最大延时时间可达49天
void delayMicroseconds (unsigned int howLong) 将执行流暂停 指定的微秒数(1000微秒 = 1毫秒 = 0.001秒)。
因为Linux本身是多线程的,所以实际暂停时间可能会长一些。参数是unsigned int 类型,最大延时时间可达71分钟


中断

wiringPi提供了一个中断处理注册函数,它只是一个注册函数,并不处理中断。他无需root权限。

 

int wiringPiISR (int pin, int edgeType,  void (*function)(void))

返回值:返回负数则代表注册失败

pin:接受中断信号的引脚

edgeType:触发的方式。

 INT_EDGE_FALLING:下降沿触发
 INT_EDGE_RISING:上升沿触发
 INT_EDGE_BOTH :上下降都会触发
 INT_EDGE_SETUP:编程时用不到。       

    

function:中断处理函数的指针,它是一个无返回值,无参数的函数。

注册的函数会在中断发生时执行

和51单片机不同的是:这个注册的中断处理函数会和main函数并发执行(同时执行,谁也不耽误谁)

当本次中断函数还未执行完毕,这个时候树莓派又触发了一个中断,那么这个后来的中断不会被丢弃,它仍然可以被执行。但是wiringPi最多可以跟踪并记录后来的仅仅1个中断,如果不止1个,则他们会被忽略,得不到执行。


 通过1脚检测 因为按键按下引发的 下降沿,触发中断,反转11控制的LED

#include<iostream>
#include<wiringPi.h>
#include<cstdlib>
using namespace std;

void ButtonPressed(void);
void setup();

/********************************/
const int LEDPin = 11;
const int ButtonPin = 1;
/*******************************/

int main()
{

    setup();

    //注册中断处理函数
    if(0>wiringPiISR(ButtonPin,INT_EDGE_FALLING,ButtonPressed))
    {
        cerr<<"interrupt function register failure"<<endl;
        exit(-1);
    }


    while(1)
    ;

    return 0;
}

void setup()
{
    if(-1==wiringPiSetup())
    {
        cerr<<"wiringPi setup error"<<endl;
        exit(-1);
    }
    
    pinMode(LEDPin,OUTPUT);    //配置11脚为控制LED的输出模式
    digitalWrite(LEDPin,LOW);  //初始化为低电平

    pinMode(ButtonPin,INPUT);            //配置1脚为输入
    pullUpDnControl(ButtonPin,PUD_UP);  //将1脚上拉到3.3v

}


//中断处理函数:反转LED的电平
void ButtonPressed(void)
{

    digitalWrite(LEDPin,  (HIGH==digitalRead(LEDPin))?LOW:HIGH );

}


多线程

wiringPi提供了简单的Linux系统下的通用的 Posix threads线程库接口来支持并发。

int piThreadCreate(name)

name:被包装的线程执行函数

返回:状态码。返回0表示成功启动,反之失败。

源代码:
int piThreadCreate (void *(*fn)(void *))
{
  pthread_t myThread ;

  return pthread_create (&myThread, NULL, fn, NULL) ;
}

包装一个用PI_THEEAD定义的函数为一个线程,并启动这个线程。

首先你需要通过以下方式创建一个特特殊的函数,这个函数中的代码就是在新的线程中将执行的代码。,myTread是你自己线程的名字,可自定义。


PI_THREAD (myThread)
{
   //在这里面写上的代码会和主线程并发执行。
}

在wiringPi.h中,我发现这样一个宏定义:#define PI_THREAD(X) void *X (void *dummy)
那么,被预处理后我们写的线程函数会变成下面这个样子,请注意返回值,难怪我每次写都会警告,因为没有返回一个指针,
那么,以后注意返回NULL,或者 (void*)0  
void *myThread (void *dummy)
{
 //在这里面写上的代码会和主线程并发执行。
}


piLock(int keyNum) keyNum:0-3的值,每一个值代表一把锁

使能同步锁。wiringPi只提供了4把锁,也就是keyNum只能取0~3的值,官方认为有这4把锁就够了。

keyNum:0,1,2,3 每一个数字就代表一把锁。

源代码:

void piLock (int keyNum)
{
  pthread_mutex_lock (&piMutexes [keyNum]) ;
}

 

piUnlock(int keyNum) keyNum:0-3的值,每一个值代表一把锁

解锁,或者说让出锁。

源代码:

void piUnlock (int key)
{
  pthread_mutex_unlock (&piMutexes [key]) ;
}

int piHiPri (int priority)

priority:优先级指数,0~99

返回值:0,成功

         -1:,失败

设定线程的优先级,设定线程的优先级变高,不会使程序运行加快,但会使这个线程获得相当更多的时间片。priority是相对的。比如你的程序只用到了主线程,

和另一个线程A,主线程设定优先级为1,A线程设定为2,那也代表A比main线程优先级高。


凡是涉及到多线程编程,就会涉及到线程安全的问题,多线程访问同一个数据,需要使用同步锁来保障数据操作正确性和符合预期。

当A线程锁上 锁S 后,其他共用这个锁的竞争线程,只能等到锁被释放,才能继续执行。

成功执行了piLock 函数的线程将拥有这把锁。其他线程想要拥有这把锁必须等到这个线程释放锁,也就是这个线程执行piUnlock后。

同时要扩展的知识是:volatile 这个C/C++中的关键字,它请求编译器不缓存这个变量的数据,而是每次都从内存中读取。特别是在多线程下共享放变量,必须使用volatile关键字声明才是保险的。

softPwm,软件实现的PWM

树莓派硬件上支持的PWM输出的引脚有限,为了突破这个限制,wiringPi提供了软件实现的PWM输出API。

需要包含头文件:#include <softPwm.h>

编译时需要添pthread库链接  -lpthread

int softPwmCreate (int pin, int initialValue, int pwmRange)

pin:用来作为软件PWM输出的引脚

initalValue:引脚输出的初始值

pwmRange:PWM值的范围上限

建议使用100.

返回:0表示成功。

使用一个指定的pin引脚创建一个模拟的PWM输出引脚
void softPwmWrite (int pin, int value)

pin:通过softPwmCreate创建的引脚

value:PWM引脚输出的值

更新引脚输出的PWM


串口通信

使用时需要包含头文件:#include <wiringSerial.h>

int serialOpen (char *device, int baud)

device:串口的地址,在Linux中就是设备所在的目录。

默认一般是"/dev/ttyAMA0",我的是这样的。

 baud:波特率

返回:正常返回文件描述符,否则返回-1失败。

打开并初始串口

void serialClose (int fd)
fd:文件描述符 关闭fd关联的串口
void  serialPutchar (int fd, unsigned char c)

fd:文件描述符

c:要发送的数据

发送一个字节的数据到串口
void  serialPuts (int fd, char *s)

fd:文件描述符

s:发送的字符串,字符串要以'\0'结尾

发送一个字符串到串口
void  serialPrintf (int fd, char *message, …)

fd:文件描述符

message:格式化的字符串

像使用C语言中的printf一样发送数据到串口
int   serialDataAvail (int fd)

fd:文件描述符

返回:串口缓存中已经接收的,可读取的字节数,-1代表错误

 获取串口缓存中可用的字节数。
int serialGetchar (int fd)

fd:文件描述符

返回:读取到的字符

从串口读取一个字节数据返回。

如果串口缓存中没有可用的数据,则会等待10秒,如果10后还有没,返回-1

所以,在读取前,做好通过serialDataAvail判断下。

void serialFlush (int fd)

fd:文件描述符

刷新,清空串口缓冲中的所有可用的数据。

*size_t write (int fd,const void * buf,size_t count)

fd:文件描述符

buf:需要发送的数据缓存数组

count:发送buf中的前count个字节数据

返回:实际写入的字符数,错误返回-1

这个是Linux下的标准IO库函数,需要包含头文件#include <unistd.h>

当要发送到的数据量过大时,wiringPi建议使用这个函数。

*size_t read(int fd,void * buf ,size_t count);

fd:文件描述符

buf:接受的数据缓存的数组

count:接收的字节数.

返回:实际读取的字符数。

这个是Linux下的标准IO库函数,需要包含头文件#include <unistd.h>

当要接收的数据量过大时,wiringPi建议使用这个函数。


初次使用树莓派串口编程,需要配置。我开始搞了很久,以为是程序写错了 还一直在调试。。。(~ ̄— ̄)~

copy code
/* 修改 cmdline.txt文件 */
>cd /boot/
>sudo vim cmdline.txt


删除【】之间的部分
dwc_otg.lpm_enable=0 【console=ttyAMA0,115200】 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait


/*修改 inittab文件 */
>cd /etc/
>sudo vim inittab

注释掉最后一行内容:,在前面加上 # 号
#T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100


sudo reboot 重启

树莓派作为串口接收方(测试程序):

#include<iostream>
#include<cstdlib>
#include<wiringPi.h>
#include<wiringSerial.h>
using namespace std;

void setup();
const int LEDPin = 11;

int main()
{
    setup();
    
    int fd; //Linux 的思想是:将一切IO设备,都看做 文件,fd就是代表串口抽象出来的文件
    
    if((fd = serialOpen("/dev/ttyAMA0",9600))==-1)    //初始化串口,波特率9600
    {
        
        cerr<<"serial open error"<<endl;
        exit(-1);

    }

    while(true)
    {    
        if(serialDataAvail(fd) >= 1) //If there is data in the serial port buffer
        {
            int data = serialGetchar(fd);

            if(data==0) //Receive data 0 sent by 51
            {
                / / close led
                digitalWrite(LEDPin,LOW);
            }
            else if(data==1) //Received data 1 sent by 51
            {
                //open led
                digitalWrite(LEDPin,HIGH);
            }
        }
    }
    return 0;
}

void setup( )
{
    if(-1==wiringPiSetup())
    {
        cerr<<"set up error"<<endl;
        exit(-1);
    }
    
    pinMode(LEDPin,OUTPUT);
    digitalWrite(LEDPin,HIGH);
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324537171&siteId=291194637