华清远见嵌入式学习——春节作业——2.15日

作业要求:

编写led驱动,通过应用程序控制三盏灯亮灭

作业答案:

作业效果:

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 *moder_e;
unsigned int *odr_e;
unsigned int *moder_f;
unsigned int *odr_f;
unsigned int *rcc;

/*
// 延时函数
void delay(int ms)
{

    int i, j;
    for (i = 0; i < ms; i++)
    {
        for (j = 0; j < 2000; j++)
        {
        }
    }
}
*/

// 封装常用的操作方法
int mychrdev_open(struct inode *inode, struct file *file)
{
    printk("调用mychrdev_open成功,%d\n", __LINE__);
    return 0;
}

ssize_t mychrdev_read(struct file *file, char __user *ubuf, size_t size, loff_t *lof)
{
    printk("调用成功mychrdev_read,%d\n", __LINE__);

    // 用户调用了read后会调用这个函数
    // 所以是从内核空间向用户空间写

    unsigned int ret; // 用于接收返回值,判断是否成功
    ret = copy_to_user(ubuf, kbuf, size);
    if (ret)
    {
        printk("数据拷贝失败\n");
        return -ret;
    }

    return 0;
}

ssize_t mychrdev_write(struct file *file, const char __user *ubuf, size_t size, loff_t *lof)
{
    printk("调用mychrdev_write成功,%d\n", __LINE__);
    // 用户调用了write后会调用这个函数
    // 所以是从用户空间向内核空间写

    unsigned int ret; // 用于接收返回值,判断是否成功
    ret = copy_from_user(kbuf, ubuf, size);
    if (ret)
    {
        printk("数据拷贝失败\n");
        return -ret;
    }

    if (kbuf[0] == '0') // 开1号灯
    {
        (*odr_e) |= (0x1 << 10);
    }
    else if (kbuf[0] == '1') // 开2号灯
    {
        (*odr_f) |= (0x1 << 10);
    }
    else if (kbuf[0] == '2') // 开3号灯
    {
        (*odr_e) |= (0x1 << 8);
    }
    else if (kbuf[0] == '3') // 开三个灯
    {
            (*odr_e) |= (0x1 << 10);
            (*odr_f) |= (0x1 << 10);
            (*odr_e) |= (0x1 << 8);
    }
    else if (kbuf[0] == '4') // 关1号灯
    {
        (*odr_e) &= (~(0x1 << 10));
    }
    else if (kbuf[0] == '5') // 关2号灯
    {
        (*odr_f) &= (~(0x1 << 10));
    }
    else if (kbuf[0] == '6') // 关3号灯
    {
        (*odr_e) &= (~(0x1 << 8));
    }
    else if (kbuf[0] == '7') // 关三个灯
    {
        (*odr_e) &= (~(0x1 << 10));
        (*odr_f) &= (~(0x1 << 10));
        (*odr_e) &= (~(0x1 << 8));
    }

    return 0;
}

int mychrdev_close(struct inode *inode, struct file *file)
{
    printk("调用mychrdev_close成功,%d\n", __LINE__);
    return 0;
}

// 定义操作方法指针
struct file_operations fops = {
    .open = mychrdev_open,
    .read = mychrdev_read,
    .write = mychrdev_write,
    .release = mychrdev_close};

