IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> NanoPi-K2 控制GPIO -> 正文阅读

[嵌入式]NanoPi-K2 控制GPIO

前言

网上关于NanoPi-K2这块板子的资料少之又少,多方收集资料加试验后,终于摸索出来了通过内核函数控制板子的GPIO的方法,由于本人纯萌新,错漏之处还望海涵~~
参考文章:三种方式控制NanoPi2的GPIO

定位GPIO位号

函数介绍

首先介绍一下主要用到的内核函数:

//gpio为要申请的管脚  label为管脚名称
gpio_request(unsigned gpio, const char *label);
//gpio为要申请的管脚,value可以是0或1,用于在指定管脚写0或1,并将该端口设为输出模式
gpio_direction_output(unsigned gpio,int value);
//gpio为要申请的管脚,value可以是0或1,用于控制管脚的输出电平
gpio_set_value(unsigned int gpio, int value);

板子管脚定义

函数我们知道了,关键是如何确定gpio的值呢,直接写GPIOY0?,那是不行的,先来看看开发板的管脚定义:
在这里插入图片描述
在这里插入图片描述
管脚分布及对应开发板上的位置如图所示

确定管脚位号

本例程中,我使用GPIOY0来演示如何控制LED灯闪烁

1.进入开发板终端,输入:

fa@NanoPi-K2:~$
fa@NanoPi-K2:~$ su
Password:
root@NanoPi-K2:/home/fa#

在root下运行

2.输入下面指令定位到GPIO所在的文件

root@NanoPi-K2:/home/fa# cd /sys/class/gpio
root@NanoPi-K2:/sys/class/gpio# ls
export  gpiochip122  gpiochip136  unexport

这里可以看到gpio分了两个块gpiochip122gpiochip136,但这样还是没有办法明白怎么控制GPIOY0啊,还有其他管脚也不清楚。作为一个萌新,我猜设备树中可能有相关代码。
先从

http://wiki.friendlyarm.com/wiki/index.php/NanoPi_K2/zh#

官方第5.3.1章节中下载内核源码到本地,根据主控的名称厂家找到设备树所在的文件路径:

linux-nanopi-k2-3.14.y\arch\arm64\boot\dts\amlogic\nanopi-k2.dts

打开后观察引用的头文件有这么几行:

#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/gxbb.h>
#include <dt-bindings/gpio/gxbb.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/reset/aml_gxbb.h>
#include "mesongxbb.dtsi"

注意gpio关键字,在内核源码中找到头文件,路径如下:

linux-nanopi-k2-3.14.y\include\dt-bindings\gpio\

打开路径下的 gxbb.h头文件:

#ifndef __ARCH_GXBB_GPIO_H__
#define __ARCH_GXBB_GPIO_H__
/*AO Bank*/
#define	GPIOAO_0    0
#define	GPIOAO_1    1
#define	GPIOAO_2    2
#define	GPIOAO_3    3
#define	GPIOAO_4    4
#define	GPIOAO_5    5
#define	GPIOAO_6    6
#define	GPIOAO_7    7
#define	GPIOAO_8    8
#define	GPIOAO_9    9
#define	GPIOAO_10    10
#define	GPIOAO_11    11
#define	GPIOAO_12    12
#define	GPIOAO_13    13

