2023.6.20 GPIO子系统编写LED驱动

news2024/11/22 14:42:57

作业:通过GPIO子系统编写LED驱动,应用程序控制LED灯亮灭

(1)led.h

 #ifndef __LED_H__
#define __LED_H__ 
// typedef struct{
//     unsigned int MODER;
//     unsigned int OTYPER;
//     unsigned int OSPEEDR;
//     unsigned int PUPDR;
//     unsigned int IDR;
//     unsigned int ODR;
// }gpio_t;
// #define PHY_LED1_ADDR 0X50006000
// #define PHY_LED2_ADDR    0X50007000
// #define PHY_LED3_ADDR 0X50006000
// #define PHY_RCC_ADDR    0X50000A28

//封装开灯关灯功能码
#define LED_ON _IOW('l',1,int)
#define LED_OFF _IOW('l',0,int)
#endif 

(2)test.h

#include"led.h"
#include<stdlib.h>
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<unistd.h>
#include<string.h>
#include <sys/ioctl.h>

int main(int argc, char const *argv[])
{
    int a,b;
    char buf[128]={0};
    int fd=open("/dev/mycdev",O_RDWR);
    if(fd<0)
    {
        printf("打开设备文件失败\n");
        exit(-1);
    }
    while(1)
    {
        printf("请输入:1(开灯) 0(关灯)>");
        scanf("%d",&a);
        printf("请输入控制的灯:1(LED1) 2(LED2) 3(LED3)>");
        scanf("%d",&b);
        switch(a)
        {
            case 1:
                ioctl(fd,LED_ON,&b);//开灯
                break;
            case 0:
                ioctl(fd,LED_OFF,&b);//关灯
                break;
        }
    }
    close(fd);
    
    return 0;
}

(3)dt.c

 #include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include<linux/fs.h>
#include<linux/io.h>
#include<linux/device.h>
#include"led.h"

int major;
char kbuf[128]={0};
// gpio_t *vir_led1;
// gpio_t *vir_led2;
// gpio_t *vir_led3;
//unsigned int *vir_rcc;
struct class *cls;
struct device *dev;

int gpiono1;  //led1
int gpiono2;  //led2
int gpiono3;  //led3
struct device_node *dnode;
int mycdev_open(struct inode *inode, struct file *file)
{
    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    return 0;
}

long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    int which;
    int ret=copy_from_user(&which,(void *)arg,4);
    if(ret)
    {
        printk("copy_from_user filed\n");
        return ret;
    }
    switch(cmd)
    {
        case LED_ON://开灯
            switch(which)
            {
                case 1:
                     gpio_set_value(gpiono1,1);
                    break;
                case 2:
                     gpio_set_value(gpiono2,1);
                    break;
                case 3:
                     gpio_set_value(gpiono3,1);
                    break;       
            }
            break;
        case LED_OFF://关灯
            switch(which)
            {
                case 1:
                     gpio_set_value(gpiono1,0);  
                     break;
                case 2:
                     gpio_set_value(gpiono2,0);  
                     break;
                case 3:
                     gpio_set_value(gpiono3,0);  
                     break;           
            }
            break;
    }
    return 0;
}
int mycdev_close(struct inode *inode, struct file *file)
{
    printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
    return 0;
}

//定义操作方法结构体变量并赋值
struct file_operations fops={
    .open=mycdev_open,
   .unlocked_ioctl=mycdev_ioctl,
    .release=mycdev_close,
};

// int all_led_init(void)
// {
//     //寄存器地址的映射
//     vir_led1=ioremap(PHY_LED1_ADDR,sizeof(gpio_t));
//     if(vir_led1==NULL)
//     {
//         printk("ioremap filed:%d\n",__LINE__);
//         return -ENOMEM;
//     }
//      vir_led2=ioremap(PHY_LED2_ADDR,sizeof(gpio_t));
//     if(vir_led2==NULL)
//     {
//         printk("ioremap filed:%d\n",__LINE__);
//         return -ENOMEM;
//     }
//      vir_led3=vir_led1;
//     vir_rcc=ioremap(PHY_RCC_ADDR,4);
//     if(vir_rcc==NULL)
//     {
//         printk("ioremap filed:%d\n",__LINE__);
//         return -ENOMEM;
//     }
//     printk("物理地址映射成功\n");
//     return 0;
// }

