【驱动开发】实现三盏灯的控制,编写应用程序测试

news/2024/10/17 21:22:19/

head.h

#ifndef __HEAD_H__
#define __HEAD_H__//LED1:PE10
//LED2:PF10
//LED3:PE8#define LED_RCC 0X50000A28         //使能GPIO#define LED_MODER 0X50006000      //设置输出模式
#define LED_ODR 0X50006014        //设置输出高低电平#define LED2_MODER 0X50007000       //设置输出模式
#define LED2_ODR 0X50007014         //设置输出高低电平#endif

mychrdev.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include "head.h"unsigned int major; //保存主设备号
char kbuf[128] = {0};unsigned int *vir_rcc;
unsigned int *vir_moder;
unsigned int *vir_odr;
unsigned int *vir_moder_led2;
unsigned int *vir_odr_led2;//封装操作方法
int mycdev_open(struct inode *inode,struct file *file)
{printk("%s:%s:%d\n",__FILE__,__func__,__LINE__); return 0;
}ssize_t mycdev_read(struct file *file,char *ubuf,size_t size,loff_t *lof)
{// printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);int ret;ret = copy_to_user(ubuf,kbuf,size);if(ret){printk("copy_to_user err\n");return -EIO;}return 0;
}ssize_t mycdev_write(struct file *file,const char *ubuf,size_t size,loff_t *lof)
{//printk("%s:%s:%d\n",__FILE__,__func__,__LINE__); int ret;ret = copy_from_user(kbuf,ubuf,size);if(ret){printk("copy_from_user err\n");return -EIO;}//控制LED1-LED3开和关if(kbuf[0] == '1')      //开灯{(*vir_odr) |= (0x1<<10);    //输出高电平(*vir_odr_led2) |= (0x1<<10);    //输出高电平(*vir_odr) |= (0x1<<8);    //输出高电平}else if(kbuf[0] == '0') //关灯{(*vir_odr) &= (~(0x1<<10));  //输出低电平(*vir_odr_led2) &= (~(0x1<<10));    //输出高电平(*vir_odr) &= (~(0x1<<8));    //输出高电平}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,.read = mycdev_read,.write = mycdev_write,.release = mycdev_close,
};   static int __init mycdev_init(void) //入口函数  安装内核模块时执行
{major=register_chrdev(0,"mychrdev",&fops);     //字符设备驱动的注册if(major<0){printk("字符设备驱动注册失败\n");return major;}printk("字符设备驱动注册成功 major=%d\n",major);//进行LED控制相关寄存器的内存映射vir_rcc = ioremap(LED_RCC,4);if(vir_rcc == NULL){printk("物理内存映射失败%d\n",__LINE__);return -EFAULT;}vir_moder = ioremap(LED_MODER,4);if(vir_moder == NULL){printk("物理内存映射失败%d\n",__LINE__);return -EFAULT;}vir_odr = ioremap(LED_ODR,4);if(vir_odr == NULL){printk("物理内存映射失败%d\n",__LINE__);return -EFAULT;}vir_moder_led2 = ioremap(LED2_MODER,4);if(vir_moder_led2 == NULL){printk("物理内存映射失败%d\n",__LINE__);return -EFAULT;}vir_odr_led2 = ioremap(LED2_ODR,4);if(vir_odr_led2 == NULL){printk("物理内存映射失败%d\n",__LINE__);return -EFAULT;}printk("寄存器内存映射成功\n");//控制led1-led3硬件寄存器的初始化(*vir_rcc) |= (0x1<<4);         //RCC使能GPIO E组(*vir_rcc) |= (0x1<<5);         //RCC使能GPIO F组(*vir_moder) &= (~(0x3<<20));   //设置PE10为输出(*vir_moder) |= (0x1<<20);(*vir_moder_led2) &= (~(0x3<<20));   //设置PF10为输出(*vir_moder_led2) |= (0x1<<20);  (*vir_moder) &= (~(0x3<<16));       //设置PE8为输出(*vir_moder) |= (0x1<<16);    (*vir_odr) &= (~(0x1<<10));         //设置led1默认关灯(*vir_odr_led2) &= (~(0x1<<10));    //设置led2默认关灯(*vir_odr) &= (~(0x1<<8));          //设置led3默认关灯return 0;
}static void __exit mycdev_exit(void)    //出口函数,卸载内核模块时执行
{iounmap(vir_moder);         //取消物理内存映射iounmap(vir_moder_led2);    //取消物理内存映射iounmap(vir_odr);           //取消物理内存映射iounmap(vir_odr_led2);      //取消物理内存映射iounmap(vir_rcc);           //取消物理内存映射unregister_chrdev(major,"mychrdev");  //注销字符设备驱动
}module_init(mycdev_init);   //用于声明当前内核模块入口函数的地址
module_exit(mycdev_exit);   //用于声明当前内核模块出口函数的地址
MODULE_LICENSE("GPL");  //声明当前内核模块遵循GPL协议