/*EE Bank*/
#define	GPIOZ_0    0
#define	GPIOZ_1    1
#define	GPIOZ_2    2
#define	GPIOZ_3    3
#define	GPIOZ_4    4
#define	GPIOZ_5    5
#define	GPIOZ_6    6
#define	GPIOZ_7    7
#define	GPIOZ_8    8
#define	GPIOZ_9    9
#define	GPIOZ_10    10
#define	GPIOZ_11    11
#define	GPIOZ_12    12
#define	GPIOZ_13    13
#define	GPIOZ_14    14
#define	GPIOZ_15    15
#define	GPIOH_0    16
#define	GPIOH_1    17
#define	GPIOH_2    18
#define	GPIOH_3    19
#define	BOOT_0    20
#define	BOOT_1    21
#define	BOOT_2    22
#define	BOOT_3    23
#define	BOOT_4    24
#define	BOOT_5    25
#define	BOOT_6    26
#define	BOOT_7    27
#define	BOOT_8    28
#define	BOOT_9    29
#define	BOOT_10    30
#define	BOOT_11    31
#define	BOOT_12    32
#define	BOOT_13    33
#define	BOOT_14    34
#define	BOOT_15    35
#define	BOOT_16    36
#define	BOOT_17    37
#define	CARD_0    38
#define	CARD_1    39
#define	CARD_2    40
#define	CARD_3    41
#define	CARD_4    42
#define	CARD_5    43
#define	CARD_6    44
#define	GPIODV_0    45
#define	GPIODV_1    46
#define	GPIODV_2    47
#define	GPIODV_3    48
#define	GPIODV_4    49
#define	GPIODV_5    50
#define	GPIODV_6    51
#define	GPIODV_7    52
#define	GPIODV_8    53
#define	GPIODV_9    54
#define	GPIODV_10    55
#define	GPIODV_11    56
#define	GPIODV_12    57
#define	GPIODV_13    58
#define	GPIODV_14    59
#define	GPIODV_15    60
#define	GPIODV_16    61
#define	GPIODV_17    62
#define	GPIODV_18    63
#define	GPIODV_19    64
#define	GPIODV_20    65
#define	GPIODV_21    66
#define	GPIODV_22    67
#define	GPIODV_23    68
#define	GPIODV_24    69
#define	GPIODV_25    70
#define	GPIODV_26    71
#define	GPIODV_27    72
#define	GPIODV_28    73
#define	GPIODV_29    74
#define	GPIOY_0    75
#define	GPIOY_1    76
#define	GPIOY_2    77
#define	GPIOY_3    78
#define	GPIOY_4    79
#define	GPIOY_5    80
#define	GPIOY_6    81
#define	GPIOY_7    82
#define	GPIOY_8    83
#define	GPIOY_9    84
#define	GPIOY_10    85
#define	GPIOY_11    86
#define	GPIOY_12    87
#define	GPIOY_13    88
#define	GPIOY_14    89
#define	GPIOY_15    90
#define	GPIOY_16    91
#define	GPIOX_0    92
#define	GPIOX_1    93
#define	GPIOX_2    94
#define	GPIOX_3    95
#define	GPIOX_4    96
#define	GPIOX_5    97
#define	GPIOX_6    98
#define	GPIOX_7    99
#define	GPIOX_8    100
#define	GPIOX_9    101
#define	GPIOX_10    102
#define	GPIOX_11    103
#define	GPIOX_12    104
#define	GPIOX_13    105
#define	GPIOX_14    106
#define	GPIOX_15    107
#define	GPIOX_16    108
#define	GPIOX_17    109
#define	GPIOX_18    110
#define	GPIOX_19    111
#define	GPIOX_20    112
#define	GPIOX_21    113
#define	GPIOX_22    114
#define	GPIOCLK_0    115
#define	GPIOCLK_1    116
#define	GPIOCLK_2    117
#define	GPIOCLK_3    118
#define	GPIO_TEST_N    119


/*AO REG */
#define AO 0x10
#define AO2 0x11
#endif

可以看到分为两个块AO BankEE Bank
经过实验可以试出AO Bank起始地址为gpiochip122
EE Bank起始地址为gpiochip136
验证方法如下:
将GPIOY_0通过杜邦线连接到LED正极,LED负极连接到开发板GND管脚(6、14、20、30、34都可以)
记下头文件中GPIOY_0的偏移量为75
因此实际地址为 EE Bank基地址加上偏移量75
136+75=211
回到终端,输入:

root@NanoPi-K2:/sys/class/gpio# echo 211 > /sys/class/gpio/export
root@NanoPi-K2:/sys/class/gpio# ls
export  gpio211  gpiochip122  gpiochip136  unexport

可以看到导出了一个引脚gpio211
接下来进入该GPIO并设置GPIO方向:

root@NanoPi-K2:/sys/class/gpio# cd gpio211
root@NanoPi-K2:/sys/class/gpio/gpio211# echo out > direction

将管脚设置为输出
然后可以操控该管脚的电平了,输出高电平点亮LED:

root@NanoPi-K2:/sys/class/gpio/gpio211# echo 1 > /sys/class/gpio/gpio211/value

输出低电平关闭LED:

root@NanoPi-K2:/sys/class/gpio/gpio211# echo 0 > /sys/class/gpio/gpio211/value

测试结束,管脚位置确定完毕,不放心的话还有那么多GPIOY可以尝试,这里就不做测试了。
之后记得清除导出的管脚,输入:

root@NanoPi-K2:/sys/class/gpio/gpio211# echo 211 > /sys/class/gpio/unexport

然后就是代码中该如何控制GPIO了

编写及编译 .KO 驱动文件

开发环境搭建

要编译驱动文件,需要相应的编译环境及内源码支持,参考

http://wiki.friendlyarm.com/wiki/index.php/NanoPi_K2/zh#
第5.1章节安装AArch64交叉编译器小节
第5.3.1章节编译Ubuntu内核小节

注意以上操作均要在64位Linux系统下进行,git拉取不方便的话可以下载K2板子分支的ZIP文件,不要在Windows环境下解压,可能导致大小写命名的文件合并导致内核文件缺损,发送到linux系统中再进行解压及后续操作。
环境搭建完成后即可进行驱动编写。

驱动编写

新建一个文件,命名为ledTest.c
代码如下:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/cdev.h>
#include <linux/delay.h>
#include <linux/compat.h>

#include <linux/spi/spi.h>
#include <linux/spi/spidev.h>

