基于GPIO子系统编写LED驱动

news2024/11/18 23:47:53

编写应用程序进行测试

设置定时器,每5秒打印一次hello world

驱动程序

#include <linux/init.h>
#include <linux/module.h>
#include<linux/of.h>
#include<linux/of_gpio.h>
#include<linux/fs.h>
#include<linux/io.h>
#include<linux/gpio.h>
/*       myled
    {
        led1-gpio=<&gpioe 10 0>; 
        led2-gpio=<&gpiof 10 0>;
        led3-gpio=<&gpioe 8 0>;           
    }; 
*/
struct device_node *dnode;
unsigned int gpiono;
unsigned int gpiono2;
unsigned int gpiono3;
struct timer_list mytimer;
char kbuf[128]={0};
int major;

//定时器处理函数
 void mytimer_function(struct timer_list *timer)
 {
    //打印
    printk("hello world\n");
    //再次启用定时器
    mod_timer(timer,jiffies+5*HZ);
 }

ssize_t mycdev_write(struct file *file, const char  *ubuf, size_t size, loff_t *lof)
{
     int net = copy_from_user(kbuf, ubuf, size);
      if (net)
    {
        printk("copy_from_user filed\n");
        return -EIO;
    }
	 switch(kbuf[0]){
        case '1'://LED1
            if(kbuf[1]=='0')//关灯           
                gpio_set_value(gpiono,0);
            else
                //灯亮
                gpio_set_value(gpiono,1);
            break;
        case '2'://LED2
            if(kbuf[1]=='0')//关灯
                gpio_set_value(gpiono2,0);
            else
                //灯亮
                gpio_set_value(gpiono2,1);
            break;
        case '3'://LED3
            if(kbuf[1]=='0')//关灯
                gpio_set_value(gpiono3,0);
            else
                //灯亮
                gpio_set_value(gpiono3,1);
            break;
    }
    return 0;
}

struct file_operations fops={
    .write=mycdev_write,
};

static int __init mycdev_init(void)
{
        //字符设备驱动注册
    major=register_chrdev(0,"mychrdev",&fops);
    if(major<0)
    {
        printk("字符设备驱动注册失败\n");
        return major;
    }
    printk("字符设备驱动注册成功:major=%d\n",major);


    //解析设备树节点信息
    dnode=of_find_node_by_path("/myled");
    if(dnode==NULL)
    {
        printk("解析设备树节点失败\n");
        return -ENXIO;
    }
    //获取LED1 GPIO编号
    gpiono=of_get_named_gpio(dnode,"led1-gpio",0);
    if(gpiono<0)
    {
        printk("获取GPIO编号失败\n");
          return -ENXIO;
    }
    gpiono2=of_get_named_gpio(dnode,"led2-gpio",0);
    if(gpiono2<0)
    {
        printk("获取GPIO编号失败\n");
          return -ENXIO;
    }
    gpiono3=of_get_named_gpio(dnode,"led3-gpio",0);
    if(gpiono3<0)
    {
        printk("获取GPIO编号失败\n");
          return -ENXIO;
    }
    //申请gpio编号
    int ret=gpio_request(gpiono,NULL);
    if(ret)
    {
        printk("申请GPIO编号失败\n");
        return -ENXIO;
    }
    printk("申请GPIO编号成功:%d\n",gpiono);
     //申请gpio编号
    int ret2=gpio_request(gpiono2,NULL);
    if(ret2)
    {
        printk("申请GPIO编号失败\n");
        return -ENXIO;
    }
    printk("申请GPIO编号成功:%d\n",gpiono2);
     //申请gpio编号
    int ret3=gpio_request(gpiono3,NULL);
    if(ret3)
    {
        printk("申请GPIO编号失败\n");
        return -ENXIO;
    }
    printk("申请GPIO编号成功:%d\n",gpiono3);

    //初始化定时器对象
    timer_setup(&mytimer,mytimer_function,0);
    mytimer.expires=jiffies+5*HZ;//定时1s;
    //注册定时器
    add_timer(&mytimer);

    //设置GPIO为输出
    ret=gpio_direction_output(gpiono,0);
    if(ret)
    {
        printk("GPIO输出设置失败\n");
        return -1;
    }
    //设置GPIO为输出
    ret2=gpio_direction_output(gpiono2,0);
    if(ret2)
    {
        printk("GPIO输出设置失败\n");
        return -1;
    }
    //设置GPIO为输出
    ret3=gpio_direction_output(gpiono3,0);
    if(ret3)
    {
        printk("GPIO输出设置失败\n");
        return -1;
    }
    // //灯亮
    // gpio_set_value(gpiono,1);
    //     //灯亮
    // gpio_set_value(gpiono2,1);
    //     //灯亮
    // gpio_set_value(gpiono3,1);
    return 0;
}
static void __exit mycdev_exit(void)
{
        //注销定时器
    del_timer(&mytimer);
    //gpiod_set_value(gpiono,0);
    gpio_set_value(gpiono,0);
    gpio_set_value(gpiono2,0);
    gpio_set_value(gpiono3,0);
    //释放GPIO编号
    gpio_free(gpiono);
       //释放GPIO编号
    gpio_free(gpiono2);
       //释放GPIO编号
    gpio_free(gpiono3);
     //注销字符设备驱动
    unregister_chrdev(major,"mychrdev");

}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");


