树莓派WiringPi库
WiringPi 是一个为树莓派提供的 C 语言库 ,让用户能简单便捷地访问树莓派的 GPIO(通用目的输入输出)引脚,实现与外部设备的交互
1.下载WiringPi库
命令安装
sudo apt - get install wiringpi
验证安装
gpio -v
或
gpio readall
手动安装
如果无法通过软件源正常安装,可从 WiringPi 的 GitHub 仓库The Drogon Network | Crow下载安装包。下载后,解压文件,进入解压后的目录,执行以下的命令进行编译安装;
./build
2.基本使用步骤
1.包含头文件:在代码开头添加 #include <wiringPi.h> 引入 WiringPi 库函数声明。
2.初始化:调用 wiringPiSetup() 初始化
3.设置引脚模式:利用 pinMode(int pin, int mode) 函数设置引脚输入输出模式,如 pinMode(XXX, OUTPUT) 设置为输出模式,pinMode(XXX, INPUT) 设置为输入模式 。
4.读写引脚:用 digitalWrite(int pin, int value) 向引脚写高低电平,digitalRead(int pin) 读取引脚电平状态。
5.编译运行:编译时加上 -lwiringPi 链接库,例如 gcc your_code.c -lwiringPi
3.常用API介绍
功能分类 | 函数原型 | 功能描述 | 参数说明 | 返回值 |
---|---|---|---|---|
初始化 | int wiringPiSetup(void) | 使用 WiringPi 引脚编号方案初始化 WiringPi 库 | 无 | 0(成功),-1(失败) |
int wiringPiSetupGpio(void) | 使用 BCM GPIO 引脚编号方案初始化 WiringPi 库 | 无 | 0(成功),-1(失败) | |
int wiringPiSetupPhys(void) | 使用物理引脚编号方案初始化 WiringPi 库 | 无 | 0(成功),-1(失败) | |
GPIO 操作 | void pinMode(int pin, int mode) | 设置指定引脚的模式(输入 / 输出 / PWM 输出) | pin :引脚编号;mode :INPUT (输入)、OUTPUT (输出)、PWM_OUTPUT (PWM 输出,仅适用于特定引脚) | 无 |
void digitalWrite(int pin, int value) | 向指定输出引脚写入高低电平 | pin :引脚编号;value :HIGH (高电平,通常为 1)或LOW (低电平,通常为 0) | 无 | |
int digitalRead(int pin) | 读取指定输入引脚的电平状态 | pin :引脚编号 | HIGH (1)或LOW (0) | |
void pullUpDnControl(int pin, int pud) | 设置指定输入引脚的上拉 / 下拉电阻状态 | pin :引脚编号;pud :PUD_OFF (无上拉 / 下拉电阻)、PUD_DOWN (下拉电阻)、PUD_UP (上拉电阻) | 无 | |
PWM 相关 | void pwmWrite(int pin, int value) | 在支持 PWM 的引脚上设置 PWM 输出值(控制占空比) | pin :支持 PWM 的引脚(如 GPIO18);value :取值范围 0 - 1024,0 表示占空比 0%,1024 表示占空比 100% | 无 |
中断处理 | int wiringPiISR(int pin, int edge, void (*function)(void)) | 为指定引脚设置中断服务程序 | pin :引脚编号;edge :触发方式,INT_EDGE_FALLING (下降沿触发)、INT_EDGE_RISING (上升沿触发)、INT_EDGE_BOTH (双边沿触发);function :中断回调函数指针 | 0(成功),-1(失败) |
延时 | void delay(unsigned int ms) | 使程序延时指定的毫秒数 | ms :延时的毫秒数 | 无 |
void delayMicroseconds(unsigned int us) | 使程序延时指定的微秒数 | us :延时的微秒数 | 无 | |
串口通信 | int serialOpen(const char *device, int baud) | 打开并初始化指定的串口设备 | device :串口设备路径(如/dev/ttyAMA0 );baud :波特率 | 成功返回文件描述符(非负整数),失败返回 - 1 |
void serialClose(int fd) | 关闭指定的串口设备 | fd :串口文件描述符(由serialOpen 返回) | 无 | |
void serialPutchar(int fd, unsigned char c) | 向指定串口发送一个字符 | fd :串口文件描述符;c :要发送的字符 | 无 | |
void serialPuts(int fd, const char *s) | 向指定串口发送一个字符串 | fd :串口文件描述符;s :字符串指针 | 无 | |
void serialPrintf(int fd, const char *message, ...) | 向指定串口发送格式化字符串(类似printf ) | fd :串口文件描述符;message :格式化字符串,后续为可变参数 | 无 | |
int serialDataAvail(int fd) | 检查指定串口缓冲区中可用的字节数 | fd :串口文件描述符 | 返回可用字节数(非负整数),错误返回 - 1 | |
int serialGetchar(int fd) | 从指定串口读取一个字符(阻塞方式) | fd :串口文件描述符 | 成功返回读取的字符(ASCII 码值),超时返回 - 1 | |
I2C 通信 | int wiringPiI2CSetup(int devId) | 初始化指定 I2C 设备 | devId :I2C 设备地址 | 成功返回设备文件描述符(非负整数),失败返回 - 1 |
int wiringPiI2CRead(int fd) | 从指定 I2C 设备读取一个字节数据 | fd :I2C 设备文件描述符(由wiringPiI2CSetup 返回) | 成功返回读取的数据(0 - 255),失败返回 - 1 | |
int wiringPiI2CWrite(int fd, int data) | 向指定 I2C 设备写入一个字节数据 | fd :I2C 设备文件描述符;data :要写入的数据(0 - 255) | 成功返回 0,失败返回 - 1 | |
SPI 通信 | void spiBegin(void) | 初始化 SPI 总线 | 无 | 无 |
void spiEnd(void) | 结束 SPI 总线通信 | 无 | 无 | |
int spiTransfer(int data) | 在 SPI 总线上传输一个字节数据并返回接收到的数据 | data :要发送的数据(0 - 255) | 返回接收到的数据(0 - 255) |
4.引脚编号说明
BCM:Broadcom SOC 芯片的 GPIO 引脚编号 ,是基于树莓派所使用的博通芯片内部定义的编号,在底层开发和官方文档中常用
wPi:WiringPi 库定义的引脚编号 ,WiringPi 是用于树莓派 GPIO 控制的第三方库,为简化编程对引脚重新编号,但该库已不再更新维护
Name:引脚功能名称 ,比如 SDA.1 、SCL.1 分别是 I2C1 总线的数据线和时钟线;GPIO 开头的表示通用输入输出引脚;还有电源引脚如 3.3v 、5v 、0v (接地 )
Mode:引脚默认模式 ,IN 表示输入模式,OUT 表示输出模式 ,部分引脚还可能有其他复用功能模式(如 ALT0 等 )
V :引脚的电平相关属性,这里的 0 和 1 可能用于表示某些功能的启用或禁用状态等(不同场景含义有别 )
Physical:引脚的物理位置编号 ,按照树莓派 GPIO 排针从上到下、从左到右的顺序依次编号,便于在实际硬件连接时快速定位引脚
5.实际使用WiringPi库
1.输入命令控制继电器组
#include <wiringPi.h>
#include <stdio.h>
#include <string.h>#define SWICH1 26
#define SWICH2 27
#define SWICH3 28
#define SWICH4 29
int main()
{char cmd[12];if(wiringPiSetup() == -1){printf("Initgpio failed!\n");return -1;}pinMode(SWICH1,OUTPUT);pinMode(SWICH2,OUTPUT);pinMode(SWICH3,OUTPUT);pinMode(SWICH4,OUTPUT);digitalWrite(SWICH1,HIGH);digitalWrite(SWICH2,HIGH);digitalWrite(SWICH3,HIGH);digitalWrite(SWICH4,HIGH);while(1){printf("请输入1/2/3/4 on或off:\n");memset(cmd,'\0',sizeof(cmd));//scanf("%s",&cmd);gets(cmd);if(strcmp(cmd,"1 on") == 0){digitalWrite(SWICH1,LOW);}else if(strcmp(cmd,"1 off") == 0){digitalWrite(SWICH1,HIGH);}if(strcmp(cmd,"2 on") == 0){digitalWrite(SWICH2,LOW);}else if(strcmp(cmd,"2 off") == 0){digitalWrite(SWICH2,HIGH);}if(strcmp(cmd,"3 on") == 0){digitalWrite(SWICH3,LOW);}else if(strcmp(cmd,"3 off") == 0){digitalWrite(SWICH3,HIGH);}if(strcmp(cmd,"4 on") == 0){digitalWrite(SWICH4,LOW);}else if(strcmp(cmd,"4 off") == 0){digitalWrite(SWICH4,HIGH);}if(strcmp(cmd,"all off") == 0){digitalWrite(SWICH2,HIGH);digitalWrite(SWICH3,HIGH);digitalWrite(SWICH4,HIGH);digitalWrite(SWICH5,HIGH);printf("全部关闭 自动退出!\n");return -1;}}return 0;
}
2.超声波测距
#include <wiringPi.h>
#include <stdio.h>
#include <sys/time.h>#define Trig 4
#define Echo 5void chaoshengboInit(void)
{pinMode(Echo, INPUT);//检测波什么时候发什么时候回来设置端口为输入pinMode(Trig, OUTPUT);//触发脉冲设置端口为输出
}float disMeasure(void)//测距原理
{struct timeval tv1;struct timeval tv2;long start, stop;float dis;digitalWrite(Trig, LOW);//先让脉冲处于低平稳delayMicroseconds(2);digitalWrite(Trig, HIGH);//再拉高delayMicroseconds(10); //发出超声波脉冲digitalWrite(Trig, LOW);//拉低至平稳while ((digitalRead(Echo) != 1));gettimeofday(&tv1, NULL); //获取当前时间,开始接收到返回信号的时候while (!(digitalRead(Echo) == 0));gettimeofday(&tv2, NULL); //获取当前时间,最后接收到返回信号的时候start = tv1.tv_sec * 1000000 + tv1.tv_usec; //微秒级的时间,开始发波的时间stop = tv2.tv_sec * 1000000 + tv2.tv_usec;//波返回来的时间dis = (float)(stop - start) / 1000000 * 34000 / 2; //计算时间差求出距离return dis;
}int main(void)
{float dis;//用来存放测试的距离if (wiringPiSetup() == -1) { //硬件端口初始化printf("setup wiringPi failed !");return -1;}chaoshengboInit();//调用超声波函数while (1) {//不断地测距dis = disMeasure();printf("distance = %0.2f cm\n", dis);delay(1000);}return 0;
}
3.串口通信
#include <wiringSerial.h>
#include <wiringPi.h>
#include <stdio.h>
#include <string.h>
int main()
{int fd;char cmd;wiringPiSetup();fd = serialOpen("/dev/ttyAMA0",9600);//打开串口while(1){ if(serialDataAvail (fd) != -1)//如果串口有数据{printf("there is data!\n");cmd = serialGetchar (fd);//串口获取一个字符printf("cmd = %c\n",cmd);if(cmd == '1')//字符是1{serialPuts (fd,"jcc\r\n");//串口发送字符串}else if(cmd == '2'){serialPuts (fd,"cc\r\n");}}else{printf("no data!\n");}delayMicroseconds(100000);}return 0;
}