led_test.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.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){   //控制LED亮和灭printf("请输入LED的控制命令:1(开灯),0(关灯) >>");fgets(buf,sizeof(buf),stdin);       //从终端输入数据传递到buf中buf[strlen(buf)-1] = '\0';          //末尾替换\nwrite(fd,buf,sizeof(buf));   }return 0;
}

 测试结果如下:

   


http://www.ppmy.cn/news/1103826.html

相关文章

粉底液、口红、睫毛膏,眼膜等护肤品和彩妆上架亚马逊需要做什么认证?HRIPT/RIPT测试,斑贴测试,COA认证和BCOP认证办理

亚马逊要求化妆、美容类睫毛膏、眼膜、足贴、假睫毛、洗发水、美甲套装等HRIPT / RIPTCOA测试&#xff0c;如果是眼睛这个部位使用的话 还需要出示BCOP认证 为了确保在使用产品或原料后不会产生潜在的刺激或过敏。亚马逊要求化妆品&#xff0c;美容产品&#xff0c;指甲胶等需…

Vue 组件中如何引入外部的js文件

Vue 组件中如何引入外部的js文件 背景 在Vue中&#xff0c;通常我们引入一个js插件都是使用npm 方式下载然后import使用的。但是我现在本地有了js文件或者是一个远程js文件链接&#xff0c;我不想使用npm install xxx 的方式&#xff0c;有什么办法吗&#xff1f; 方式一 简…

抖音小程序开发教学系列(5)- 抖音小程序数据交互

第五章&#xff1a;抖音小程序数据交互 5.1 抖音小程序的网络请求5.1.1 抖音小程序的网络请求方式和API介绍5.1.2 抖音小程序的数据请求示例和错误处理方法 5.2 抖音小程序的数据缓存和本地存储5.2.1 抖音小程序的数据缓存机制和使用方法5.2.2 抖音小程序的本地存储和数据持久化…

【深度学习】 Python 和 NumPy 系列教程(七):Python函数

目录 一、前言 二、实验环境 三、Python函数基础 1. 定义函数 2. 参数传递 3. 函数调用 4. 返回值 5. 函数文档字符串 四、将函数存储在模块中 1. 创建模块 2. 导入模块 a. import 模块名 b. from 模块名 import 函数名 c. from 模块名 import * 五、多种形式的…

多语言开发(vant

参考&#xff1a;https://blog.csdn.net/qq_44649801/article/details/131878128?spm1001.2014.3001.5506 一、抛出字段对象A export default { } 二、引入汇总文件&#xff0c;&#xff08;主要的是 模块分割 汇总&#xff0c;对A 等的处理 export default { A&#xff0c;B,…

微信小程序云开发数据懒加载+打破云数据库返回数据条数限制

目录 数据懒加载 打破数据表返回条数限制 数据懒加载 show.wxml <view wx:for="{{Adata}}" wx:key="index" style="padding: 80rpx 10rpx 140rpx;border-bottom: rgb(109, 134, 134) 2px solid;"><view style="margin-left: 20…

什么?这个策略可以加速大模型推理2-2.5倍以上?

今天我要分享的是deepmind团队的文章《Accelerating Large Language Model Decoding with Speculative Sampling》 代码 https://github.com/shreyansh26/Speculative-Sampling 背景 short continuations 指在给定的文本中&#xff0c;后续的一小段文本 the latency of p…

DQN算法概述及基于Pytorch的DQN迷宫实战代码

一. DQN算法概述 1.1 算法定义 Q-Learing是在一个表格中存储动作对应的奖励值&#xff0c;即状态-价值函数Q(s,a)&#xff0c;这种算法存在很大的局限性。在现实中很多情况下&#xff0c;强化学习任务所面临的状态空间是连续的&#xff0c;存在无穷多个状态&#xff0c;这种情…