一、测试目的
GPIO的控制往往是在学习板卡过程中最简单的了,但是在实际测试中发现了Linux系统中GPIO的控制还是有点难度的。
二、原理图
板卡将部分的引脚通过排座引出来了,方便进行测试。通过原理图可以看到普通GPIO引脚的编号分组号和组内编号。

三、指令控制
1、导出对应GPIO属性文件
因为GPIO的复用还是比较多的,在制作系统文件的时候并没有定义这些引脚的功能,所以制作的系统是没有将这些引脚直接提供给用户使用。需要将其导入到用户可以访问的文件中,这也是在学习该板卡时遇到的最大的困难。主要是因为板卡板载芯片的上市时间是2012年左右,系统版本迭代的速度超过网上的教程了,所以导致按照网上的教程去导出时总是提示错误。
首先需用通过如下指令查看GPIO在系统中的编号(需要在root用户下可以查看,root用户的密码可以通过指令sudo passwd root)
cat /sys/kernel/debug/gpio
如果是EMMC启动的话打印内容如下
gpiochip0: GPIOs 512-543, parent: platform/4804c000.gpio, gpio-0-31: gpio-512 (P8_25 [mmc1_dat0] ) gpio-513 ([mmc1_dat1] ) gpio-514 (P8_5 [mmc1_dat2] ) gpio-515 (P8_6 [mmc1_dat3] ) gpio-516 (P8_23 [mmc1_dat4] ) gpio-517 (P8_22 [mmc1_dat5] ) gpio-518 (P8_3 [mmc1_dat6] ) gpio-519 (P8_4 [mmc1_dat7] ) gpio-520 (NC |PHY reset ) out hi ACTIVE LOW gpio-521 (NC ) gpio-522 (NC ) gpio-523 (NC ) gpio-524 (P8_12 ) gpio-525 (P8_11 ) gpio-526 (P8_16 ) gpio-527 (P8_15 ) gpio-528 (P9_15A ) gpio-529 (P9_23 ) gpio-530 (P9_14 [ehrpwm1a] ) gpio-531 (P9_16 [ehrpwm1b] ) gpio-532 ([emmc rst] ) gpio-533 ([usr0 led] |beaglebone:green:usr) out lo gpio-534 ([usr1 led] |beaglebone:green:usr) out lo gpio-535 ([usr2 led] |beaglebone:green:usr) out hi gpio-536 ([usr3 led] |beaglebone:green:usr) out lo gpio-537 ([hdmi irq] |interrupt ) in hi IRQ gpio-538 ([usb vbus oc] ) gpio-539 ([hdmi audio] |enable ) out lo gpio-540 (P9_12 ) gpio-541 (P8_26 ) gpio-542 (P8_21 [emmc] ) gpio-543 (P8_20 [emmc] ) gpiochip1: GPIOs 544-575, parent: platform/481ac000.gpio, gpio-32-63: gpio-544 (P9_15B ) gpio-545 (P8_18 ) gpio-546 (P8_7 ) gpio-547 (P8_8 ) gpio-548 (P8_10 ) gpio-549 (P8_9 ) gpio-550 (P8_45 [hdmi] ) gpio-551 (P8_46 [hdmi] ) gpio-552 (P8_43 [hdmi] ) gpio-553 (P8_44 [hdmi] ) gpio-554 (P8_41 [hdmi] ) gpio-555 (P8_42 [hdmi] ) gpio-556 (P8_39 [hdmi] ) gpio-557 (P8_40 [hdmi] ) gpio-558 (P8_37 [hdmi] ) gpio-559 (P8_38 [hdmi] ) gpio-560 (P8_36 [hdmi] ) gpio-561 (P8_34 [hdmi] ) gpio-562 ([rmii1_rxd3] ) gpio-563 ([rmii1_rxd2] ) gpio-564 ([rmii1_rxd1] ) gpio-565 ([rmii1_rxd0] ) gpio-566 (P8_27 [hdmi] ) gpio-567 (P8_29 [hdmi] ) gpio-568 (P8_28 [hdmi] ) gpio-569 (P8_30 [hdmi] ) gpio-570 ([mmc0_dat3] ) gpio-571 ([mmc0_dat2] ) gpio-572 ([mmc0_dat1] ) gpio-573 ([mmc0_dat0] ) gpio-574 ([mmc0_clk] ) gpio-575 ([mmc0_cmd] ) gpiochip2: GPIOs 576-607, parent: platform/481ae000.gpio, gpio-64-95: gpio-576 ([mii col] ) gpio-577 ([mii crs] ) gpio-578 ([mii rx err] ) gpio-579 ([mii tx en] ) gpio-580 ([mii rx dv] ) gpio-581 ([i2c0 sda] ) gpio-582 ([i2c0 scl] ) gpio-583 ([jtag emu0] ) gpio-584 ([jtag emu1] ) gpio-585 ([mii tx clk] ) gpio-586 ([mii rx clk] ) gpio-587 (NC ) gpio-588 (NC ) gpio-589 ([usb vbus en] ) gpio-590 (P9_31 [spi1_sclk] ) gpio-591 (P9_29 [spi1_d0] ) gpio-592 (P9_30 [spi1_d1] ) gpio-593 (P9_28 [spi1_cs0] ) gpio-594 (P9_42B [ecappwm0] ) gpio-595 (P9_27 ) gpio-596 (P9_41A ) gpio-597 (P9_25 ) gpio-598 (NC ) gpio-599 (NC ) gpio-600 (NC ) gpio-601 (NC ) gpio-602 (NC ) gpio-603 (NC ) gpio-604 (NC ) gpio-605 (NC ) gpio-606 (NC ) gpio-607 (NC ) gpiochip3: GPIOs 608-639, parent: platform/44e07000.gpio, gpio-96-127: gpio-608 ([mdio_data] ) gpio-609 ([mdio_clk] ) gpio-610 (P9_22 [spi0_sclk] ) gpio-611 (P9_21 [spi0_d0] ) gpio-612 (P9_18 [spi0_d1] ) gpio-613 (P9_17 [spi0_cs0] ) gpio-614 ([mmc0_cd] |cd ) in hi IRQ ACTIVE LOW gpio-615 (P9_42A [ecappwm0] ) gpio-616 (P8_35 [lcd d12] ) gpio-617 (P8_33 [lcd d13] ) gpio-618 (P8_31 [lcd d14] ) gpio-619 (P8_32 [lcd d15] ) gpio-620 (P9_20 [i2c2_sda] ) gpio-621 (P9_19 [i2c2_scl] ) gpio-622 (P9_26 [uart1_rxd] ) gpio-623 (P9_24 [uart1_txd] ) gpio-624 ([rmii1_txd3] ) gpio-625 ([rmii1_txd2] ) gpio-626 ([usb0_drvvbus] ) gpio-627 ([hdmi cec] ) gpio-628 (P9_41B ) gpio-629 ([rmii1_txd1] ) gpio-630 (P8_19 [ehrpwm2a] ) gpio-631 (P8_13 [ehrpwm2b] ) gpio-632 (NC ) gpio-633 (NC ) gpio-634 (P8_14 ) gpio-635 (P8_17 ) gpio-636 ([rmii1_txd0] ) gpio-637 ([rmii1_refclk] ) gpio-638 (P9_11 [uart4_rxd] ) gpio-639 (P9_13 [uart4_txd] )
如果是SD卡启动的话,打印内容如下
gpiochip0: 32 GPIOs, parent: platform/4804c000.gpio, gpio-0-31: gpio-0 (P8_25 [mmc1_dat0] ) gpio-1 ([mmc1_dat1] ) gpio-2 (P8_5 [mmc1_dat2] ) gpio-3 (P8_6 [mmc1_dat3] ) gpio-4 (P8_23 [mmc1_dat4] ) gpio-5 (P8_22 [mmc1_dat5] ) gpio-6 (P8_3 [mmc1_dat6] ) gpio-7 (P8_4 [mmc1_dat7] ) gpio-8 (NC |PHY reset ) out hi ACTIVE LOW gpio-9 (NC ) gpio-10 (NC ) gpio-11 (NC ) gpio-12 (P8_12 ) gpio-13 (P8_11 ) gpio-14 (P8_16 ) gpio-15 (P8_15 ) gpio-16 (P9_15A ) gpio-17 (P9_23 ) gpio-18 (P9_14 [ehrpwm1a] ) gpio-19 (P9_16 [ehrpwm1b] ) gpio-20 ([emmc rst] ) gpio-21 ([usr0 led] |beaglebone:green:usr) out hi gpio-22 ([usr1 led] |beaglebone:green:usr) out lo gpio-23 ([usr2 led] |beaglebone:green:usr) out hi gpio-24 ([usr3 led] |beaglebone:green:usr) out lo gpio-25 ([hdmi irq] ) gpio-26 ([usb vbus oc] ) gpio-27 ([hdmi audio] |enable ) out lo gpio-28 (P9_12 ) gpio-29 (P8_26 ) gpio-30 (P8_21 [emmc] ) gpio-31 (P8_20 [emmc] ) gpiochip1: 32 GPIOs, parent: platform/481ac000.gpio, gpio-32-63: gpio-0 (P9_15B |sysfs ) in hi gpio-1 (P8_18 ) gpio-2 (P8_7 ) gpio-3 (P8_8 ) gpio-4 (P8_10 ) gpio-5 (P8_9 ) gpio-6 (P8_45 [hdmi] ) gpio-7 (P8_46 [hdmi] ) gpio-8 (P8_43 [hdmi] ) gpio-9 (P8_44 [hdmi] ) gpio-10 (P8_41 [hdmi] ) gpio-11 (P8_42 [hdmi] ) gpio-12 (P8_39 [hdmi] ) gpio-13 (P8_40 [hdmi] ) gpio-14 (P8_37 [hdmi] ) gpio-15 (P8_38 [hdmi] ) gpio-16 (P8_36 [hdmi] ) gpio-17 (P8_34 [hdmi] ) gpio-18 ([rmii1_rxd3] ) gpio-19 ([rmii1_rxd2] ) gpio-20 ([rmii1_rxd1] ) gpio-21 ([rmii1_rxd0] ) gpio-22 (P8_27 [hdmi] ) gpio-23 (P8_29 [hdmi] ) gpio-24 (P8_28 [hdmi] ) gpio-25 (P8_30 [hdmi] ) gpio-26 ([mmc0_dat3] ) gpio-27 ([mmc0_dat2] ) gpio-28 ([mmc0_dat1] ) gpio-29 ([mmc0_dat0] ) gpio-30 ([mmc0_clk] ) gpio-31 ([mmc0_cmd] ) gpiochip2: 32 GPIOs, parent: platform/481ae000.gpio, gpio-64-95: gpio-0 ([mii col] ) gpio-1 ([mii crs] ) gpio-2 ([mii rx err] ) gpio-3 ([mii tx en] ) gpio-4 ([mii rx dv] ) gpio-5 ([i2c0 sda] ) gpio-6 ([i2c0 scl] ) gpio-7 ([jtag emu0] ) gpio-8 ([jtag emu1] ) gpio-9 ([mii tx clk] ) gpio-10 ([mii rx clk] ) gpio-11 (NC ) gpio-12 (NC ) gpio-13 ([usb vbus en] ) gpio-14 (P9_31 [spi1_sclk] ) gpio-15 (P9_29 [spi1_d0] ) gpio-16 (P9_30 [spi1_d1] ) gpio-17 (P9_28 [spi1_cs0] ) gpio-18 (P9_42B [ecappwm0] ) gpio-19 (P9_27 ) gpio-20 (P9_41A ) gpio-21 (P9_25 ) gpio-22 (NC ) gpio-23 (NC ) gpio-24 (NC ) gpio-25 (NC ) gpio-26 (NC ) gpio-27 (NC ) gpio-28 (NC ) gpio-29 (NC ) gpio-30 (NC ) gpio-31 (NC ) gpiochip3: 32 GPIOs, parent: platform/44e07000.gpio, gpio-96-127: gpio-0 ([mdio_data] ) gpio-1 ([mdio_clk] ) gpio-2 (P9_22 [spi0_sclk] ) gpio-3 (P9_21 [spi0_d0] ) gpio-4 (P9_18 [spi0_d1] ) gpio-5 (P9_17 [spi0_cs0] ) gpio-6 ([mmc0_cd] |cd ) in lo IRQ ACTIVE LOW gpio-7 (P9_42A [ecappwm0] ) gpio-8 (P8_35 [lcd d12] ) gpio-9 (P8_33 [lcd d13] ) gpio-10 (P8_31 [lcd d14] ) gpio-11 (P8_32 [lcd d15] ) gpio-12 (P9_20 [i2c2_sda] ) gpio-13 (P9_19 [i2c2_scl] ) gpio-14 (P9_26 [uart1_rxd] ) gpio-15 (P9_24 [uart1_txd] ) gpio-16 ([rmii1_txd3] ) gpio-17 ([rmii1_txd2] ) gpio-18 ([usb0_drvvbus] ) gpio-19 ([hdmi cec] ) gpio-20 (P9_41B ) gpio-21 ([rmii1_txd1] ) gpio-22 (P8_19 [ehrpwm2a] ) gpio-23 (P8_13 [ehrpwm2b] ) gpio-24 (NC ) gpio-25 (NC ) gpio-26 (P8_14 ) gpio-27 (P8_17 ) gpio-28 ([rmii1_txd0] ) gpio-29 ([rmii1_refclk] ) gpio-30 (P9_11 [uart4_rxd] ) gpio-31 (P9_13 [uart4_txd] )
这是因为两者的设备数(DTB)不一致导致的,在导出GPIO的时候需要使用EMMC的编号才可以。以P8_12为例,导入指令为
sudo echo 524 > /sys/class/gpio/export
需要注意的是文件导入后从新上电或重启不会保存该属性文件。导入成功后会出现gpio524文件夹的快捷方式。
2、GPIO属性文件结构
进入gpio524文件夹后查看文件内容