应用程序

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


int main(int argc, char const *argv[])
{
    char buf[128]={0};
    int fd=open("/dev/mychrdev",O_RDWR);
    if(fd<0)
    {
        printf("打开设备文件失败\n");
        exit(-1);
    }
    while(1)
    {
        //从终端读取
        printf("请输入两个字符\n");
        printf("第一个字符:1(LED1) 2(LED2) 3(LED3)\n");
        printf("第二个字符:0(关灯) 1(开灯)\n");
        printf("请输入>");
        fgets(buf,sizeof(buf),stdin);
        buf[strlen(buf)-1]='\0';
        //向设备文件中写
        write(fd,buf,sizeof(buf));
    }
    return 0;
}

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

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

相关文章

笔记-《RabbitMQ实战指南》

目录 1.发到Mq对应的3个参数&#xff1a;Exchange(交换器)&#xff0c;RountingKey(路由键)&#xff0c;param2.队列3.Exchange(交换器)4.Binding(绑定)5.交换器类型6.Connection(连接)&#xff0c;Channel(信道)7. AMQP协议8. 判断Channel或者Connection关闭状态9. 交换器和队…

【论文解读】RLAIF基于人工智能反馈的强化学习

一、简要介绍 人类反馈强化学习(RLHF)可以有效地将大型语言模型(LLM)与人类偏好对齐&#xff0c;但收集高质量的人类偏好标签是一个关键瓶颈。论文进行了一场RLHF与来自人工智能反馈的RL的比较(RLAIF) -一种由现成的LLM代替人类标记偏好的技术&#xff0c;论文发现它们能带来相…

Spring MVC的常用注解

目录 RequestMapping 例子&#xff1a; RequestMapping 支持什么类型的请求 使 RequestMapping 只支持特定的类型 RestController 通过 HTTP 请求传递参数给后端 1.传递单个参数 注意使⽤基本类型来接收参数的情况 2.传递多个参数 3.传递对象 4.RequestParam 后端参数…

Haskell Stack编译cannot encode character ‘8226‘ 错误 (Win10)

文章目录 Haskell Stack编译cannot encode character 8226 错误解决方案 &#xff1a; 更改Windows语言和区域设置(locale setting)为支持UTF-18 Haskell Stack编译cannot encode character ‘8226’ 错误 解决方案 &#xff1a; 更改Windows语言和区域设置(locale setting)为支…

测开(自动化测试selenium(WebDriver API))

一个简单的 Web自动化 演示 百度一下 迪丽热巴。这样的一个用户行为 &#xff0c;会涉及的那些操作呢&#xff1f;1、打开浏览器 2、在输入框里面输入关键词【迪丽热巴】PS&#xff1a;当然这里可能还涉及到一个操作&#xff0c;回车执行操作。或者说&#xff1a;点击 “百度一…

vue源码分析(四)——vue 挂载($mount)的详细过程

文章目录 前言一、使用RuntimeCompiler解析$mount的原因二、$mount 解析的详细过程1.解析挂载的#app执行了vm.$mount2. 通过$mount方法执行以下文件的mount方法3. 执行util工具文件夹中的query方法4. 执行query方法后返回$mount方法判断el是否是body5. 判断!options.render&…

Spring的执行流程与Bean的生命周期

目录 一、Spring的执行流程&#xff08;生命周期&#xff09; 二、Bean的生命周期 一、Spring的执行流程&#xff08;生命周期&#xff09; 首先在Spring的执行过程中会先启动容器&#xff0c;这里是将配置文件进行加载。根据配置文件完成Bean的实例化&#xff0c;比如是配置的…

通过cpolar分享本地电脑上有趣的照片:部署piwigo网页

通过cpolar分享本地电脑上有趣的照片&#xff1a;部署piwigo网页 文章目录 通过cpolar分享本地电脑上有趣的照片&#xff1a;部署piwigo网页前言1.Piwigo2. 使用phpstudy网页运行3. 创建网站4. 开始安装Piwogo 总结 前言 作为一个游戏爱好者&#xff0c;笔者在闲暇之余也会登录…

ChatGLM系列二:ChatGLM2的介绍及代码实践

