当前位置: 首页 > news >正文

驱动开发 day3 (模块化驱动启动led,蜂鸣器,风扇,震动马达)

模块化驱动启动led,蜂鸣器,风扇,震动马达并加上Makefile

封装模块化驱动,可自由安装卸载驱动,便于驱动更新(附图)

1.安装模块驱动同时初始化各个设备并使能

2.该驱动会自动创建驱动节点.

3.通过c函数程序输入控制各个设备

4.卸载模块驱动

//编译驱动(注意Makefile的编译到移植到开发板的内核)

        make arch=arm

//安装驱动

        insmod mycdev.ko

//卸载驱动

        rmmod mycdev

//编译fun.c 函数(用到交叉工具编译)

        arm-linux-gnueabihf-gcc fun.c

        

head.h //头文件

#ifndef __HEAD_H__
#define __HEAD_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   //GPIOE 10
#define PHY_LED2_ADDR   0X50007000   //GPIOF 10
#define PHY_LED3_ADDR   0X50006000   //GPIOE 8
#define PHY_RCC_ADDR    0X50000A28   //RCC#define PHY_FAN_ADDR    0X50006000      //GPIOE 9  TIM1  风扇
#define PHY_ATO_ADDR    0X50007000      //GPIOF 6  TIM16 震动马达
#define PHY_WMM_ADDR    0X50003000      //GPIOB 6  TIM4  蜂鸣器//功能码
#define LED_ON _IOW('1',1,int)
#define LED_OFF _IOW('1',0,int)#endif // MACRO

