Linux下GPIO和看门狗应用编程

news2024/11/17 11:29:16

文章目录

  • GPIO应用编程
  • 看门狗应用编程

GPIO应用编程

应用层操控硬件可以通过操作这些硬件的设备文件来进行,设备文件是各种硬件设备向应用层提供的一个接口,应用层通过对设备文件的I/O操作来操控硬件设备。设备文件通常在/dev/目录下,该目录下的文件也称为设备节点,前面驱动开发中的设备节点文件就存放该目录下,通过对相应的设备文件进行读写操作从而达到控制其对应硬件的目的。
除了对设备文件操作可以控制硬件设备外,还可以通过对sysfs文件系统对硬件设备进行操控。sysfs提供了一种机制,可以显式的描述内核对象、对象属性及对象间关系,用来导出内核对象的数据、属性到用户空间,以文件目录结构的形式为用户空间提供对这些数据和属性的访问支持。硬件设备、设备属性、对象关系在sysfs中分别对应目录、文件和链接文件。
sysfs挂载在/sys/目录下,打开/sys/目录,其包含的文件及其层级关系如下图所示。
在这里插入图片描述
/sys/devices下存放着系统所有的设备目录;/sys/block是块设备目录;/sys/bus是系统总线类型的目录;/sys/class是按照功能分类放置的目录;/sys/dev是按照设备号方式放置的目录;/sys/firmware是内核中的固件目录;/sys/fs是文件系统目录;/sys/kernel是内核中所有可调参数的位置;/sys/module是系统中存放模块信息的目录;/sys/power是系统中电源选项。/sys/devices是最重要的目录,其他的设备目录都是链接到该目录下。
下面介绍一下通过sysfs控制gpio的方法。
进入到/sys/class/gpio目录下,该目录下包含两个文件export和unexport以及gpio_和gpiochip_等文件夹。gpiochip_对应着开发板的gpio控制器,是一组gpio,后面的数字就是这组gpio中的起点,gpio_就是某一个具体的gpio口。
export用于将指定编号的GPIO引脚导出,在使用GPIO引脚之前,需要将其导出,导出成功之后才能使用它。export文件是只写文件,将一个指定的编号写入到export文件中即可将对应的GPIO引脚导出。导出的命令如下。

echo 0 > export //导出gpio0

使用上面的命令后就可以在/sys/class/gpio目录下生成了一个名为gpio0的文件夹,文件夹里面有相关属性的文件,使用cat命令就可以查看属性值,如下图所示。
在这里插入图片描述
unexport用于将导出的GPIO引脚删除,删除的命令如下。

echo 0 > unexport //删除gpio0

direction文件配置GPIO引脚为输入或输出模式,有"in"和"out";value是在GPIO配置为输出模式下,向value文件写入"0"控制GPIO引脚输出低电平,写入"1"则控制GPIO引脚输出高电平。在输入模式下,读取value文件获取GPIO引脚当前的输入电平状态。active_low属性文件用于控制极性,可读可写,默认情况下为0;edge控制中断的触发模式,该文件可读可写,非中断引脚为"none",上升沿触发为"rising",下降沿触发为"falling",边沿触发为"both"。
进到相应的gpio目录下,配置各属性的命令如下,可根据自己的要求给属性设置对应的值。

echo “in” > direction
echo “out” > direction
echo “0” > active_low
echo “1” > active_low
echo “0” > value
echo “1” > value
echo “none” > edge
echo “rising” > edge
echo “falling” > edge
echo “both” > edge

上面是采用命令设置各属性,代码实现如下。

#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <error.h>
#include <stdlib.h>

static char gpio_path[100];   //gpio存放路径
static int gpio_config(const char *attr, const char *val)   //gpio属性设置函数
{
    char file_path[100];  //加属性之后的路径
    int fd,ret;
    sprintf(file_path,"%s/%s",gpio_path,attr);   //属性的路径
    
    fd = open(file_path, O_RDWR);
    if(fd < 0)
    {
        perror("open error"); 
        return fd;
    }
    ret = write(fd,val,strlen(val));  //给gpio相关属性设置值
    if(ret < 0)
    {
        perror("attribute write error");
        return ret;
    }
    close(fd);
    return 0;
}