#define OUTPUT  1
#define INPUT   0
#define HIGH    1
#define LOW     0

#define DEVICE_NAME "LED"//该名称在编写APP时要用到
#define SET_VALUE   1
#define GPIOY_BASE  136//基地址
unsigned int GPIOY0 = GPIOY_BASE+75;//加上头文件中偏移量得到实际地址

static int gpio_open(struct inode *inode,struct file *file)
{
    gpio_request(GPIOY0,"test");
    gpio_direction_output(GPIOY0, 0);//方向为输出,初始值低电平
    printk("Open:gpio_set_value LOW\n");
    gpio_set_value(GPIOY0, LOW);
    printk("request GPIOY0\n");
    return 0;
}
static int gpio_close(struct inode *inode,struct file *file)
{
    printk("close:gpio_set_value LOW\n");
    gpio_set_value(GPIOY0, LOW);
    gpio_free(GPIOY0);
    return 0;
}
static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    if(cmd == SET_VALUE)
    {
        if(arg == HIGH)
        {
            gpio_set_value(GPIOY0,HIGH);
            printk("gpio_set_value HIGH\n");
        }
        else if(arg == LOW)
        {
            gpio_set_value(GPIOY0,LOW);
            printk("gpio_set_value LOW\n");
        }
        
    }
    return -EMSGSIZE;
}
static struct file_operations gpio_fops =
{
    .owner = THIS_MODULE,
    .open = gpio_open,
    .release = gpio_close,
    .unlocked_ioctl = gpio_ioctl,
};
static struct miscdevice gpio_dev =
{
    .minor = MISC_DYNAMIC_MINOR,
    .name = DEVICE_NAME,
    .fops = & gpio_fops,
}; 
volatile unsigned * GPIOYOUT;
static int gpio_init(void)
{
    int ret = 0;
    printk("init\n");
    ret = misc_register(&gpio_dev);
    return ret;
}
static void gpio_exit(void)
{
    misc_deregister(&gpio_dev);
    printk("exit\n");
}
module_init(gpio_init);
module_exit(gpio_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("YQY");

接下来保存并开始编写Makefile

obj-m:=ledTest.o
mymodule-objs:=ledTest
KDIR:=/home/yan/linux/NanoPi/Kernal/linux-nanopi-k2-3.14.y
MAKE:=make
# EXTRA_CFLAGS += -I$(KDIR)arch/arm/mach-s5p4418/prototype/module
default:
	$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) clean

第三行的地址填你自己保存的编译后的内核所在的地址
保存后,在该文件夹下编译驱动即可:

yan@yan-virtual-machine:~/linux/NanoPi/TestMod/led$ make
make -C /home/yan/linux/NanoPi/Kernal/linux-nanopi-k2-3.14.y M=/home/yan/linux/NanoPi/TestMod/led modules
make[1]: Entering directory '/home/yan/linux/NanoPi/Kernal/linux-nanopi-k2-3.14.y'
  Building modules, stage 2.
  MODPOST 1 modules
make[1]: Leaving directory '/home/yan/linux/NanoPi/Kernal/linux-nanopi-k2-3.14.y'

该目录下生成了驱动文件ledTest.ko

驱动加载

将其拷贝到开发板中即可,文件夹自己定,记得给文件赋予读写权限,简单粗暴就

root@NanoPi-K2:/home/fa/dri# chmod 777 ledTest.ko

下面加载驱动,输入:

root@NanoPi-K2:/home/fa/dri# insmod ledTest.ko

检查 /dev/ 目录下,会发现多出一个名称为 LED 的文件,驱动挂载成功

编写及编译APP文件

新建 ledApp.c 文件,源码如下:

#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#define HIGH    1
#define LOW     0

#define SET_VALUE 1

int main()
{
    int fd = open("/dev/LED",O_RDWR);//和上一章最后提到的文件有关
    if(fd <0)
    {
        printf("File open filed!\r\n");
    }
    int i;
    for(i=0;i<3;i++)
    {
        ioctl(fd,SET_VALUE,HIGH);
        usleep(100000);
        ioctl(fd,SET_VALUE,LOW);
        usleep(100000);
    }
    close(fd);
    return 0;
}

保存后编译文件:

yan@yan-virtual-machine:~/linux/NanoPi/TestMod/led.c$ aarch64-linux-gnu-gcc -o ledApp ledApp.c

文件夹下会多出一个ledApp文件,这就是需要的应用文件,拷贝到开发板中,并赋予读写权限:

root@NanoPi-K2:/home/fa# chmod 777 ledApp

运行程序:

root@NanoPi-K2:/home/fa# ./ledApp

即可看到KED快闪3下

第一次写博客,希望各位看官满意哦~~ (^ ^)

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-09-12 13:19:13  更:2021-09-12 13:19:34 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/18 14:29:20-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码