mycmod.c //驱动函数 

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/io.h>
#include <linux/device.h>
#include "head.h"unsigned int major;
char kbuf[128] = {0};gpio_t *vir_led1;
gpio_t *vir_led2;
gpio_t *vir_led3;gpio_t *vir_wmm;
gpio_t *vir_fan;
gpio_t *vir_ato;unsigned int *vir_rcc;struct class *cls;
struct device *dev;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;copy_from_user(&which,(void *)arg,4);switch (cmd){case LED_ON:switch (which){case 1:                           // LED1vir_led1->ODR |= (0x1 << 10); // LED1开灯break;case 2:                           // LED2vir_led2->ODR |= (0x1 << 10); // LED2开灯break;case 3:                          // LED3vir_led3->ODR |= (0x1 << 8); // LED3开灯break;case 4:                           // FANvir_fan->ODR |= (0x1 << 9); // FAN开灯break;case 5:                           // ATOvir_ato->ODR |= (0x1 << 6); // ATO开灯break;case 6:                          // WMMvir_wmm->ODR |= (0x1 << 6); // WMM开灯break;}break;case LED_OFF:switch (which){case 1:vir_led1->ODR &= (~(0X1 << 10));break;case 2:vir_led2->ODR &= (~(0X1 << 10));break;case 3:vir_led3->ODR &= (~(0X1 << 8));break;case 4:vir_fan->ODR &= (~(0X1 << 9));break;case 5:vir_ato->ODR &= (~(0X1 << 6));break;case 6:vir_wmm->ODR &= (~(0X1 << 6));break;default:return -1;}default:return -1;}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,.release = mycdev_close,.unlocked_ioctl = mycdev_ioctl,
};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_fan = vir_led1;vir_ato = vir_led2;vir_wmm = ioremap(PHY_WMM_ADDR, sizeof(gpio_t));if (vir_wmm == NULL){printk("ioremap filed:%d\n", __LINE__);return -ENOMEM;}vir_rcc = ioremap(PHY_RCC_ADDR, 4);if (vir_rcc == NULL){printk("ioremap filed:%d\n", __LINE__);return -ENOMEM;}printk("物理地址映射成功\n");// 寄存器的初始化// rcc(*vir_rcc) |= (3 << 4);(*vir_rcc) |= (1 << 1);// led1vir_led1->MODER &= (~(3 << 20));vir_led1->MODER |= (1 << 20);vir_led1->ODR &= (~(1 << 10));// led2vir_led2->MODER &= (~(3 << 20));vir_led2->MODER |= (1 << 20);vir_led2->ODR &= (~(1 << 10));// led3vir_led3->MODER &= (~(3 << 16));vir_led1->MODER |= (1 << 16);vir_led1->ODR &= (~(1 << 8));// WMM  B 6vir_wmm->MODER &= (~(3 << 12));vir_wmm->MODER |= (1 << 12);vir_wmm->ODR &= (~(1 << 6));// FAM  E 9vir_fan->MODER &= (~(3 << 18));vir_fan->MODER |= (1 << 18);vir_fan->ODR &= (~(1 << 9));// ATO  F 6vir_ato->MODER &= (~(3 << 12));vir_ato->MODER |= (1 << 12);vir_ato->ODR &= (~(1 << 6));printk("寄存器初始化成功\n");return 0;
}static int __init mycdev_init(void)
{int i;//字符设备驱动注册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");//向上提交设备节点信息for(i = 0;i < 3; i++){dev = device_create(cls,NULL,MKDEV(major,i),NULL,"myled%d",i);if(IS_ERR(dev)){printk("向上提交设备节点信息失败\n");return -PTR_ERR(dev);}}printk("向上提交设备节点信息成功\n");//寄存器映射以及初始化all_led_init();return 0;}
static void __exit mycdev_exit(void)
{int i;//设备初始化all_led_init();//取消虚拟映射iounmap(vir_led1);iounmap(vir_led2);iounmap(vir_led3);iounmap(vir_rcc);//销毁节点信息for(i = 0; i < 3; i++){device_destroy(cls,MKDEV(major,i));}//销毁目录信息class_destroy(cls);//注销字符设备驱动unregister_chrdev(major,"mycdev");printk("出口函数\n");
}module_init(mycdev_init);module_exit(mycdev_exit);MODULE_LICENSE("GPL");

fun.c

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <string.h>
#include "head.h"int main(int argc, char const *argv[])
{/* code */int a,b;char buf[128] = {0};printf("调用open\n");int fd = open ("/dev/myled0",O_RDWR);if(fd < 0){printf("打开设备文件失败\n");exit(-1);}while(1){//从终端读取printf("请输入指令\n");printf("0(关) 1(开)\n");printf("请输入>");scanf("%d",&a);if(a){printf("打开以下设备\n");}else{printf("关闭以下设备\n");}printf(" 1(LED1) 2(LED2) 3(LED3)\n");printf(" 4(FAN)  5(ATO)  6(WMM)\n");printf("请输入要控制的设备:");scanf("%d",&b);switch(a){case 1:ioctl(fd,LED_ON,&b);//开灯break;case 0:ioctl(fd,LED_OFF,&b);break;}}printf("调用close\n");close (fd);   return 0;
}

Makefile

modname ?= mycdevarch ?= armifeq ($(arch),arm)
KERNELDIR:= /home/ubuntu/13_UBOOT/linux-stm32mp-5.10.61-stm32mp-r2-r0/linux-5.10.61
else
KERNELDIR:=/lib/modules/$(shell uname -r)/build/
endifPWD:=$(shell pwd)all:make -C $(KERNELDIR) M=$(PWD) modulesclean:make -C $(KERNELDIR) M=$(PWD) cleanobj-m:=$(modname).o

 

 

相关文章:

驱动开发 day3 (模块化驱动启动led,蜂鸣器,风扇,震动马达)

模块化驱动启动led,蜂鸣器,风扇,震动马达并加上Makefile 封装模块化驱动&#xff0c;可自由安装卸载驱动&#xff0c;便于驱动更新(附图) 1.安装模块驱动同时初始化各个设备并使能 2.该驱动会自动创建驱动节点. 3.通过c函数程序输入控制各个设备 4.卸载模块驱动 //编译驱动…...

数据结构与算法基础-学习-27-图之最短路径之Dijkstra(迪杰斯特拉)算法

一、最短路径应用案例 例如从北京到上海旅游&#xff0c;有多条路可以到目的地&#xff0c;哪条路线最短&#xff0c;哪条路线最省钱&#xff0c;就是典型的最短路径问题。 二、最短路径问题分类 最短路径问题可以分为两类&#xff0c;第一类为&#xff1a;两点间最短路径。第…...

Windows Server 2012 能使用的playwright版本

由于在harkua_bot里面使用到了playwright&#xff0c;我的服务器又是Windows Server 2012 R2&#xff0c;最新版playwright不支持Windows Server 2012 R2&#xff0c;支持Windows Server 2016以上&#xff0c;所以有了这个需求 https://cdn.npmmirror.com/binaries/playwright…...

css实现溢出变为省略号

单行文本溢出省略 text-overflow&#xff1a;规定当文本溢出时&#xff0c;显示省略符号来代表被修剪的文本 white-space&#xff1a;设置文字在一行显示&#xff0c;不能换行 overflow&#xff1a;文字长度超出限定宽度&#xff0c;则隐藏超出的内容overflow设为hidden&#…...

nginx如何配置两个服务器的连接

nginx 中通过server_name listen的方式配置多个服务器 nginx配置两个站点的windows操作方法&#xff0c;双域名双站点...

Linux环境Arduino IDE中配置ATOM S3

linux选择ubuntu发行版。 硬件设备有多小呢&#xff1a; 功能超级强大。 之前的ROS1和ROS2案例已经全部移植完成并测试结束&#xff08;三轮纯人力校验&#x1f60e;&#xff09;。 官网文档信息非常非常好&#xff1a; https://docs.m5stack.com/zh_CN/quick_start/atoms3…...

【C#】.Net Framework框架下的Authorize权限类

2023年&#xff0c;第31周&#xff0c;第3篇文章。给自己一个目标&#xff0c;然后坚持总会有收货&#xff0c;不信你试试&#xff01; 在C#的.NET Framework中&#xff0c;你可以使用Authorize类来处理权限认证。Authorize类位于System.Web.Mvc命名空间中&#xff0c;它提供了…...

C++ list底层实现原理

文章目录 一、list底层实现二、类构成三、构造函数四、迭代器五、获取第一个元素六、获取最后一个元素七、插入元素 一句话&#xff1a;list底层实现一个双向循环链表 一、list底层实现 一个双向循环链表 二、类构成 class list : protected_List_base_list_base.lsit_impl…...

C#实现数字验证码

开发环境&#xff1a;VS2019&#xff0c;.NET Core 3.1&#xff0c;ASP.NET Core API 1、建立一个验证码控制器 新建两个方法Create和Check&#xff0c;Create用于创建验证码&#xff0c;Check用于验证它是否有效。 声明一个静态类变量存放列表&#xff0c;列表中存放包含令…...

Git的常用命令以及使用场景

文章目录 1.前言2.工作区,暂存区,版本库简介3.Git的常用命令4.版本回退5.撤销修改6.删除文件7.总结 1.前言 在学习Git命令之前,需要先了解工作区,暂存区和版本库这三个概念 2.工作区,暂存区,版本库简介 在使用Git进行版本控制时&#xff0c;有三个重要的概念&#xff1a;工作…...

tcp keepalive

tcp keepalive用于检查两者之间的链路是否正常&#xff0c;或防止链路断开。 一旦建立了TCP连接&#xff0c;该连接被定义为有效&#xff0c;直到一方关闭它。一旦连接进入连接状态&#xff0c;它将无限期地保持连接状态。但实际上&#xff0c;这种联系不会无限期地持续下去。如…...

PP-Matting: AI高精度图像前景Matting,让抠图轻而易举

分割和Matting的一个重要区别是:分割返回的是像素分类标签,其结果是整型数据;而Matting返回的是属于前景或背景的概率P,从而在前景与背景交互区域产生渐变的效果,使得抠图更加自然。Matting分割模型训练完成后,对于原始图像每个位置上的像素,都将生成一个表示其前景透明…...

VUE3-01

1.选项式和组合式 选项式API&#xff1a;按照作用组织代码 组合式API&#xff1a;按照功能组织代码 2.<script setup> <template><div class"about"><h1>{{name}}</h1><button click"sayHello">测试</button>…...

分库分表之基于Shardingjdbc+docker+mysql主从架构实现读写分离(二)

说明&#xff1a;如果实现了docker部署mysql并完成主从复制的话再继续&#xff0c;本篇文章主要说明springboot配置实现Shardingjdbc进行读写分离操作。 如果没实现docker部署mysql实现主从架构的话点击我 Shardingjdbc配置介绍&#xff08;版本&#xff1a;5.3.2&#xff09;…...

Python 进阶(四):日期和时间(time、datetime、calendar 模块)

❤️ 博客主页&#xff1a;水滴技术 &#x1f338; 订阅专栏&#xff1a;Python 入门核心技术 &#x1f680; 支持水滴&#xff1a;点赞&#x1f44d; 收藏⭐ 留言&#x1f4ac; 文章目录 1. time模块1.1 获取当前时间1.2 时间休眠1.3 格式化时间 2. datetime模块2.1 获取当前…...

Transformer背景介绍

目录 Transformer的诞生Transformer的优势Transformer的市场 Transformer的诞生 论文地址 Transformer的优势 Transformer的市场...

深入理解BeanDefinition和Spring Beans

深入理解BeanDefinition和Spring Beans 引言 在Spring框架中&#xff0c;BeanDefinition和Spring Beans是非常重要的概念。BeanDefinition定义了Spring Bean的元数据&#xff0c;而Spring Beans是应用程序中的对象实例。理解BeanDefinition和Spring Beans的概念和使用方法对于…...

实验六 调度器-实验部分

目录 一、知识点 1.进程调度器设计的目标 1.1.进程的生命周期 1.2.用户进程创建与内核进程创建 1.3.进程调度器的设计目标 2.ucore 调度器框架 2.1.调度初始化 2.2.调度过程 2.2.1.调度整体流程 2.2.2.设计考虑要点 2.2.3.数据结构 2.2.4.调度框架应与调度算法无关…...

基于飞桨paddle波士顿房价预测练习模型测试代码

基于飞桨paddle波士顿房价预测练习模型测试代码 导入基础库 #paddle&#xff1a;飞桨的主库&#xff0c;paddle 根目录下保留了常用API的别名&#xff0c;当前包括&#xff1a;paddle.tensor、paddle.framework、paddle.device目录下的所有API&#xff1b; import paddle #Lin…...

只会“点点点”,凭什么让开发看的起你?

众所周知&#xff0c;如今无论是大厂还是中小厂&#xff0c;自动化测试基本是标配了&#xff0c;毕竟像双 11、618 这种活动中庞大繁杂的系统&#xff0c;以及多端发布、多版本、机型发布等需求&#xff0c;但只会“写一些自动化脚本”很难胜任。这一点在招聘要求中就能看出来。…...

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

浅谈不同二分算法的查找情况

二分算法原理比较简单&#xff0c;但是实际的算法模板却有很多&#xff0c;这一切都源于二分查找问题中的复杂情况和二分算法的边界处理&#xff0c;以下是博主对一些二分算法查找的情况分析。 需要说明的是&#xff0c;以下二分算法都是基于有序序列为升序有序的情况&#xf…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

基于Java+VUE+MariaDB实现(Web)仿小米商城

仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意&#xff1a;运行前…...

数学建模-滑翔伞伞翼面积的设计,运动状态计算和优化 !

我们考虑滑翔伞的伞翼面积设计问题以及运动状态描述。滑翔伞的性能主要取决于伞翼面积、气动特性以及飞行员的重量。我们的目标是建立数学模型来描述滑翔伞的运动状态,并优化伞翼面积的设计。 一、问题分析 滑翔伞在飞行过程中受到重力、升力和阻力的作用。升力和阻力与伞翼面…...

comfyui 工作流中 图生视频 如何增加视频的长度到5秒

comfyUI 工作流怎么可以生成更长的视频。除了硬件显存要求之外还有别的方法吗&#xff1f; 在ComfyUI中实现图生视频并延长到5秒&#xff0c;需要结合多个扩展和技巧。以下是完整解决方案&#xff1a; 核心工作流配置&#xff08;24fps下5秒120帧&#xff09; #mermaid-svg-yP…...

如何在Windows本机安装Python并确保与Python.NET兼容

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…...

【大模型】RankRAG:基于大模型的上下文排序与检索增强生成的统一框架

文章目录 A 论文出处B 背景B.1 背景介绍B.2 问题提出B.3 创新点 C 模型结构C.1 指令微调阶段C.2 排名与生成的总和指令微调阶段C.3 RankRAG推理&#xff1a;检索-重排-生成 D 实验设计E 个人总结 A 论文出处 论文题目&#xff1a;RankRAG&#xff1a;Unifying Context Ranking…...