int main(int argc, char **argv)
{
    int fd,ret;
    char value[1];
    char file_path[100];
    if(argc != 3)   //argv[1]:gpio number ------  argv[2]:value
    {
        printf("error argument!\n");
        return -1;
    }
    sprintf(gpio_path,"/sys/class/gpio/gpio%s",argv[1]);
    
    if (access(gpio_path,F_OK))    //如果需要的gpio目录不存在,则需要通过export导出,相当于命令 echo 0 > export
    {
            fd = open("/sys/class/gpio/export", O_WRONLY);  //打开配置文件
            if(fd < 0)
            {
                perror("open error"); 
                return fd;
            }
            ret = write(fd,argv[1],strlen(argv[1]));
            if(ret < 0)
            {
                perror("gpio write error");
                return ret;
            }
            close(fd);
    }
        
    //目标gpio已存在,直接设置
    gpio_config("direction","out");  //配置输入输出方向
    gpio_config("active_low","0");   //配置低电平
    gpio_config("value",argv[2]);   //设置值
    //gpio_config("edge","both");   //设置中断触发模式
    
    //读取gpio的value属性
    sprintf(file_path,"%s/%s",gpio_path,"value");
    fd = open(file_path,O_RDONLY);
    read(fd,value,1);
    printf("value = %c\n",value[0]);
    return 0;
}

上面的程序执行时传入两个参数,第一个参数是gpio对应的编号,第二个参数是设置的value属性值,有些gpio口设置value的时候是不被允许的,可以根据自己开发板的情况修改代码执行程序。


看门狗应用编程

为了使系统在异常情况下能自动复位,一般都需要引入看门狗,看门狗本质上是一个可以在一定时间内被复位的计数器。当看门狗启动后,计数器开始自动计数,经过特定的时间,如果计数器没有被复位,计数器就会溢出从而对CPU产生一个复位信号使系统重启。系统正常运行时,需要在看门狗允许的时间间隔内对看门狗计数器清零,俗称喂狗,喂狗是为了不产生复位信号。如果系统不出问题,程序就可以保证按时喂狗,一旦程序跑飞,则不会喂狗,系统收到复位信号进行复位。
使用WDIOC_GETTIMEOUT指令获取超时时间,WDIOC_SETTIMEOUT指令设置超时时间。

int timeout;
ioctl(int fd, WDIOC_GETTIMEOUT, int *timeout); //获取超时时间
ioctl(int fd, WDIOC_SETTIMEOUT, int *timeout); //设置超时时间

WDIOS_ENABLECARD指令开启、WDIOS_DISABLECARD指令停止看门狗。

int option = WDIOS_ENABLECARD;
ioctl(int fd, WDIOC_SETOPTIONS, int *option);  //开启

int option = WDIOS_DISABLECARD;
ioctl(int fd, WDIOC_SETOPTIONS, int *option);  //关闭

使用WDIOC_KEEPALIVE指令喂狗。

ioctl(int fd, WDIOC_KEEPALIVE, NULL);

开发板的/dev/目录下有watchdog和watchdog0两个和看门狗相关的设备节点,这两个代表的是同一个硬件外设,我在代码中都试了,这两个设备节点都是可以控制看门狗的。
在这里插入图片描述
看门狗的测试代码如下。

#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <error.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <linux/watchdog.h>

int main(int argc, char **argv)
{
    int timeout;   //超时时间设定
    int time;   //喂狗间隔时间
    int op;   //设置看门狗状态
    int fd;
    int ret;
   
    if(argc != 2)   //需要用户传入超时时间
    {
        printf("error argument!\n");
        return -1;
    }
    
    fd = open("/dev/watchdog", O_RDWR);   //打开看门狗设备文件
    if (fd < 0) 
    { 
        perror("open error"); 
        return fd;
    }

    op = WDIOS_DISABLECARD; 
    ret = ioctl(fd,WDIOC_SETOPTIONS,&op);   //先停止看门狗计时器
    if (ret < 0) 
    { 
        close(fd); 
        return ret; 
    }
   
    timeout = atoi(argv[1]);   //接收参数
    ret = ioctl(fd,WDIOC_SETTIMEOUT,&timeout);  //设置超时
    if (ret < 0) 
    { 
        close(fd); 
        return ret; 
    }

    op = WDIOS_ENABLECARD; 
    ret = ioctl(fd,WDIOC_SETOPTIONS,&op);  //开启看门狗计时器
    if (ret < 0) 
    { 
        close(fd); 
        return ret; 
    }

    time = (timeout*1000-100)*1000;   //设置喂狗时间间隔,在超时时间到来前100ms喂狗
    printf("set timeout : %ds\n",timeout);
    ret = 0;
    while(1)
    {
        usleep(time);  //喂狗时间间隔
        ret++;
        printf("KEEPALIVE---%d\n",ret);
        ioctl(fd,WDIOC_KEEPALIVE,NULL);  //喂狗
    }
    return 0;
}