static int __init mycdev_init(void)
{
    int ret;
    //字符设备驱动注册
    major=register_chrdev(0,"mycdev",&fops);
    if(major<0)
    {
        printk("字符设备驱动注册失败\n");
        return major;
    }
    printk("字符设备驱动注册成功:major=%d\n",major);
    //向上提交目录
    cls=class_create(THIS_MODULE,"mycdev");
    if(IS_ERR(cls))
    {
        printk("向上提交目录失败\n");
        return -PTR_ERR(cls);
    }
    printk("向上提交目录成功\n");
    //向上提交设备节点信息
    dev=device_create(cls,NULL,MKDEV(major,0),NULL,"mycdev");
    if(IS_ERR(dev))
    {
        printk("向上提交设备节点失败\n");
        return -PTR_ERR(dev);
    }
    printk("向上提交设备节点成功\n");
    // //寄存器映射
    // all_led_init();
   //解析设备树节点
   dnode=of_find_node_by_name(NULL,"myleds");
   if(dnode==NULL)
   {
       printk("解析设备树节点失败...\n");
       return -ENOMEM;
   }
   printk("解析设备树节点成功...\n");

   //根据设备树节点解析出gpio编号
   /***************LED1*******************/
   gpiono1=of_get_named_gpio(dnode,"led1",0);
   if(gpiono1<0)
   {
       printk("解析设备号%d失败...\n",gpiono1);
       return -EIO;
   }
    printk("解析设备号%d成功...\n",gpiono1);

    //申请gpio编号
    ret=gpio_request(gpiono1,NULL);
    if(ret)
    {
        printk("申请GPIO编号%d失败...\n",gpiono1);
        return -EIO;
    }
        printk("申请GPIO编号%d成功...\n",gpiono1);
        //设置管脚为输出
        gpio_direction_output(gpiono1,0);

    /***************LED2*******************/
   gpiono2=of_get_named_gpio(dnode,"led2",0);
   if(gpiono2<0)
   {
       printk("解析设备号%d失败...\n",gpiono2);
       return -EIO;
   }
        printk("解析设备号%d成功...\n",gpiono2);

        //申请gpio编号
        ret=gpio_request(gpiono2,NULL);
        if(ret)
        {
            printk("申请GPIO编号%d失败...\n",gpiono2);
            return -EIO;
        }
            printk("申请GPIO编号%d成功...\n",gpiono2);
            //设置管脚为输出
            gpio_direction_output(gpiono2,0);
            
         /***************LED3*******************/
   gpiono3=of_get_named_gpio(dnode,"led3",0);
   if(gpiono3<0)
   {
       printk("解析设备号%d失败...\n",gpiono3);
       return -EIO;
   }
        printk("解析设备号%d成功...\n",gpiono3);

        //申请gpio编号
        ret=gpio_request(gpiono3,NULL);
        if(ret)
        {
            printk("申请GPIO编号%d失败...\n",gpiono3);
            return -EIO;
        }
            printk("申请GPIO编号%d成功...\n",gpiono3);
            //设置管脚为输出
            gpio_direction_output(gpiono3,0);
      
    return 0;
}
static void __exit mycdev_exit(void)
{
    // //取消地址映射
    // iounmap(vir_led1);
    // iounmap(vir_led2);
    // iounmap(vir_rcc);
    //销毁设备节点信息
    device_destroy(cls,MKDEV(major,0));
    //销毁目录空间
    class_destroy(cls);
    //注销字符设备驱动
    unregister_chrdev(major,"mychrdev");

    //释放编号
    gpio_free(gpiono1);                      //led1
    gpio_free(gpiono2);                     //led2
    gpio_free(gpiono3);                      //led3
    //关灯
    gpio_set_value(gpiono1,0); 
    gpio_set_value(gpiono2,0); 
    gpio_set_value(gpiono3,0); 
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

(4)实验现象

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

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

相关文章

FreeRTOS实时操作系统(五)临界区及任务调度器

系列文章目录 文章目录 系列文章目录临界区代码保护任务调度器的挂起与保护 临界区代码保护 临界区&#xff1a;是指那些必须要完整运行的&#xff0c;不能被打断的代码 适用于&#xff1a; 1.外设初始化 2.操作系统的代码有很多不能被打断 3.用户自己的需求 一般在中断、任…

014 - STM32学习笔记 - I2C访问存储器(一)

014 - STM32学习笔记 - I2C访问存储器 1、存储器分类 存储器主要分为两类&#xff1a;易失性存储器和非易失性存储器&#xff0c;从字面上理解&#xff0c;判断易失/非易失主要取决于设备掉电后&#xff0c;存储的数据是否会丢失。常规的来说&#xff0c;易失性存储器存取速度…

Django基础入门⑥:Django过滤器和标签讲解

Django基础入门⑥&#xff1a;Django过滤器和标签讲解 Django过滤器过滤器语法过滤器应用获取变量的长度截取指定个数的词返回指定键的排序列表add给变量值加“n” Django url标签url标签动态url Django自定义标签如何自定义标签定义之前的准备工作模块变量register自定义标签赋…

Java 对接google WIFI定位API

1.创建Http请求工具类 1.1.引入httpclient <dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.10</version></dependency> 1.2.封装Http工具类 /*** Http请求* a…

MySQL 高级语句 一

目录 一、MySQL高级&#xff08;进阶&#xff09;SQL语句1. select2. distinct3. where4. and or5. in6. between7. 通配符8. order by9. 函数9.1 数学函数9.2 聚合函数9.3 字符串函数 二、高级查询语句2.1 group by &#xff08;用于分组和汇总&#xff09;2.2 having2.3 别名…

如何在 XMind 中绘制流程图

XMind 是专业强大的思维导图软件,由于其结构没有任何限制,很多朋友特别喜欢用它来绘制流程图。禁不住大家的多次询问,今天 XMind 酱就将这简单的流程图绘图方法分享给大家。 在 XMind 中,绘制流程图的主角是「自由主题」和「联系」。它们可以打破思维导图的限制,让你自由…

《异常检测——从经典算法到深度学习》21 Anomaly Transformer:具有关联差异的时间序列异常检测

We # 《异常检测——从经典算法到深度学习》 0 概论1 基于隔离森林的异常检测算法 2 基于LOF的异常检测算法3 基于One-Class SVM的异常检测算法4 基于高斯概率密度异常检测算法5 Opprentice——异常检测经典算法最终篇6 基于重构概率的 VAE 异常检测7 基于条件VAE异常检测8 Do…

[NX亲测有效]Ubuntu,Jetson nano,NX板开机设置开机自起,Jetson nano,NX设置x11vnc开机自起

&#xff01;&#xff01;Ubuntu,Jetson nano,NX板开机设置开机自起&#xff0c;nano NX设置x11vnc开机自起&#xff01;&#xff01; 1.创建一个rc-local自启服务 2.创建运行脚本 3.启动服务 4.NX&#xff0c;nano设置x11vnc并设置开机自启 大功告成&#xff01;编写不易…

【中级软考】软件设计-考试介绍

一、软考好处 通过软考认证可以抵扣当年的 3600 元的个税,并且有些城市可以积分落户,同时获得证书可以获得同等级别的职称。计算机方向的职称是以考代评,所以获得中级软考证书就相当于获得同等的中级计算机工程师职称,获得高级软考证书就相当于获得同等的高级计算机工程师…

如何使用@umijs/plugin-qiankun搭建微前端项目

umijs/plugin-qiankun是一个基于UmiJS框架的插件&#xff0c;用于实现乾坤微前端架构。乾坤微前端是一种前端架构模式&#xff0c;可以将一个大型的前端应用拆分成多个小型的子应用&#xff0c;每个子应用可以独立开发、独立部署、独立运行&#xff0c;同时可以通过乾坤框架进行…

ArduPilot开源代码之AP_InertialSensor

ArduPilot开源代码之AP_InertialSensor 1. 源由2. AP_InertialSensor类2.1 init2.2 periodic2.3 update 3. 重要应用方法3.1 BatchSampler::push_data_to_log3.2 wait_for_sample3.2 calibrate_gyros 4. 总结5. 参考资料 1. 源由 前面研读了IMU如何通过front-end/back-end获取…

基于SpringBoot+kaptcha的验证码生成

教程 1.添加 Kaptcha 依赖 在 pom.xml 文件中添加 Kaptcha 依赖&#xff1a; <dependency><groupId>com.github.penggle</groupId><artifactId>kaptcha</artifactId><version>2.3.2</version> </dependency> <!--或者 都…

【深度学习 | 机器学习】干货满满 | 近万字总结了 12 个令人惊艳的神经网络可视化工具!

文章目录 一、神经网络可视化难点在哪里&#xff1f;二、神经网络可视化方法三、神经网络可视化解释的工具3.1 draw_convnet3.2 NNSVG3.3 PlotNeuralNet3.4 Tensorboard3.5 Caffe3.6 Matlab3.7 Keras.js3.8 DotNet3.9 Graphviz3.10 ConX3.11 ENNUI3.12 Neataptic 神经网络可视化…

linux下Python的学习(五)用matplotlib画iostat的折线图

之前写测试脚本的时候习惯用shell来写&#xff0c;只不过用AWK(个人觉得awk是shell的精髓)处理表格的时候比Python复杂的多&#xff0c;因为Python有很多现成的库&#xff0c;直接调用就可以。下面用Python自带的matplotlib函数实现一下对iostat log的采样 比如有一个记录iosta…

第一章 数据可视化简介(复习)

第一章 数据可视化简介 什么是可视化 定义&#xff1a;通过可视表达增强人们完成某些 任务的效率 The American Heritage Dictionary&#xff1a; The act or process of interpreting in visual terms or of putting into visible form&#xff08;用可视形式进行解释的 动作…

做性能测试必须掌握的基本概念和套路

目录 性能优化的常见概念 性能调优的思路 1.性能摸底测试 2.定义性能优化的目标 3.分析 针对内存&#xff1a; OOM&#xff1a; 针对IO&#xff1a; 文件IO&#xff1a; 总结&#xff1a; 经常听到人说&#xff0c;做个性能优化&#xff0c;吞吐量越高越好&#xff1…

2023 年开发者必须知道的 6 个 AI 工具

自Chat GPT发布以来&#xff0c;AI在各个领域都出现了令人惊艳的产品&#xff0c;在编程方面也是如此。这些由 AI 驱动的工具使用算法快速准确地生成代码&#xff0c;从而节省程序员的时间和精力。虽然目前AI写出来的代码还不能完全替代人类&#xff0c;但开发人员完全可以作为…

安卓开发之广播接收器

搞安全的&#xff0c;用到哪学到哪 广播的几个部分 1.发送广播的逻辑&#xff08;需要先定义Intent方法&#xff0c;再进行send&#xff09; 2.接收广播的逻辑&#xff08;继承BroadcastReceiver方法&#xff09; 3.开关控制广播&#xff0c;也就是注册广播的过程&#xff…

Express框架与Mongodb的结合使用

前言 如果你打开这篇文章&#xff0c;说明已经开始有做项目的打算了。 这里有express和mongodb的相关参考教程&#xff0c;遇到问题可以在里面找到答案&#xff1a; Express框架从入门到如土 一文入门Mongodb 这里说下为什么要express框架和mongodb结合。express框架不是指单…

【MySQL数据库】MySQL 高级SQL 语句

[TOC](MySQL 高级SQL 语句 一、MySQL 高级SQL 语句1.1select -显示表格中一个或数个字段的所有数据记录1.2distinct不显示重复的数据记录1.3where有条件查询1.4and、or且 或1.5in 显示已知的值的数据记录1.6between 显示两个值范围内的数据记录1.7通配符&#xff0c;通常通配符…