其中可以只关注direction和value两个文件。direction文件管理gpio的输入输出方向,写入in和out分别设置GPIO引脚为输入或输出方向。value为读取输入或设置输出电平的逻辑值。
3、测试GPIO引脚
文件导入后就可以进行测试了,首先是查看引脚的默认工作模式,通过查看direction文件就可以看出了。

可以看出引脚的默认工作模式为输入。可以通过杜邦线将对应的引脚与P9_1(GND)短接,然后查看value文件就可以读出对应的引脚电平逻辑值

通过杜邦线将对应的引脚与P9_3(VDD_3V3B)短接,查看对应的电平逻辑值为

然后是测试其输出功能,设置工作模式为输出模式的指令为
echo out > /sys/class/gpio/gpio524/direction
设置输出为高电平的指令为
echo 1 > /sys/class/gpio/gpio524/value

设置输出为低电平的指令为

四、开发环境搭建
除了指令控制之外最终的目的是通过代码进行控制。而让代码能够运行起来就需要有编译工具。BEAGLEBONE BLK REV C AM3358BZCZ的编译工具可以运行在Linux、Windows和Mac等操作系统,而板卡本身又是可以运行Linux操作系统的。测试外设资源的代码并不多,所以可以在板卡运行的Linux系统搭建开发环境。而我们烧写的系统本身并不带有编译代码的功能,需要联网在线安装或者导入离线安装包后离线安装。最简单的方式就是在线安装。由于板卡没有板载WiFi模块,本身也没有WiFi功能,所以需要通过网线让板卡联网。不过好在在连接上网线后不需要进行任何的配置就可以联网。运行如下指令就可以在线安装gcc,从而可以对C代码进行编译
sudo apt install -y gcc make g++ vim
安装成功后可以通过查看安装的软件版本检查安装是否成功,对应的指令为
gcc -v
打印出gcc的版本后就表示安装成功

