日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

树莓派wiringPi库详解

發布時間:2024/4/19 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 树莓派wiringPi库详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

wiringPi是一個很棒的樹莓派IO控制庫,使用C語言開發,提供了豐富的接口:GPIO控制,中斷,多線程,等等。java 的pi4j項目也是基于wiringPi的,我最近也在看源代碼,到時候整理好了會放出來的。

下面開始wiringPi之旅吧!

?

安裝

進入? wiringPi的github (https://git.drogon.net/?p=wiringPi;a=summary) 下載安裝包。點擊頁面的第一個鏈接的右邊的snapshot,下載安裝壓縮包。

然后進入安裝包所在的目錄執行以下命令:

>tar xfz wiringPi-98bcb20.tar.gz //98bcb20為版本標號,可能不同 >cd wiringPi-98bcb20 >./build

?

驗證wiringPi的是否安裝成功,輸入gpio -v,會在終端中輸出相關wiringPi的信息。否則安裝失敗。

?

?

?

?

?

編譯 和運行

假如你寫了一個LEDtest.c 的項目,則如下。

編譯:g++ -Wall -o LEDtest LEDtest.cpp -lwiringPi //使用C++編程 , -Wall 是為了使能所有警告,以便發現程序中的問題 gcc -Wall -o LEDtest LEDtest.c -lwiringPi //使用C語言編程 運行:sudo ./LEDtest

?

?

查看引腳編號表格

使用如下控制臺下命令

> gpio readall

?也可以查看下面的圖。

注意:查看時,將樹莓派的USB接口面對自己,這樣看才是正確的。

?

?

?

wiringPi庫API大全

在使用wiringPi庫時,你需要包含頭文件 #include<wiringPi.h>。凡是寫wiringPi的程序,都包含這個頭文件。

?

硬件初始化函數

使用wiringPi時,你必須在執行任何操作前初始化樹莓派,否則程序不能正常工作。

可以調用下表函數之一進行初始化,它們都會返回一個int , 返回 -1 表示初始化失敗。

?

int wiringPiSetup (void)返回:執行狀態,-1表示失敗

當使用這個函數初始化樹莓派引腳時,程序使用的是wiringPi 引腳編號表。引腳的編號為 0~16

需要root權限

int wiringPiSetupGpio (void)返回執行狀態,-1表示失敗

當使用這個函數初始化樹莓派引腳時,程序中使用的是BCM GPIO 引腳編號表。

需要root權限

wiringPiSetupPhys(void)?不常用,不做介紹?/
wiringPiSetupSys (void) ;?不常用,不做介紹?/

?

?

?

?

通用GPIO控制函數

void pinMode (int pin, int mode)

pin:配置的引腳

mode:指定引腳的IO模式

可取的值:INPUT、OUTPUT、PWM_OUTPUT,GPIO_CLOCK

?????


作用:配置引腳的IO模式

注意:
只有wiringPi 引腳編號下的1腳(BCM下的18腳) 支持PWM輸出

只有wiringPi編號下的7(BCM下的4號)支持GPIO_CLOCK輸出

void digitalWrite (int pin, int value)

pin:控制的引腳

value:引腳輸出的電平值。

?可取的值:HIGH,LOW分別代表高低電平

讓對一個已近配置為輸出模式的 引腳? 輸出指定的電平信號
int digitalRead (int pin)

pin:讀取的引腳

返回:引腳上的電平,可以是LOW HIGH 之一

讀取一個引腳的電平值? LOW? HIGH ,返回
void analogWrite(int pin, int value)

pin:引腳

value:輸出的模擬量

模擬量輸出

樹莓派的引腳本身是不支持AD轉換的,也就是不能使用模擬量的API,

需要增加另外的模塊
int analogRead (int pin)

pin:引腳

返回:引腳上讀取的模擬量

模擬量輸入

樹莓派的引腳本身是不支持AD轉換的,也就是不能使用模擬量的API,

需要增加另外的模塊

void pwmWrite (int pin, int value)

pin:引腳

value:寫入到PWM寄存器的值,范圍在0~1024之間。

輸出一個值到PWM寄存器,控制PWM輸出。
pin只能是wiringPi 引腳編號下的1腳(BCM下的18腳)
void pullUpDnControl (int pin, int pud)

?pin:引腳

pud:拉電阻模式

可取的值:PUD-OFF ? ???? 關閉拉電阻
???????????? PUD_DOWN??? 引腳電平拉到3.3v
???????????? PUD_UP???????? 引腳電平拉到0v 接地

對一個設置IO模式為 INPUT 的輸入引腳設置拉電阻模式。

與Arduino不同的是,樹莓派支持的拉電阻模式更豐富。

樹莓派內部的拉電阻達50K歐姆

?

?

?LED閃爍程序

#include<iostream> #include<cstdlib> #include<wiringPi.h> const int LEDpin = 1;int main() {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; } View Code

?

?

?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); } View Code