程序运行结果如下图所示。
在这里插入图片描述
该程序运行起来之后,每隔一段时间,在看门狗将要到时前进行一次喂狗操作,这样系统就能正常运行。按下Ctrl+C终止该程序之后,内核打印信息如下。

watchdog watchdog0: watchdog did not stop!

说明看门狗计时器还在计时,没有因为程序的终止而停下,所以看门狗计时器会溢出,从而发生复位重启,由上图可以看到,计时器到时候开发板就自动重启了。


参考资料:
I.MX6U嵌入式Linux C应用编程指南V1.4——正点原子

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1150758.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

react:生命周期

一、生命周期阶段 官方文档&#xff1a;https://zh-hans.legacy.reactjs.org/docs/react-component.html React组件生命周期可分为三个阶段&#xff1a;挂载、更新、卸载 挂载&#xff1a;当组件实例被创建并插入 DOM 中时。其生命周期调用顺序如下&#xff1a; constructor()s…

rfsoc FPGA 49DR 16收16发模块

前面简单介绍过RFSOC板卡 https://blog.csdn.net/jingjiankai5228/article/details/114734631 整体来说RFSOC降低了传统AD DA软硬件开发难度&#xff0c;但是同样存在整数点FS/N谐波大的问题 交织采样是通过多个AD拼接完成的&#xff0c;所以校准比较关键&#xff0c;和以前常…

【算法练习Day33】不同路径不同路径 II

​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;练题 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录 不同路径不同路径 II总结&a…

腾讯云轻量服务器“镜像类型”以及“镜像”选择方法

腾讯云轻量应用服务器镜像类型分为应用镜像、系统镜像、Docker基础镜像、自定义镜像和共享镜像&#xff0c;腾讯云百科txybk.com来详细说下不同镜像类型说明和详细介绍&#xff1a; 轻量应用服务器镜像类型说明 腾讯云轻量应用服务器 应用镜像&#xff1a;独有的应用镜像除了包…

RHCE---作业4

一.批量创建账户 .编写脚本for1.sh,使用for循环创建20账户&#xff0c;账户名前缀由用户从键盘输入&#xff0c;账户初始密码由用广输入&#xff0c;例如: test1、test2、test3、.....、 test10 read -p "请输入账户前缀名&#xff1a;" user read -p "请输入…

低代码软件在酒店行业的应用:提升效率与创新!

疫情放开后&#xff0c;旅游业开始兴盛发展&#xff0c;酒店行业也恢复了疫情前的繁忙。但是由于管理架构上的不完善导致很多酒店并不能很好地承接巨大的客流量&#xff0c;而消费者在旅游过程对体验要求是最高的&#xff0c;所以酒店拥有一个能够高效运营的管理系统至关重要。…

前端接口请求支持内容缓存和过期时间

前端接口请求支持内容缓存和过期时间 支持用户自定义缓存时间&#xff0c;在规则时间内读取缓存内容&#xff0c;超出时间后重新请求接口 首先封装一下 axios&#xff0c;这一步可做可不做。但是在实际开发场景中都会对 axios 做二次封装&#xff0c;我们在二次封装的 axios …

Redis入门指南学习笔记(1):初识Redis

一.什么是Redis? Redis全称为Remote Dictionary Server&#xff0c;即远程字典服务器&#xff0c;它采用字典结构来存储数据&#xff0c;并允许其他应用通过TCP协议来访问数据。 字典在众多开发语言中都很常见&#xff0c;其形式为键值对&#xff0c;根据键可以获取相应的值…