不过在联网的状态下可以通过SSH进行远程控制,这样就不需要串口线进行指令控制。
五、代码控制
因为导入的属性文件再下一次上电后就不存在了,所以代码中要有检测属性文件是否存在,如果不存在就要导入。测试的逻辑是设置引脚为输出模式,输出高电平保持两秒,低电平也保持两秒,依次循环。对应流程图如下

对应的代码如下
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
// 你要控制的 GPIO 编号
#define GPIO_NUM 524
// GPIO 路径定义
#define GPIO_PATH "/sys/class/gpio/gpio"
#define EXPORT "/sys/class/gpio/export"
#define UNEXPORT "/sys/class/gpio/unexport"
// 拼接文件路径工具函数
void make_path(char *path, const char *prefix, int num, const char *suffix) {
sprintf(path, "%s%d%s", prefix, num, suffix);
}
// 判断文件/文件夹是否存在
int file_exists(const char *path) {
struct stat buffer;
return (stat(path, &buffer) == 0);
}
// 导出 GPIO
int gpio_export(int num) {
char buf[4];
int fd = open(EXPORT, O_WRONLY);
if (fd < 0) {
perror("export open failed");
return -1;
}
sprintf(buf, "%d", num);
write(fd, buf, strlen(buf));
close(fd);
return 0;
}
// 设置方向 out
int gpio_set_direction(int num, const char *dir) {
char path[64];
make_path(path, GPIO_PATH, num, "/direction");
int fd = open(path, O_WRONLY);
if (fd < 0) {
perror("direction open failed");
return -1;
}
write(fd, dir, strlen(dir));
close(fd);
return 0;
}
// 设置电平 1/0
int gpio_set_value(int num, int val) {
char path[64];
make_path(path, GPIO_PATH, num, "/value");
int fd = open(path, O_WRONLY);
if (fd < 0) {
perror("value open failed");
return -1;
}
char v = val ? '1' : '0';
write(fd, &v, 1);
close(fd);
return 0;
}
int main() {
char gpio_dir[64];
make_path(gpio_dir, GPIO_PATH, GPIO_NUM, "/");
// ======================
// 1. 判断 GPIO 是否已经导出
// ======================
if (!file_exists(gpio_dir)) {
printf("GPIO%d 未导出,正在导出...\n", GPIO_NUM);
gpio_export(GPIO_NUM);
sleep(1); // 等待内核创建文件
} else {
printf("GPIO%d 已存在,跳过导出\n", GPIO_NUM);
}
// ======================
// 2. 设置为输出模式
// ======================
gpio_set_direction(GPIO_NUM, "out");
printf("已设置为输出模式\n");
// ======================
// 3. 循环高低电平(无限轮询)
// ======================
printf("开始轮询:高2秒 → 低2秒 → 循环...\n");
while (1) {
gpio_set_value(GPIO_NUM, 1);
printf("→ 高电平\n");
sleep(2);
gpio_set_value(GPIO_NUM, 0);
printf("→ 低电平\n");
sleep(2);
}
return 0;
}将以上的代码复制到用户目录下,这里命名为gpio524_test.c。输入如下指令进行编译
gcc gpio524_test.c -o gpio524_test
编译成功后会有一个名为gpio524_test的执行文件,如果有执行权限可以直接运行。运行命令为
./gpio524_test
程序在执行过程中会有提示。
我要赚赏金