一、介绍 2023年06月25日&#xff0c;清华大学开源了 ChatGLM2-6B 模型&#xff0c;是 ChatGLM 模型的升级版本。ChatGLM2-6B 在多个方面有显著提升&#xff1a;模型性能更强&#xff0c;在各种测试集上的表现更好&#xff1b;支持更长的上下文&#xff0c;最大上下文长度提升…

Java练习题2021-3

"某地大数据防疫平台记录了往来的所有防疫相关信息&#xff0c;包括 本地或外地人员、健康码颜色、接种疫苗情况、最近一次核酸结果、最近一次核酸检测时间等。 该地希望依据平台数据组织新一轮的疫苗接种&#xff0c;现有2针免疫的疫苗A和1针免疫的疫苗B。 对于本地人员&…

漏洞复现-Apache Druid 任意文件读取 _(CVE-2021-36749)

Apache Druid 任意文件读取 _&#xff08;CVE-2021-36749&#xff09; 漏洞信息 Apache Druid Version 0.22以下版本中存在安全漏洞CVE-2021-36749文件读取漏洞 描述 ​ 由于用户指定 HTTP InputSource 没有做出限制&#xff0c;可以通过将文件 URL 传递给 HTTP InputSourc…

氧化锌纳米线 Zinc oxide nanowires

氧化锌纳米线 英文&#xff1a;Zinc oxide nanowires 分子式&#xff1a;ZnO 直径&#xff1a; 50nm 长度&#xff1a; 20um 纯度: 99% 外观&#xff1a;白色 描述&#xff1a;纳米线可以被定义为一种具有在横向上被限制在100纳米以下(纵向没有限制)的一维结构。悬置纳米…

Builder 请进:波卡最新开发入门指南

撰文&#xff1a;Dennis Zoma 编译&#xff1a;OneBlock 社区 本文更新于 2023 年 10 月 3 日&#xff0c;来源&#xff1a;https://wiki.polkadot.network/docs/build-guide Polkadot 是一个区块链协议&#xff0c;有两个目标&#xff1a;在所有连接的平行链之间提供共享安全…

你绝对不知道的JMeter中如何实现接口之间的关联?

关联是Jmeter工具中非常重要的一个技术。因为在测试过程过有些数据是经常发生变化的&#xff0c;要获取并使用这些数据&#xff0c;就要使用关联。 比如&#xff1a;用户登录后&#xff0c;session信息都不同&#xff0c;有些操作要使用session&#xff0c;就需要将这个动态的信…

计算机网络_04_传输层

文章目录 1.什么是传输层2.传输层提供了什么服务3.传输层协议TCP 1.什么是传输层 传输层是OSI七层体系架构中的第四层, TCP/IP四层体系架构中的第二层, 从通信和信息处理两方面来看&#xff0c;“传输层”既是面向通信部分的最高层&#xff0c;与下面的三层一起共同构建进行网…

bootstap_小项目

通过bootstrap画一个简单的后台管理页面&#xff0c;知识有限&#xff0c;页面粗糙&#xff0c;一种记录方式 页面效果展示 首页页面代码 <!DOCTYPE html> <html><head><meta charset"utf-8"><meta http-equiv"X-UA-Compatible&qu…

Uva11059 Maximum Product(最大乘积)

1、题目 Uva 11059 2、题意 输入 n n n 个元素组成的序列 S S S&#xff0c;你需要找出一个乘积最大的连续子序列。如果这个最大的乘积不是正数&#xff0c;应输出0&#xff08;表示无解&#xff09;。 1 ≤ n ≤ 18 &#xff0c; − 10 ≤ S i ≤ 10 1 \le n \le 18&…

测试小白必看!接口测试必需掌握的知识要点!

接口测试 接口测试是测试系统组件间接口的一种测试。接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点。测试的重点是要检查数据的交换&#xff0c;传递和控制管理过程&#xff0c;以及系统间的相互逻辑依赖关系等。 接口测试原理 通过测试程序模拟客…

SpringBoot中使用JdbcTemplate访问Oracle数据库

Oracle相信大家都不陌生吧&#xff0c;一个大型的数据库&#xff0c;至于数据库&#xff0c;我相信各位都比较熟悉了&#xff0c;一个软件系统&#xff0c;不论是我们常做的App、小程序、还是传统的web站点&#xff0c;我们都有用户的信息&#xff0c;相关业务的数据&#xff0…

公司如何禁止拷贝文件

公司如何禁止拷贝文件 安企神U盘管理系统下载使用 禁止拷贝文件是一种数据安全措施&#xff0c;通常在企业中用于保护重要信息和知识产权。禁止拷贝文件的方法需要根据公司的实际情况来选择和实施&#xff0c;以下是一些常见的方法&#xff0c;可用于防止文件拷贝&#xff1a…