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

解决方法:

  1. 确认lgpio库已安装

  2. 检查头文件路径:ls /usr/local/include/lgpio.h

  3. 如果在其他路径,编译时指定: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)"

如果引脚被占用,需要先释放或选择其他未占用的引脚。

参考资源