一、硬件说明:
主板上J2306 插座是5个可编程GPIO
序号 | IO说明 | 对应操作地址 | libgpiod控制IO编号 |
---|---|---|---|
1 | GPIO-H19 | 0xFD6D0730 | 179 |
2 | GPIO-H18 | 0xFD6D0720 | 178 |
3 | GPIO-H17 | 0xFD6D0710 | 177 |
4 | GPIO-H16 | 0xFD6D0700 | 176 |
5 | GPIO-H00 | 0xFD6D0600 | 160 |
6 | GND | 无 | 无 |
二、测试软件(内核映射驱动方式)下载:
linux GPIO 测试软件源码下载:
linux-gpio-test-src-File
三、测试软件(内核映射驱动方式)编译和测试:
下载测试软件源码,解压后,linux-gpio目录如图:
源码目录结构说明:
文件/文件夹 | 说明 |
---|---|
drv文件夹 | gpio内核映射驱动 |
IOApp.h | gpio应用接口头文件 |
IOApp.cpp | gpio应用接口源文件 |
test_gpio.cpp | 测试代码main |
Makefile | make编译脚本文件 |
Readme.txt | 编译流程说明文件 |
编译和运行流程如下,下面开始目录是linux-gpio
进行编译操作前,需要先安装基本的编译工具,安装方法请参考"Linux应用程序开发(调用硬件)"说明.
#进入gpio驱动源码目录
user@X1:~/linux-gpio$ cd drv
#编译gpio驱动
user@X1:~/linux-gpio/drv$ make
#返回上一级目录
user@X1:~/linux-gpio/drv$ cd ..
#复制驱动ko到当前目录
user@X1:~/linux-gpio$ cp drv/gpio_drv.ko ./
#编译gpio测试应用程序
user@X1:~/linux-gpio$ make
#执行程序程序
user@X1:~/linux-gpio$ sudo ./test_gpio
以上操作,若没有错误,显示测试结果如下:
$ sudo ./test_gpio
GPIO输出成功,LED控制成功,GPIO-H19输入电平:84000102
特别提醒:因为是控制硬件,需要sudo 来运行测试程序.若是root 账号可以直接运行.
三、gpio应用接口(内核映射驱动方式)说明:
3.1以下是IOApp.h文件结构说明
#ifndef _IOAPP_H
#define _IOAPP_H
#include <stdint.h>
//5个IO控制地址
#define GPIO_H19_ADR 0xFD6D0730
#define GPIO_H18_ADR 0xFD6D0720
#define GPIO_H17_ADR 0xFD6D0710
#define GPIO_H16_ADR 0xFD6D0700
#define GPIO_H00_ADR 0xFD6D0600
//使用前,需要动态加载驱动:加载模块方式1:(仅加载本模块)
//命令行 chmod 644 gpio_drv.ko
//命令行 insmod gpio_drv.ko
class IOApp
{
//驱动
int fd;
public:
IOApp();
~IOApp();
//连接gpio内核驱动
bool Open();
//释放gpio内核驱动
void Release();
public:
//gpio 输出高低电平
bool Gpio_Out(uint32_t PhysAddr,bool HightLevel);
//gpio 输入电平:若值为0X84000102表示高电平,若值为0X84000100表示低电平
bool Gpio_In(uint32_t PhysAddr,uint32_t *lpVal);
//设置gpio为输出模式
bool Gpio_SetModel_OutPut(uint32_t PhysAddr);
//设置gpio为输入模式
bool Gpio_SetModel_InPut(uint32_t PhysAddr);
//设置gpio为中断模式,尚未实现.
bool Gpio_SetModel_Interrupt(uint32_t PhysAddr);
//以下是LED控制----
//控制红色LED亮灭
bool Led_Ctrl_Red(bool isOn);
//控制红色LED闪烁
bool Led_Ctrl_Red_Flash(bool isOn);
//控制绿色LED亮灭
bool Led_Ctrl_Green(bool isOn);
//控制绿色LED闪烁
bool Led_Ctrl_Green_Flash(bool isOn);
};
#endif
3.2IO输入输出说明:
IO口有输入模式和输出模式
IO口设置为输出模式后,输出的高低电平才是正确的,此模式下读取的IO值是随机的。
IO口设置为输入模式后,读取的值:
若读出值为0X84000102表示高电平,若值为0X84000100表示低电平
若读取出其他值,可能IO不是在输入模式下。
四、GPIO 其他控制方式说明(根据实际情况,参考使用):
4.1 GPIO sysfs接口 (kernel 4.8开始 已经默认禁用,官方也不推荐使用)
在Linux中,最常见的读写GPIO方式就是用GPIO sysfs interface, 是通过操作 /sys/class/gpio 目录下的 export 、 unexport 、gpio{N}/direction, gpio{N} /value (用实际引脚号替代{N})等文件实现的,经常出现shell脚本里面。 在kernel 4.8开始,加入了libgpiod的支持;而原有基于sysfs的访问方式,将被逐渐放弃。
4.2使用libgpiod 库控制IO
libgpiod是一种字符设备接口,GPIO访问控制是通过操作字符设备文件(比如 /dev/gpiodchip0 )实现的, 并通过libgpiod提供一些命令工具、c库以及python封装。
4.2.1 想要使用libgpiod,需要在开发板上安装libgpiod库。
#安装libgpiod库及头文件
sudo apt -y install libgpiod-dev
#安装gpiod 命令行工具
sudo apt -y install gpiod
以上命令安装是libgpiod1.6.3版本.
4.2.2 libgpiod控制方式,板子上的GPIO对应编号如下
序号 | IO说明 | libgpiod控制IO编号 |
---|---|---|
1 | GPIO-H19 | 179 |
2 | GPIO-H18 | 178 |
3 | GPIO-H17 | 177 |
4 | GPIO-H16 | 176 |
5 | GPIO-H00 | 160 |
4.2.3 gpiod命令行控制
常用的命令行如下,可使用 -h 查看命令相对应的使用说明
命令 | 作用 | 使用举例(179 是GPIO-H19编号) | 说明 |
---|---|---|---|
gpiodetect | 列出所有的GPIO控制器 | sudo gpiodetec | 列出所有的GPIO控制器 |
gpioinfo | 列出gpio控制器的引脚情况 | sudo gpioinfo 0 | 列出gpio0控制器引脚组情况 |
gpioset | 设置gpio | sudo gpioset 0 179=0 | 设置gpio0组编号179引脚为低电平 |
gpioget | 获取gpio引脚状态 | sudo gpioget 0 179 | 获取gpio0组编号179的引脚状态 |
gpiomon | 监控gpio的状态 | sudo gpiomon 0 179 | 监控gpio0组编号179的引脚状态 |
4.2.4 使用libgpiod编程开发
libgpiod库对应头文件在/usr/include/gpiod.h
常用到的函数如下:
//成员变量
struct gpiod_chip; //GPIO组句柄
struct gpiod_line; //GPIO引脚句柄
//获取GPIO控制器(GPIO组)
struct gpiod_chip *gpiod_chip_open(const char *path);
//获取GPIO引脚
struct gpiod_line * gpiod_chip_get_line(struct gpiod_chip *chip, unsigned int offset);
//设置引脚方向为输入模式
int gpiod_line_request_input(struct gpiod_line *line,const char *consumer);
//设置引脚为输出模式
int gpiod_line_request_output(struct gpiod_line *line,const char *consumer, int default_val)
//设置引脚的高低电平
int gpiod_line_set_value(struct gpiod_line *line, int value);
//读取引脚状态
int gpiod_line_get_value(struct gpiod_line *line);
//释放GPIO引脚
void gpiod_line_release(struct gpiod_line *line);
//关闭GPIO组句柄并释放所有分配的资源。
void gpiod_chip_close(struct gpiod_chip *chip);
简单样例:GPIO-H19先输出高电平,延时2秒,输出低电平
#创建gpio-h19.c 文件
jb@X1:~$ vim gpio-h19.c
gpio-h19.c文件源码如下:
#include <gpiod.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
int main(void)
{
const char *chipname="/dev/gpiochip0";
struct gpiod_line *line_h19;
int ret;
//获取GPIO控制器
struct gpiod_chip *chip = gpiod_chip_open(chipname);
if (!chip) {
printf("Open chip by name failed. name: %s\n", chipname);
return -1;
}
//获取GPIO-G19 引脚
line_h19 = gpiod_chip_get_line(chip, 179);
if (!line_h19) {
printf("Get line failed\n");
gpiod_chip_close(chip);
return -2;
}
//将GPIO-G19设置为输出模式,默认输出高电平
ret = gpiod_line_request_output(line_h19, "Consumer",GPIOD_LINE_ACTIVE_STATE_HIGH);
if (ret < 0) {
printf("Request line_h19 as output failed\n");
gpiod_line_release(line_h19);
gpiod_chip_close(chip);
return -3;
}
//设置输出状态:高电平
ret = gpiod_line_set_value(line_h19, 1);
if (ret < 0) {
printf("Set line_h19 output 1 failed. \n");
}
//延时2秒
sleep(2);
//设置输出状态:低电平
ret = gpiod_line_set_value(line_h19, 0);
if (ret < 0) {
printf("Set line_h19 output 0 failed. \n");
}
//释放资源
gpiod_line_release(line_h19);
gpiod_chip_close(chip);
return 0;
}
编译gpio-h19.c,并运行
注意:编译时候需要连接gpiod,运行时候需要sudo 权限或者root 用户下
#编译
jb@X1:~$ gcc gpio-h19.c -lgpiod
#运行
jb@X1:~$ sudo ./a.out
以上程序效果:GPIO-H19 先输出高电平,2秒后,输出低电平.
五、GPIO测试样例程序Qt界面(内核映射驱动方式):
在GPIO测试页面
IO-PIO:可以选择切换5个不同GIPIO
输出模式测试:
选择需要测试的IO,先点"设置输出模式",把IO设置为输出模式,
在"值(HEX)"位置输入1(输出高电平)或者0(输出低电平)
然后点"写IO"按钮.然后用万用表测量对应IO验证输出电平是否正确.
输入模式测试:
选择需要测试的IO,先点"设置输入模式",把IO设置为输入模式,
对应IO可以接GND(低电平)或者悬空(IO内部有上拉,默认高电平).
然后点"读IO"按钮,查看读取到的值(若值为0X84000102表示高电平,若值为0X84000100表示低电平),以验证读取结果.
测试程序qt界面样例源码和如何编译使用,请参考如下页面:
http://wiki.youyeetoo.cn/zh/x1/linux/qt-build