基于i.MX6平台GPIO引脚控制

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Tiger99111/article/details/80940953

系统平台:

芯片平台:Freescale i.MX6Q/6DL
OS版本:Android 7.1.2(Linux 4.9.17)

一、内核中使用GPIO

  1. 修改内核,dtsi中导出GPIO,以下导出了两个GPIO,GPIO3_IO29, GPIO07_IO04。
  2. 在内核代码中添加linux/gpio.h头文件,导入GPIO相关操作方法。
  3. 使用GPIO相关操作方法,设置GPIO方法,触发方法,设置相关值等。
    以下在last.c中测试将GPIO设置成输出模式,并拉高电平。
From 3aa4328884f1bed27f566352ae2e299bd0834561 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E4=BD=95=E5=AE=9D=E8=99=8E?= <baohuhe@szsoling.com>
Date: Fri, 6 Jul 2018 13:27:22 +0800
Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0GPIO=E5=BC=95=E8=84=9A?=
 =?UTF-8?q?=E6=B5=8B=E8=AF=95=E4=BB=A3=E7=A0=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 arch/arm/boot/dts/imx6qdl-sabresd.dtsi | 4 +++-
 sound/last.c | 14 ++++++++++++++
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
index f8cbc25..c6b848f 100755
--- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
@@ -816,6 +816,8 @@ tsc@24 {
     MX6QDL_PAD_NANDF_CS3__GPIO6_IO16 0x80000000
     MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x1b0b0
     MX6QDL_PAD_EIM_D28__GPIO3_IO28 0x13059
+    MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x80000000
+    MX6QDL_PAD_SD3_DAT0__GPIO7_IO04 0x80000000
     MX6QDL_PAD_NANDF_CLE__GPIO6_IO07 0x13069
     MX6QDL_PAD_NANDF_WP_B__GPIO6_IO09 0x13069
     MX6QDL_PAD_NANDF_CS2__CCM_CLKO2 0x130b0
@@ -887,7 +889,7 @@ tsc@24 {

   pinctrl_gpio_keys: gpio_keysgrp {
    fsl,pins = <
-   MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x1b0b0
+   /*MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x1b0b0*/
     /*MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1b0b0*/
     MX6QDL_PAD_GPIO_5__GPIO1_IO05 0x1b0b0
    >;
diff --git a/sound/last.c b/sound/last.c
index 43f2228..52f4f21 100644
--- a/sound/last.c
+++ b/sound/last.c
@@ -21,6 +21,7 @@

 #include <linux/init.h>
 #include <sound/core.h>
+#include <linux/gpio.h>

 static int __init alsa_sound_last_init(void)
 {
@@ -34,6 +35,19 @@ static int __init alsa_sound_last_init(void)
   }
  if (ok == 0)
   printk(KERN_INFO " No soundcards found.\n");
+#if 1
+   int ret = 0;
+ ret = gpio_request(93, NULL);
+ if(!ret)
+ ret = gpio_direction_output(93, 0);
+ if(unlikely(ret))
+ {
+   printk("gpio(93) direction output fail\n\n\n");
+ gpio_free(93);
+ return 0;
+ }
+ printk("gpio_direction_output 93 OK\n\n\n");
+#endif
  return 0;
 }

-- 
1.9.1

以上代码运行时,实际测量GPIO93电平被拉低。

二、在文件系统中控制GPIO

GPIO用户太控制接口
linux内核提供了一套在用户态配置GPIO的接口,在/sys/class/gpio/目录下:
可以发现其中包含有两个文件export、unexport和若干gpiochipN 类型文件夹

  • export:
    用于将指定编号的引脚导出,作为GPIO使用
  • unexport:
    用于将导出的GPIO删除掉
  • gpiochipN:
    当前芯片中包含的GPIO控制器
  • direction:
    设置输出还是输入模式
    • 设置为输入:echo “in” > direction
    • 设置为输出:echo “out” > direction
  • value
    输出时,控制高低电平;输入时,获取高低电平
    • 高电平:echo 1 > value
    • 低电平:echo 0 > value
  • edge
    控制中断触发模式,引脚被配置为中断后可以使用poll()函数监听引脚
    • 非中断引脚: echo “none” > edge
    • 上升沿触发:echo “rising” > edge
    • 下降沿触发:echo “falling” > edge
    • 边沿触发:echo “both” > edge
  • gpiochipN目录
    用来管理和控制一组gpio端口的控制器
    • base
      和N相同,表示控制器管理的最小的端口编号。
    • lable
      诊断使用的标志(并不总是唯一的)
    • ngpio
      控制器管理的gpio端口数量(端口范围是:N ~ N+ngpio-1)

使用方法示例

  • 添加设备接口GPIO196
    echo 196 > export
    可以发现,目录下出现了GPIO196,如果执行命令后没有反应,表示当前的GPIO已经用作其他的功能,例如作为IIC的引脚等。
    另外在测试中发现,如上面内核中所示,我们在使用中使用了93脚,此时我们echo 93 > export无法将93脚正常导出。
  • 设置GPIO196为输出
    echo out > gpio196/direction
  • 删除当前导出的GPIO196
    echo 196 > unexport

三、应用程序中操作GPIO

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include "gpio_control.h"

#define BUFFER_MAX 100
#define DIRECTION_MAX 100
#define IN 0
#define OUT 1
#define LOW 0
#define HIGH 1
#define POUT 196

int gpio_export(int pin);
int gpio_unexport(int pin);
int gpio_direction(int pin, int dir);
int gpio_write(int pin, int value);
int gpio_read(int pin);

int main(int argc, char *argv[)
{
 int i = 0;  
 gpio_export(POUT);  
 gpio_direction(POUT, OUT);  
 gpio_write(POUT, 1);  
 for (i = 0; i < 20; i++) {  
    gpio_write(POUT, i % 2);  
    usleep(500 * 1000);  
 }  
 gpio_unexport(POUT);  
 return 0;
}
int gpio_export(int pin)  
{  
 char buffer[BUFFER_MAX];  
 int len;  
 int fd;  

 fd = open("/sys/class/gpio/export", O_WRONLY);  
 if (fd < 0) {  
  fprintf(stderr, "Failed to open export for writing!\n");  
  return(-1);  
 }  

 len = snprintf(buffer, BUFFER_MAX, "%d", pin);  
 if (write(fd, buffer, len) < 0) {  
  fprintf(stderr, "Fail to export gpio!");  
  return -1;  
 }  
 close(fd);  
 return 0;  
}  

int gpio_unexport(int pin)  
{  
 char buffer[BUFFER_MAX];  
 int len;  
 int fd;  

 fd = open("/sys/class/gpio/unexport", O_WRONLY);  
 if (fd < 0) {  
  fprintf(stderr, "Failed to open unexport for writing!\n");  
  return -1;  
 }  

 len = snprintf(buffer, BUFFER_MAX, "%d", pin);  
 if (write(fd, buffer, len) < 0) {  
  fprintf(stderr, "Fail to unexport gpio!");  
  return -1;  
 }  

 close(fd);  
 return 0;  
}  

int gpio_direction(int pin, int dir)
{
 static const char dir_str[] = "in\0out";
 char path[DIRECTION_MAX];
 int fd;

 snprintf(path, DIRECTION_MAX, "/sys/class/gpio/gpio%d/direction", pin);
 fd = open(path, O_WRONLY);
 if (fd < 0) {
  fprintf(stderr, "failed to open gpio direction for writing!\n");
  return -1;
 }

 if (write(fd, &dir_str[dir == IN ? 0 : 3], dir == IN ? 2 : 3) < 0) {
  fprintf(stderr, "failed to set direction!\n");
  return -1;
 }

 close(fd);
 return 0;
}

int gpio_write(int pin, int value)  
{  
 static const char values_str[] = "01";  
 char path[DIRECTION_MAX];  
 int fd;  

 snprintf(path, DIRECTION_MAX, "/sys/class/gpio/gpio%d/value", pin);  
 fd = open(path, O_WRONLY);  
 if (fd < 0) {  
  fprintf(stderr, "failed to open gpio value for writing!\n");  
  return -1;  
 }  

 if (write(fd, &values_str[value == LOW ? 0 : 1], 1) < 0) {  
  fprintf(stderr, "failed to write value!\n");  
  return -1;  
 }  

 close(fd);  
 return 0;  
}  

int gpio_read(int pin)  
{  
 char path[DIRECTION_MAX];  
 char value_str[3];  
 int fd;  

 snprintf(path, DIRECTION_MAX, "/sys/class/gpio/gpio%d/value", pin);  
 fd = open(path, O_RDONLY);  
 if (fd < 0) {  
  fprintf(stderr, "failed to open gpio value for reading!\n");  
  return -1;  
 }  

 if (read(fd, value_str, 3) < 0) {  
  fprintf(stderr, "failed to read value!\n");  
  return -1;  
 }  

 close(fd);  
 return (atoi(value_str));  
}  

以上可实现规律的拉高拉低GPIO196引脚

阅读更多

扫码向博主提问

麦嘞个田

非学,无以致疑;非问,无以广识
  • 擅长领域:
  • 车载导航
  • 嵌入式
去开通我的Chat快问
换一批

没有更多推荐了,返回首页