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 5
void 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;
}