static int __init mycdev_init(void)
{
    // 注册字符设备驱动
    // 填0代表动态申请主设备号
    major = register_chrdev(0, "mychrdev", &fops);

    // 申请失败
    if (major < 0)
    {
        printk("注册字符设备驱动失败 %d\n", __LINE__);
    }
    printk("注册字符设备驱动成功 major = %d\n", major);

    // 进行LED寄存器的地址映射
    moder_e = ioremap(GPIOE_MODER, 4);
    if (moder_e == NULL)
    {
        printk("地址映射失败%d\n", __LINE__);
        return 0;
    }
    moder_f = ioremap(GPIOF_MODER, 4);
    if (moder_f == NULL)
    {
        printk("地址映射失败%d\n", __LINE__);
        return 0;
    }
    odr_e = ioremap(GPIOE_ODR, 4);
    if (odr_e == NULL)
    {
        printk("地址映射失败%d\n", __LINE__);
        return 0;
    }
    odr_f = ioremap(GPIOF_ODR, 4);
    if (odr_f == NULL)
    {
        printk("地址映射失败%d\n", __LINE__);
        return 0;
    }
    rcc = ioremap(RCC_GPIO, 4);
    if (rcc == NULL)
    {
        printk("地址映射失败%d\n", __LINE__);
        return 0;
    }
    printk("地址映射成功\n");
    // 硬件初始化
    // 使能时钟
    (*rcc) |= (0X3 << 4);
    // 设置PE10、PF10、PE8为输出
    (*moder_e) &= (~(0X3 << 20));
    (*moder_e) |= (0X1 << 20);
    (*moder_f) &= (~(0X3 << 20));
    (*moder_f) |= (0X1 << 20);
    (*moder_e) &= (~(0X3 << 16));
    (*moder_e) |= (0X1 << 16);
    // 默认输出低电平
    (*odr_e) &= (~(0x1 << 10));
    (*odr_f) &= (~(0x1 << 10));
    (*odr_e) &= (~(0x1 << 8));
    return 0;
}
static void __exit mycdev_exit(void)
{
    // 取消内存映射
    iounmap(moder_e);
    iounmap(odr_e);
    iounmap(moder_f);
    iounmap(odr_f);
    iounmap(rcc);

    // 注销字符设备驱动
    unregister_chrdev(major, "mychrdev");
    printk("注销字符设备驱动成功 %d\n", __LINE__);
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

led.c

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

int main(int argc,const char * argv[])
{
    //用于接收读取到的数据
    char buf[128] = {};
    //打开自定义字符设备文件
    int fd = open("/dev/mychrdev",O_RDWR);
    //当打开失败时
    if(fd < 0)
    {
        printf("打开自定义字符设备文件失败\n");
        return -1;
    }
    //开关灯的逻辑控制
    while (1)
    {
        printf("请输入控制码:0(开1号灯) 1(开2号灯) 2(开3号灯) \
        3(开三个灯) 4(关1号灯) 5(关2号灯) \
        6(关3号灯) 7(关三个灯)>");
        fgets(buf, sizeof(buf), stdin); // 从终端输入一个数据
        buf[strlen(buf) - 1] = '\0';
        write(fd, buf, sizeof(buf));
    }

    //关闭
    close(fd);

    return 0;
}

head.h

#ifndef __HEAD_H__
#define __HEAD_H__
 
#define GPIOE_MODER 0X50006000
#define GPIOF_MODER 0X50007000
#define GPIOE_ODR   0X50006014
#define GPIOF_ODR   0X50007014
#define RCC_GPIO    0X50000A28
 
#endif

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

单源最短路建图方式例题整理

1129. 热浪&#xff08;活动 - AcWing&#xff09; 思路&#xff1a;题目只是加了一个背景&#xff0c;但实际上还是很裸的单源最短路问题。我们有四种写法&#xff0c;bellman_ford算法时间复杂度不如spfa&#xff0c;而且这里对边数没有限定&#xff0c;所以没必要使用bellma…

【JAVA-Day77】Java线程继承Thread类实现Runnable接口

Java线程继承Thread类实现Runnable接口 《Java线程编程指南&#xff1a;轻松掌握线程的创建和启动》摘要 &#x1f60a;引言 &#x1f680;一、什么是进程和线程 ❓二、线程如何创建 &#x1f60e;2.1 继承Thread类并重写run()方法 &#x1f4dd;2.2 实现Runnable接口并实现run…

jvm 内存模型介绍

一、类加载子系统 1、类加载的过程&#xff1a;装载、链接、初始化&#xff0c;其中&#xff0c;链接又分为验证、准备和解析 装载&#xff1a;加载class文件 验证&#xff1a;确保字节流中包含信息符合当前虚拟机要求 准备&#xff1a;分配内存&#xff0c;设置初始值 解析&a…

Protégé pizza 03 Install Protege - 本体编辑器 Ontology Editor

Protege是一款非常方便使用的开源的本体&#xff08;ontology&#xff09;编辑器&#xff0c;可以用来建立知识图谱。 这个视频介绍了Protege工具的安装&#xff0c;是学习pizza.owl系列知识的前提。 https://v.youku.com/v_show/id_XNjE1NDc0NTU3Mg.html

【JAVA】计算机软件工程人工智能研究生复试资料整理

1、JAVA 2、计算机网络 3、计算机体系结构 4、数据库 5、计算机租场原理 6、软件工程 7、大数据 8、英文 自我介绍 1. Java 1. == 和 equals的区别 比较基本数据类型是比较的值,引用数据类型是比较两个是不是同一个对象,也就是引用是否指向同 一个对象,地址是否相同,equ…

精读Relational Embedding for Few-Shot Classification (ICCV 2021)

Relational Embedding for Few-Shot Classification (ICCV 2021) 一、摘要 该研究提出了一种针对少样本分类问题的新方法&#xff0c;通过元学习策略来学习“观察什么”和“在哪里关注”。这种方法依赖于两个关键模块&#xff1a;自相关表示&#xff08;SCR&#xff09;和交叉…

OS内存管理

内存 定义 内存是计算机用于存储数据和程序的硬件设备&#xff0c;它允许计算机快速读取和写入数据。内存通常是临时存储&#xff0c;其内容在计算机关闭或断电时会丢失。内存可存放数据。程序执行前需要先放到内存中才能被CPU处理(缓和CPU与硬盘之间的速度矛盾)。 在多道程…

ZBX_NOTSUPPORTED: Unsupported item key. 原因排查

进行自定义监控项时&#xff0c;在zabbix-agent端测试没问题&#xff0c;却在zabbix-server进行测试时&#xff0c;出现 ZBX_NOTSUPPORTED: Unsupported item key. 1.在zabbix-agent测试没问题&#xff0c;证明自定义监控项的脚本没问题&#xff0c;却在zabbix-server端测试出…

表的连接

目录 内连接实现效果 使用左外连接&#xff0c;将所有的员工信息都显示出来&#xff0c;即便他没有对应的部门 使用右外连接&#xff0c;将所有的部门信息都显示出来 查询每个员工的编号、姓名、职位&#xff0c;以及所在各部门的领导姓名、领导职位 确定所需要的数据表 确…

IMX6ULL移植U-Boot 2022.04

目录 目录 1.编译环境以及uboot版本 2.默认编译测试 3.uboot中新增自己的开发板 3.编译测试 4.烧录测试 5.patch文件 1.编译环境以及uboot版本 宿主机Debian12u-boot版本lf_v2022.04 ; git 连接GitHub - nxp-imx/uboot-imx: i.MX U-Boot交叉编译工具gcc-arm-10.3-2021.0…

机器学习:卷积介绍及代码实现卷积操作

传统卷积运算是将卷积核以滑动窗口的方式在输入图上滑动&#xff0c;当前窗口内对应元素相乘然后求和得到结果&#xff0c;一个窗口一个结果。相乘然后求和恰好也是向量内积的计算方式&#xff0c;所以可以将每个窗口内的元素拉成向量&#xff0c;通过向量内积进行运算&#xf…

关于nuclei-ai-extension

nuclei-ai-extension &#x1f341; Nuclei 官方开发的 利用 AI 生成 nuclei 模板的工具。Nuclei AI - 用于快速生成 Nuclei 模板的浏览器扩展&#xff0c;Nuclei AI Browser Extension建立在 cloud.projectdiscovery.io 之上&#xff0c;使用户能够从任何网页中提取漏洞信息&…

设计模式之创建型模式

创建型模式提供创建对象的机制,能够提升已有代码的灵活性和复用性 常用的有&#xff1a;单例模式、工厂模式&#xff08;工厂方法和抽象工厂&#xff09;、建造者模式。 不常用的有&#xff1a;原型模式。 4.1 单例模式 创建型模式提供创建对象的机制,能够提升已有代码的灵…

【MATLAB】在图框中加箭头文本注释

1、在图框中加 文本方法 —— text&#xff08;&#xff09;函数 2、使用箭头标注——annotation&#xff08;&#xff09;函数 X、Y是箭头的位置相对于整个方框的比例&#xff0c; [0.32,0.5]是指&#xff1a;x坐标从整个图形32%的地方到50%的地方&#xff08;从左到右&…

基于laravel开发的开源交易所源码|BTC交易所/ETH交易所/交易所/交易平台/撮合交易引擎

开源交易所&#xff0c;基于Laravel开发的交易所 | BTC交易所 | ETH交易所 | 交易所 | 交易平台 | 撮合交易引擎。本项目有完整的撮合交易引擎源码、后台管理&#xff08;后端前端&#xff09;、前台&#xff08;交易页面、活动页面、个人中心等&#xff09;、安卓APP源码、苹果…

【蓝桥杯单片机入门记录】认识单片机

目录 单片机硬件平台 单片机的发展过程 单片机开发板 单片机基础知识 电平 数字电路中只有两种电平&#xff1a;高和低 二进制&#xff08;8421码&#xff09; 十六进制 二进制数的逻辑运算 “与” “或” “异或” 标准C与C51 如何学好单片机 端正学习的态度、培…

BUGKU-WEB 矛盾

题目描述 进入场景看看&#xff1a; 代码如下&#xff1a; $num$_GET[num]; if(!is_numeric($num)) { echo $num; if($num1) echo flag{**********}; }解题思路 需要读懂一下这段PHP代码的意思明显是一道get相关的题目&#xff0c;需要提供一个num的参数,然后需要传入一个不…

CSGO搬砖项目怎么样?分享一下个人的看法!

对于steam搬砖平台&#xff0c;无人不知&#xff0c;无人不晓啊&#xff0c;全球最大的一个游戏平台&#xff0c;像我们知道的PUBG&#xff0c;CS:GO&#xff0c;都是里面的&#xff0c;比较火的一个平台。 对于想了解Steam搬砖的&#xff0c;今天分享一下个人的看法。 首先&a…

【C语言】数据结构#实现堆

目录 &#xff08;一&#xff09;堆 &#xff08;1&#xff09;堆区与数据结构的堆 &#xff08;二&#xff09;头文件 &#xff08;三&#xff09;功能实现 &#xff08;1&#xff09;堆的初始化 &#xff08;2&#xff09;堆的销毁 &#xff08;3&#xff09;插入数据 …

java中stream流中的concat合并操作

可以用stream.of来合并两个流 public class Test7concat {public static void main(String[] args) {/*Stream流:static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b);合并2个流中的元素*/Stream<String> stream1 St…
最新文章