C/C++ GPIO开发¶
Copyright © Quectel Wireless Solutions Co., Ltd. 2026. All rights reserved.
lgpio简介¶
lgpio 是一个用于Linux系统的GPIO控制库,提供了简单易用的C语言API来操作GPIO、I2C、SPI等外设。
主要特点¶
高性能:C语言实现,执行效率高
跨平台兼容:支持多种Linux单板计算机
功能丰富:支持GPIO、I2C、SPI、PWM等多种外设
易于集成:提供标准的C库接口
支持的功能¶
功能 |
说明 |
|---|---|
GPIO |
通用输入输出控制 |
I2C |
I²C总线通信 |
SPI |
SPI总线通信 |
PWM |
脉宽调制输出 |
通知 |
GPIO中断和事件通知 |
安装lgpio¶
从源码安装¶
# 安装依赖工具apt update
apt install -y git build-essential
# 克隆lgpio源码git clone https://github.com/joan2937/lg.git
cd lg
# 编译并安装makemake install# 更新动态链接库缓存
ldconfig
验证安装¶
安装完成后,可以通过以下命令验证:
# 检查动态库
ldconfig -p | grep lgpio
应该能看到类似 liblgpio.so 的输出。
其他验证方法:
# 检查库文件是否存在ls -l /usr/local/lib/liblgpio.*
# 检查头文件是否存在ls -l /usr/local/include/lgpio.h
GPIO控制¶
硬件准备¶
主板
杜邦线
万用表(可选,用于测量电压)
GPIO输出控制¶
以下示例演示如何使用lgpio控制GPIO引脚输出高低电平。
示例代码¶
创建 gpio_output.c 文件:
#include <stdio.h>#include <stdlib.h>#include <lgpio.h>#include <unistd.h>int main(int argc, char **argv){if (argc < 3) {printf("Usage: %s <gpio_num> <pin_level>\n", argv[0]);printf("Example: %s 36 1 # Set GPIO36 to HIGH\n", argv[0]);return 1;}int gpio_num = atoi(argv[1]);int pin_level = atoi(argv[2]);int h;// 打开GPIO芯片4
h = lgGpiochipOpen(4);if (h < 0) {printf("ERROR: %s (%d)\n", lguErrorText(h), h);return 1;}// 设置GPIO为输出模式并设置初始电平int e = lgGpioClaimOutput(h, 0, gpio_num, pin_level);if (e < 0) {printf("ERROR: %s (%d)\n", lguErrorText(e), e);lgGpiochipClose(h);return 1;}printf("GPIO %d set to %s\n", gpio_num, pin_level ? "HIGH (3.3V)" : "LOW (0V)");// 保持状态5秒sleep(5);// 释放GPIO资源lgGpioFree(h, gpio_num);lgGpiochipClose(h);return 0;}
编译程序¶
gcc -o gpio_output gpio_output.c -llgpio
运行测试¶
测试低电平:
sudo ./gpio_output 36 0
输出:GPIO 36 set to LOW (0V)
测试高电平:
sudo ./gpio_output 36 1
输出:GPIO 36 set to HIGH (3.3V)
提示:GPIO36对应40Pin的Pin3。
GPIO输入读取¶
以下示例演示如何读取GPIO引脚的状态。
示例代码¶
创建 gpio_input.c 文件:
#include <stdio.h>#include <stdlib.h>#include <lgpio.h>#include <unistd.h>int main(int argc, char **argv){if (argc < 2) {printf("Usage: %s <gpio_num>\n", argv[0]);printf("Example: %s 36 # Read GPIO36 state\n", argv[0]);return 1;}int gpio_num = atoi(argv[1]);int h, e, value;// 打开GPIO芯片4
h = lgGpiochipOpen(4);if (h < 0) {printf("ERROR: %s (%d)\n", lguErrorText(h), h);return 1;}// 设置GPIO为输入模式
e = lgGpioClaimInput(h, 0, gpio_num);if (e < 0) {printf("ERROR: %s (%d)\n", lguErrorText(e), e);lgGpiochipClose(h);return 1;}printf("Reading GPIO %d state (press Ctrl+C to exit)...\n", gpio_num);// 循环读取GPIO状态while (1) {
value = lgGpioRead(h, gpio_num);if (value < 0) {printf("ERROR: %s (%d)\n", lguErrorText(value), value);break;}printf("GPIO %d: %s\n", gpio_num, value ? "HIGH" : "LOW");sleep(1);}// 释放资源lgGpioFree(h, gpio_num);lgGpiochipClose(h);return 0;}
编译和运行¶
# 编译
gcc -o gpio_input gpio_input.c -llgpio
# 运行sudo ./gpio_input 36
GPIO输出反馈测试¶
以下示例演示如何通过一个引脚输出,另一个引脚读取来验证功能。
示例代码¶
创建 gpio_feedback.c 文件:
#include <stdio.h>#include <lgpio.h>#include <unistd.h>int main(){int h;int gpio_out = 36; // Pin3 - GPIO36int gpio_in = 37; // Pin5 - GPIO37// 打开GPIO芯片4
h = lgGpiochipOpen(4);if (h < 0) {printf("ERROR: %s (%d)\n", lguErrorText(h), h);return 1;}// 设置GPIO36为输出,GPIO37为输入int e1 = lgGpioClaimOutput(h, 0, gpio_out, 0);int e2 = lgGpioClaimInput(h, 0, gpio_in);if (e1 < 0 || e2 < 0) {printf("ERROR: Failed to claim GPIO\n");lgGpiochipClose(h);return 1;}printf("=== GPIO Feedback Test ===\n");printf("Output: GPIO%d (Pin3)\n", gpio_out);printf("Input: GPIO%d (Pin5)\n", gpio_in);printf("Please connect Pin3 and Pin5 together\n\n");for (int i = 0; i < 5; i++) {// 设置高电平lgGpioWrite(h, gpio_out, 1);usleep(100000); // 100msint val_high = lgGpioRead(h, gpio_in);printf("Output: HIGH | Input: %s\n", val_high ? "HIGH" : "LOW");sleep(1);// 设置低电平lgGpioWrite(h, gpio_out, 0);usleep(100000);int val_low = lgGpioRead(h, gpio_in);printf("Output: LOW | Input: %s\n", val_low ? "HIGH" : "LOW");sleep(1);}// 释放资源lgGpioFree(h, gpio_out);lgGpioFree(h, gpio_in);lgGpiochipClose(h);printf("\nTest completed\n");return 0;}
编译和运行¶
# 编译
gcc -o gpio_feedback gpio_feedback.c -llgpio
# 运行(需要先将Pin3和Pin5短接)sudo ./gpio_feedback
预期输出:
=== GPIO Feedback Test ===
Output: GPIO36 (Pin3)
Input: GPIO37 (Pin5)
Please connect Pin3 and Pin5 together
Output: HIGH | Input: HIGH
Output: LOW | Input: LOW
Output: HIGH | Input: HIGH
Output: LOW | Input: LOW
...
GPIO引脚映射¶
Quectel Pi H1主要使用 /dev/gpiochip4 进行GPIO控制。
常用引脚映射¶
物理引脚 |
引脚名称 |
GPIO编号 |
GPIO芯片 |
默认功能 |
|---|---|---|---|---|
Pin3 |
NFC_I2C_SDA |
36 |
/dev/gpiochip4 |
I2C09_SDA |
Pin5 |
NFC_I2C_SCL |
37 |
/dev/gpiochip4 |
I2C09_SCL |
Pin7 |
CAM2_RST |
77 |
/dev/gpiochip4 |
GPIO |
Pin11 |
GPIO_16 |
16 |
/dev/gpiochip4 |
GPIO/SPI/UART/I2C |
Pin13 |
GPIO_17 |
17 |
/dev/gpiochip4 |
GPIO/SPI/UART/I2C |
注意:Pin3和Pin5默认配置为I2C9接口,如需作为GPIO使用,请确保没有其他设备占用。
完整的引脚映射请参考:40-Pin扩展
lgpio API参考¶
GPIO芯片操作¶
// 打开GPIO芯片int lgGpiochipOpen(int chip_num);// 关闭GPIO芯片int lgGpiochipClose(int handle);
GPIO配置¶
// 申请GPIO为输出模式int lgGpioClaimOutput(int handle, int flags, int gpio, int level);// 申请GPIO为输入模式int lgGpioClaimInput(int handle, int flags, int gpio);// 释放GPIOint lgGpioFree(int handle, int gpio);
GPIO读写¶
// 读取GPIO电平int lgGpioRead(int handle, int gpio);// 写入GPIO电平int lgGpioWrite(int handle, int gpio, int level);
PWM控制¶
// 输出PWM信号int lgTxPwm(int handle, int gpio, float freq, float duty, int offset, int cycles);
常见问题¶
编译错误¶
问题:找不到lgpio.h
fatal error: lgpio.h: No such file or directory
解决方法:
确认lgpio库已安装
检查头文件路径:ls /usr/local/include/lgpio.h
如果在其他路径,编译时指定:gcc -I/path/to/include …
运行时错误¶
问题:Permission denied
解决方法:
使用 sudo 运行程序:
sudo ./gpio_output 36 1
问题:找不到共享库
error while loading shared libraries: liblgpio.so
解决方法:
# 更新动态链接库缓存sudo ldconfig
# 或者设置LD_LIBRARY_PATHexport LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
引脚占用问题¶
如果遇到GPIO已被占用的错误,使用以下命令检查:
# 查看GPIO状态
gpioinfo /dev/gpiochip4 | grep -E "(line 36|line 37|consumer)"
如果引脚被占用,需要先释放或选择其他未占用的引脚。