文件名替换,关键字替换改名:不同路径中的多个文件如何批量重命名

在日常生活和工作中&#xff0c;我们经常需要处理大量的文件&#xff0c;包括重命名、分类、整理等操作。其中&#xff0c;批量重命名不同路径中的多个文件是一项非常常见的任务。本文将介绍云炫文件管理器常见的批量重命名方法&#xff1a;文件名关键字替换改名&#xff0c;帮…

python类模拟“对战游戏”

Game类含玩家昵称、生命值、攻击力(整数)&#xff0c;暴击率、闪避率(小数)&#xff0c;在魔术方法init定义&#xff1b;attack方法中实现两个Game实例对战模拟。 (本笔记适合初通Python类class的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.py…

请输入正确的小程序的链接,并确保小程序允许被搜索

公众号文章插入小程序时提示“请输入正确的小程序的链接&#xff0c;并确保小程序允许被搜索”&#xff1a; 这是因为你输入的是小程序路径&#xff0c;不是小程序链接。 如果是你想使用小程序路径&#xff0c;需要点击第一张图中的蓝色字“去搜索”&#xff0c;然后搜索选择你…

少儿编程 2023年9月中国电子学会图形化编程等级考试Scratch编程四级真题解析(判断题)

2023年9月scratch编程等级考试四级真题 判断题(共10题,每题2分,共20分) 11、运行程序后,变量"result"的值是6 答案:对 考点分析:考查积木综合使用,重点考查自定义积木的使用 图中自定义积木实现的功能是获取两个数中最大的那个数并存放在result变量中,左…

Find My水杯|苹果Find My技术与水杯结合,智能防丢,全球定位

2018年中国智能水杯行业的市场规模约为32亿元&#xff0c;而到2021年&#xff0c;这一市场规模将达到45亿元&#xff0c;增长率约为8.6%。随着智能科技的不断深入发展&#xff0c;智能水杯也越来越受到消费者的青睐&#xff0c;他们更加偏爱智能水杯带来的便捷。智能水杯可以监…

Webpack5中devServer配置contentBase报错的问题

结果报错&#xff0c;没有contentBase这个属性&#xff0c;已经被弃用了。 新的配置方式&#xff1a; const path require(path);module.exports {//...devServer: {static: {directory: path.join(__dirname, public),},compress: true,port: 9000,}, };

关于Spring和SpringBoot中对配置文件的读取

Spring读取xml文件 具体流程见网址Spring源码分析2 — spring XML配置文件的解析流程 - 知乎 (zhihu.com) 我这里只做一下总结和自己的理解&#xff1a; &#xff08;1&#xff09;通过getConfigLocations方法, 从web.xml文件中读取配置文件地址&#xff0c;如果web.xml中读取…

ES 8.x新特性一览(完整版)

一、看点 在 2022 年 2 月 11 日&#xff0c;Elasticsearch&#xff08;ES&#xff09;正式发布了 8.0 版本&#xff0c;而截止到 2023 年 10 月&#xff0c;历经一年半时间&#xff0c;ES官方已经连续发布了多个版本&#xff0c;最新版本为 8.10.4。这一系列的更新引入了众多引…

【多线程面试题二十】、 如何实现互斥锁(mutex)?

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a;如何实现互斥锁&#xf…

JavaSE20——IO流

IO流 1 Java IO流 I/O是Input/Output的缩写&#xff0c; I/O技术是非常实用的技术&#xff0c;用于处理设备之间的数据传输。如读/写文件&#xff0c;网络通讯等。Java程序中&#xff0c;对于数据的输入/输出操作以“流(stream)” 的方式进行 I(Input): 输入流指的是将数据以…

世界前沿技术发展报告2023《世界航空技术发展报告》(七)机载系统与武器技术

&#xff08;七&#xff09;机载系统与武器技术 1.机载系统技术1.1 美国推进商用5G技术在航空装备中的应用1.2 人工智能技术在航空中的应用日益增多1.3 美国空军研究实验室推出综合座舱感知技术1.4 美国空军为固定翼飞机驾驶员选定新一代头盔1.5 美国DARPA探索通过机载光能量中…