驱动开发 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 封装模块化驱动,可自由安装卸载驱动,便于驱动更新(附图) 1.安装模块驱动同时初始化各个设备并使能 2.该驱动会自动创建驱动节点. 3.通过c函数程序输入控制各个设备 4.卸载模块驱动 //编译驱动…...
数据结构与算法基础-学习-27-图之最短路径之Dijkstra(迪杰斯特拉)算法
一、最短路径应用案例 例如从北京到上海旅游,有多条路可以到目的地,哪条路线最短,哪条路线最省钱,就是典型的最短路径问题。 二、最短路径问题分类 最短路径问题可以分为两类,第一类为:两点间最短路径。第…...
Windows Server 2012 能使用的playwright版本
由于在harkua_bot里面使用到了playwright,我的服务器又是Windows Server 2012 R2,最新版playwright不支持Windows Server 2012 R2,支持Windows Server 2016以上,所以有了这个需求 https://cdn.npmmirror.com/binaries/playwright…...
css实现溢出变为省略号
单行文本溢出省略 text-overflow:规定当文本溢出时,显示省略符号来代表被修剪的文本 white-space:设置文字在一行显示,不能换行 overflow:文字长度超出限定宽度,则隐藏超出的内容overflow设为hidden&#…...
nginx如何配置两个服务器的连接
nginx 中通过server_name listen的方式配置多个服务器 nginx配置两个站点的windows操作方法,双域名双站点...
Linux环境Arduino IDE中配置ATOM S3
linux选择ubuntu发行版。 硬件设备有多小呢: 功能超级强大。 之前的ROS1和ROS2案例已经全部移植完成并测试结束(三轮纯人力校验😎)。 官网文档信息非常非常好: https://docs.m5stack.com/zh_CN/quick_start/atoms3…...
【C#】.Net Framework框架下的Authorize权限类
2023年,第31周,第3篇文章。给自己一个目标,然后坚持总会有收货,不信你试试! 在C#的.NET Framework中,你可以使用Authorize类来处理权限认证。Authorize类位于System.Web.Mvc命名空间中,它提供了…...
C++ list底层实现原理
文章目录 一、list底层实现二、类构成三、构造函数四、迭代器五、获取第一个元素六、获取最后一个元素七、插入元素 一句话:list底层实现一个双向循环链表 一、list底层实现 一个双向循环链表 二、类构成 class list : protected_List_base_list_base.lsit_impl…...
C#实现数字验证码
开发环境:VS2019,.NET Core 3.1,ASP.NET Core API 1、建立一个验证码控制器 新建两个方法Create和Check,Create用于创建验证码,Check用于验证它是否有效。 声明一个静态类变量存放列表,列表中存放包含令…...
Git的常用命令以及使用场景
文章目录 1.前言2.工作区,暂存区,版本库简介3.Git的常用命令4.版本回退5.撤销修改6.删除文件7.总结 1.前言 在学习Git命令之前,需要先了解工作区,暂存区和版本库这三个概念 2.工作区,暂存区,版本库简介 在使用Git进行版本控制时,有三个重要的概念:工作…...
tcp keepalive
tcp keepalive用于检查两者之间的链路是否正常,或防止链路断开。 一旦建立了TCP连接,该连接被定义为有效,直到一方关闭它。一旦连接进入连接状态,它将无限期地保持连接状态。但实际上,这种联系不会无限期地持续下去。如…...
PP-Matting: AI高精度图像前景Matting,让抠图轻而易举
分割和Matting的一个重要区别是:分割返回的是像素分类标签,其结果是整型数据;而Matting返回的是属于前景或背景的概率P,从而在前景与背景交互区域产生渐变的效果,使得抠图更加自然。Matting分割模型训练完成后,对于原始图像每个位置上的像素,都将生成一个表示其前景透明…...
VUE3-01
1.选项式和组合式 选项式API:按照作用组织代码 组合式API:按照功能组织代码 2.<script setup> <template><div class"about"><h1>{{name}}</h1><button click"sayHello">测试</button>…...
分库分表之基于Shardingjdbc+docker+mysql主从架构实现读写分离(二)
说明:如果实现了docker部署mysql并完成主从复制的话再继续,本篇文章主要说明springboot配置实现Shardingjdbc进行读写分离操作。 如果没实现docker部署mysql实现主从架构的话点击我 Shardingjdbc配置介绍(版本:5.3.2)…...
Python 进阶(四):日期和时间(time、datetime、calendar 模块)
❤️ 博客主页:水滴技术 🌸 订阅专栏:Python 入门核心技术 🚀 支持水滴:点赞👍 收藏⭐ 留言💬 文章目录 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框架中,BeanDefinition和Spring Beans是非常重要的概念。BeanDefinition定义了Spring Bean的元数据,而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:飞桨的主库,paddle 根目录下保留了常用API的别名,当前包括:paddle.tensor、paddle.framework、paddle.device目录下的所有API; import paddle #Lin…...
只会“点点点”,凭什么让开发看的起你?
众所周知,如今无论是大厂还是中小厂,自动化测试基本是标配了,毕竟像双 11、618 这种活动中庞大繁杂的系统,以及多端发布、多版本、机型发布等需求,但只会“写一些自动化脚本”很难胜任。这一点在招聘要求中就能看出来。…...
屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...
【C++】纯虚函数类外可以写实现吗?
1. 答案 先说答案,可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...
pycharm 设置环境出错
pycharm 设置环境出错 pycharm 新建项目,设置虚拟环境,出错 pycharm 出错 Cannot open Local Failed to start [powershell.exe, -NoExit, -ExecutionPolicy, Bypass, -File, C:\Program Files\JetBrains\PyCharm 2024.1.3\plugins\terminal\shell-int…...
[拓扑优化] 1.概述
常见的拓扑优化方法有:均匀化法、变密度法、渐进结构优化法、水平集法、移动可变形组件法等。 常见的数值计算方法有:有限元法、有限差分法、边界元法、离散元法、无网格法、扩展有限元法、等几何分析等。 将上述数值计算方法与拓扑优化方法结合&#…...
字符串哈希+KMP
P10468 兔子与兔子 #include<bits/stdc.h> using namespace std; typedef unsigned long long ull; const int N 1000010; ull a[N], pw[N]; int n; ull gethash(int l, int r){return a[r] - a[l - 1] * pw[r - l 1]; } signed main(){ios::sync_with_stdio(false), …...
2025-05-08-deepseek本地化部署
title: 2025-05-08-deepseek 本地化部署 tags: 深度学习 程序开发 2025-05-08-deepseek 本地化部署 参考博客 本地部署 DeepSeek:小白也能轻松搞定! 如何给本地部署的 DeepSeek 投喂数据,让他更懂你 [实验目的]:理解系统架构与原…...
CppCon 2015 学习:REFLECTION TECHNIQUES IN C++
关于 Reflection(反射) 这个概念,总结一下: Reflection(反射)是什么? 反射是对类型的自我检查能力(Introspection) 可以查看类的成员变量、成员函数等信息。反射允许枚…...