?




時間控制函數

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 );} View Code

?

?

?

多線程

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建議使用這個函數。

?

初次使用樹莓派串口編程,需要配置。我開始搞了很久,以為是程序寫錯了 還一直在調試。。。(~ ̄— ̄)~

/* 修改 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 vt100sudo reboot 重啟

?

?

下面是雙機通信的一個例子

C51代碼,作為串口通信的接發送。serial庫請看另一篇文章

#include<reg52.h> #include"serial.h"/**********function****************/ bit isOpenPressed(void); bit isClosePressed(void); void delay(unsigned int t); /*********************************/sbit closeButton = P2^0; //與關閉按鍵相連的引腳 sbit openButton = P2^1; //與打開按鍵相連的引腳void main(void) {closeButton = 1; //拉高openButton = 1; //拉高 EA =1; //打開總中斷serial_init(9600); //初始化51串口while(1){if(isClosePressed()) //如果關閉按鈕按下 {serial_write(0); //發送數據 0給樹莓派delay(10);}else if(isOpenPressed()) //如果打開按鈕按下 {serial_write(1); //發送數據 1給樹莓派delay(10);}} }bit isOpenPressed(void) {bit press =0;if(0==openButton){delay(5);if(0==openButton){while(!openButton);press = 1;}}return press; }bit isClosePressed(void) {bit press =0;if(0==closeButton){delay(5);if(0==closeButton){while(!closeButton);press = 1;}}return press; }void delay(unsigned int t) {unsigned int i ;unsigned char j;for(i = t;i>0;i--)for(j=120;j>0;j--); } View Code

?

樹莓派代碼,作為串口通信的接收方

#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) //如果串口緩存中有數據 {int data = serialGetchar(fd);if(data==0) //接受到51發送的 數據 0 {// close led digitalWrite(LEDPin,LOW);}else if(data==1) //接受到51發送的 數據 1 {//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);} View Code

?

?

shift移位寄存器芯片API

需要包含頭文件? #include <wiringShift.h>

void shiftOut (uint8_t dPin, uint8_t cPin, uint8_t order, uint8_t val)

dPin:移位芯片的串行數據入口引腳,比如74HC595的SER腳

cPin:移位芯片的時鐘引腳。如74HC595的11腳

order:

?? LSBFIRST 先發送數據的低位

?? MSBFIRST先發送數據的高位

?????

val:要發送的8位數據

將val串化,通過芯片轉化為并行輸出

如常見的74HC595

?uint8_t shiftIn (uint8_t dPin, uint8_t cPin, uint8_t order)
同上。?

將并行數據,通過芯片轉化為串行輸出。

?

用過595的都知道還有一個引腳:12腳,Rpin,用于把移位寄存器中的數據更新到存儲寄存器中,然后wiringPi的API中沒有使用這個引腳。我建議使用的時候自己加上。

?

#include<iostream> #include<wiringPi.h> #include <wiringShift.h> #include<cstdlib> using namespace std;const int SERpin = 1; //serial data input const int SCKpin = 2; //shift register clock const int RCKpin = 3; // storage register clock /************************/ void setup();/*************************/int main() {setup();for(int i=0;i<8;++i){digitalWrite(RCKpin,LOW);shiftOut(SERpin,SCKpin,LSBFIRST,1<<i);digitalWrite(RCKpin,HIGH);delay(800);}return 0;}void setup() {if(-1==wiringPiSetup()){cerr<<"setup error\n";exit(-1);}pinMode(SERpin,OUTPUT);pinMode(RCKpin,OUTPUT);pinMode(SCKpin,OUTPUT);} View Code

?

?

?

樹莓派硬件平臺特有的API

并沒有列全,我只是列出了相對來說有用的,其他的,都基本不會用到。

pwmSetMode (int mode)

mode:PWM運行模式

設置PWM的運行模式。

pwm發生器可以運行在2種模式下,通過參數指定:
???? PWM_MODE_BAL?? :樹莓派默認的PWM模式
???? PWM_MODE_MS??? :傳統的pwm模式,

pwmSetRange (unsigned int range)

range,范圍的最大值

0~range

設置pwm發生器的數值范圍,默認是1024
pwmSetClock (int divisor)?This sets the divisor for the PWM clock.
To understand more about the PWM system, you’ll need to read the Broadcom ARM peripherals manual.
piBoardRev (void)

返回:樹莓派板子的版本編號

1或者2

/

?

?

就這樣,以后會更新。

?

?

?

?歡迎轉載,請注明出處:www.cnblogs.com/lulipro

?為了獲得更好的閱讀體驗,請訪問原博客地址。

限于本人水平,如果文章和代碼有表述不當之處,還請不吝賜教。

代碼鋼琴家



?

總結

以上是生活随笔為你收集整理的树莓派wiringPi库详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。