i.MX8MM处理器采用了先进的14LPCFinFET工艺,提供更快的速度和更高的电源效率;四核Cortex-A53,单核Cortex-M4,多达五个内核 ,主频高达1.8GHz,2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT、4G模块、CAN、RS485等接口一应俱全。H264、VP8视频硬编码,H.264、H.265、VP8、VP9视频硬解码,并提供相关历程,支持8路PDM接口、5路SAI接口、2路Speaker。系统支持Android9.0(支持获取root限)Linux4.14.78+Qt5.10.1、Yocto、Ubuntu20、Debian9系统。适用于智能充电桩,物联网,工业控制,医疗,智能交通等,可用于任何通用工业和物联网应用、
【公众号】迅为电子
【粉丝群】258811263(加群获取驱动文档+例程)
第三十章 控制GPIO高低电平
我们学 linux 、单片机的第一个操作硬件就是点亮第一个led灯,也就是控制GPIO的高低电平。在单片机上我们控制一个GPIO非常的简单,直接操作引脚就可以了。虽然linux听着比较高大上,但是控制一个GPIO是非常容易的。我们甚至不用去写驱动,直接命令操作就可以了,因为linux系统本身有好多成熟的驱动框架,使用这些框架的好处就是当我们更换平台的时候,比如换到iTOP-iMX8MM平台,我们应用程序可以几乎不用做任何改变,就可以直接在新的平台上运行。但是比如说我在stm32单片机上写了一个控制GPIO的程序,我现在想把它移植到51单片机的话,这个移植过程是比较麻烦的,但是在linux上对于GPIO设备,甚至可以不用写程序,可以直接在命令行操作。
30.1 前置知识
- echo > 重定向命令
举例:
echo hello > test.txt
将字符串输出重定向,当前目录没有 test.txt,则创建 text.txt ,并将字符串输出到 test.txt 文件中。和直接使用vi编辑器打开 test.txt然后输入hello 的效果是一样的。如下图所示。
30.2 使用命令控制GPIO
在文件系统的/sys目录下给用户提供了许多接口,比如在/sys下面的bus目录,这个目录下放置的都是和总线相关的,比如I2C,usb等。如下图所示:
本章我们需要重点关注下class目录,这个目录下放置的是一些按照类型归类的设备,比如led灯就可以归类到/sys/class/gpio下面。如下图所示:
其中,/sys/class/gpio/sys/class/gpio/export 用于通知系统需要导出控制的 GPIO 引脚编号
/sys/class/gpio/unexport 用于通知系统取消导出。 export 和 unexport,他们都是只写的。
/sys/class/gpio/gpiochipX (X为0,1,2.....)目录下保存系统中 GPIO 寄存器的信息,包括每个寄存器控制引脚的起始编号base, 寄存器名称, 引脚总数。比如我们进入到 gpiochip32,如下图所示
30.3 控制一个gpio
以GPIO1_IO09为例,这个管脚在i.MX8MM开发板J19座子上,如下图所示:
1 在imx8MM中,GPIO_number 的计算方法为: 32*(n-1) +m, 字母 n 的含义为哪个 GPIO, 字母 m 为该 GPIO 的第几个 io 口。 所以此GPIO_number=32*(1-1)+9=9
2 向/sys/class/gpio/export 写入此编号, 比如引脚编号是 9,也就是GPIO1_IO09管脚。 在 shell 中可以通过以下命令实现, 命令成功后生成/sys/class/gpio/gpio9 目录, 如果没有出现相应的目录, 说明此引脚不可导出:
echo 9 > /sys/class/gpio/export
如下图所示:
在这一步可能会遇到以下错误:
sh: write error: Device or resource busy
出现这个问题的原因是你将要使用的这个 gpio 口之前已经申请过了,包括内核申请或者使用上述方法申请过。需要在内核里面找到是哪个驱动使用了这个管脚,然后去掉他。
3 定义输入输出方向,使用cd命令,先进到我们在步骤2中导出的gpio9的目录中,如下图所示:
我们设置direction 来设置这个gpio方向。
注意: direction 接受的参数: in(输入) , out(输出) , high, low。 high/low 同时设置方向为输出, 并将 value设置为相应的 1(高电平) 或 0(低电平) 。
如果我们把它设置成输出,命令如下: echo out > direction
如下图所示:
- 设置高低电平,如果我们要把这个管脚设置成高电平,我们只需要给value设置成1即可,反之,则设置成0。
把GPIO1_IO09设置成高电平,使用命令echo 1 > value
反之,把GPIO1_IO09设置成高电平,使用命令echo 0 > value
30.4 使用c语言调用shell命令控制GPIO
我们也可以让程序帮我们输入这些命令,可以使用system 函数来完成。
头文件:#include <stdio.h>
格式:system(要执行的命令)
我们在ubuntu虚拟机的任意目录下,创建一个名为gpio.c的文件,在里面写入以下代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void main(void)
{
system(“echo 9 > /sys/class/gpio/export”);//导出GPIO
system(“echo out > /sys/class/gpio/gpio9/direction”);//设置GPIO方向为输出
while(1)
{
system(“echo 1 > /sys/class/gpio/gpio9/value”);//置1
sleep(5);
system(“echo 0 > /sys/class/gpio/gpio9/value”);//置0
sleep(5);
}
}
我们直接使用交叉编译器编译下刚才我们写的这个gpio.c ,因为是在开发板上运行的,所以就不能使用gcc了。我们使用静态编译,这样就得到了gpio这个可执行的程序。编译方法参考本手册“交叉编译器的安装和使用”章节。
把这个gpio可执行文件拷贝到开发板,我们可以使用U盘或者TF卡也可以使用NFS ,这个依据自己的习惯来就可以了。
我们来运行下这个可执行文件,如下图所示。
我们可以用电笔来测一下这个GPIO,会发现这个GPIO的电平每隔5S翻转一次。其实这个程序里面的方法和我们直接使用命令的方法是一样的,只不过我们是使用c语言来调用我们的shell命令来实现,就不用再人为地输入了。