继第一节第一个驱动程序框架记录之后,本篇文章将会在上一篇驱动程序的框架下编写点亮LED的驱动程序,同样会对上一个框架进行修改,优化。接下来进入正题
1、点亮LED程序框架分析

在最开始之前先来梳理一下点亮LED程序的框架
1、通过对驱动程序的框架分析,我们知道第一步都要从入口函数开始,第一个驱动里我写的入口函数很简单,只是完成了必要操作
这里的话就要进行改进。
2、要点亮LED首先要对LED使用的引脚进行配置,引脚的模式只用配置一次,所以该部分工作放在打开设备文件时进行,
因为设备文件也只是打开一次。
3、对LED进行点亮或者熄灭处理,在写应用程序时我们一般通过write函数进行写文件操作,所以,这一部分比较频繁的操作同样
放在了驱动程序的write函数里。

内容就是这些,在简单梳理之后就可以写程序了
2、程序

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
static struct class *first_class;
static struct class_device *fisrst_class_device;volatile unsigned long *gpfcon = NULL;
volatile unsigned long *gpfdat = NULL;static int leddrv_open(struct inode *inode, struct file *file)
{*gpfcon &= ~((3 << 8) | (3 << 10) | (3 << 12));*gpfcon |= ((1 << 8) | (1 << 10) | (1 << 12));return 0;
}
static ssize_t leddrv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
{int val;copy_from_user(&val, buf, count);if (val == 1) {*gpfdat &= ~((1 << 4) | (1 << 5) | (1 << 6));} else {*gpfdat |= ((1 << 4) | (1 << 5) | (1 << 6));}return 0;}
struct file_operations leddrv_fops = {.owner  =   THIS_MODULE,.open   =   leddrv_open,     .write = leddrv_write,
};//入口函数
int major;
static int leddrv_init(void)
{major = register_chrdev(0, "led_drv", &leddrv_fops); first_class = class_create(THIS_MODULE, "led_drv");fisrst_class_device = class_device_create(first_class, NULL,MKDEV(major,0),NULL,"led");gpfcon = (volatile unsigned long *)ioremap(0x56000050, 16);gpfdat = gpfcon + 1;return 0;
}
//出口函数
static void leddrv_exit(void)
{unregister_chrdev(major, "led_drv");class_device_unregister(fisrst_class_device);class_destroy(first_class);iounmap(gpfcon);
}
module_init(leddrv_init);
module_exit(leddrv_exit);
MODULE_LICENSE("GPL");

测试程序

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main(int argc, char **argv)
{int fd;int val = 1;fd = open("/dev/led", O_RDWR);if (fd < 0){printf("can't open!\n");}if (argc != 2){printf("Usage :\n");printf("%s <on|off>\n", argv[0]);return 0;}if (strcmp(argv[1], "on") == 0){val  = 1;}else{val = 0;}write(fd, &val, 4);return 0;
}

3、总结

驱动程序改进的地方:
1、第一节中在注册设备驱动的时候,选择的主设备号是固定的,是通过我们查找了一个空闲的设备号来确定的,
这样的做法肯定是不方便的,那么,在上面的程序中,在注册设备驱动的时候传入的主设备号为0的
时候,内核就会给我们自动分配一个空闲的主设备号,在卸载的时候使用该设备号卸载驱动程序。
2、在上一节中只是完成了编写、插入一个驱动模块的工作,在打开设备文件时发现并没有设备文件,然后
我们通过手动执行mknod命令创建了一个设备文件,才完成了后续操作,在这一节中我们使用
"class_create"和"class_device_create"创建了一个类和类下的一个设备,
那么什么是类呢?我们插入的驱动模式内核都把他当做是一个类来看待,在"/sys/class"目录下就有使用
class_create函数创建的类文件,在该文件夹里有一个设备文件,是以我们创建时候命名的设备来命名的,
进入该设备文件夹里,使用"cat dev"命令,可以显示该设备驱动的主次设备号,
实际上内核在自动创建/dev/目录下的设备节点时就是使用该信息进行创建的。
3、硬件使用的地址都是物理地址,但是在内核中使用的地址是虚拟地址,所以在操作LED设备物理地址
的时候首先需要把该地址转换为虚拟地址,这里使用"ioremap"函数进行映射,在出口函数里使用
"iounmap"函数把之前映射的地址取消
4、用户空间的write函数调用的是驱动层的write函数,它们之间必须有参数的传递过程,在驱动函数write的参数中,
第二个和第三个参数就是用户空间传递下来的缓冲区和数据的长度,使用"copy_from_user"函数把数据拷贝到
内核空间中供我们使用,同样使用"copy_to_user"函数把数据从内核空间拷贝到用户空间
5、一系列工作做完之后就可以像裸机那样去操作LED灯了,进行点亮或者熄灭

结果:
注册的字符设备,主设备号是252

进入/sys/class目录,发现注册的类

进入led_drv目录下,查看类里面的设备

再进入文件夹,查看设备的主次编号

结果和我们注册时候写的是一样的,到这里,简单的点亮LED的驱动程序就已经完成

使用驱动程序点亮LED灯相关推荐

  1. 第一个驱动程序(点亮LED灯)

    1.概述 一个软件系统分为:应用程序.库.操作系统.驱动程序. (1)应用程序使用库函数提供的open打开LED设备文件. (2)库根据open函数传入的参数执行"swi"指令,引 ...

  2. STM32笔记2-使用库函数点亮LED灯

    目录 一.硬件电路设计 二.软件设计 1.工程配置 2.程序编写 (1)led头文件 (2)Led_Init()函数编写 三.实验测试 四.使用宏定义 1.修改后的led.h中程序 2.修改后的Led ...

  3. 和12岁小同志搞创客开发:手撕代码,点亮LED灯

    目录 1.Arduino编程架构 2.点亮LED灯 机缘巧合在网上认识一位12岁小同志,从零开始系统辅导其创客开发思维和技巧. 项目专栏:https://blog.csdn.net/m0_381069 ...

  4. STM32F 103C8T6开发板 点亮LED灯

    每组IO口含下面7个寄存器.7个寄存器可以控制一组GPIO的16个IO口. GPIOx_CRL:端口配置低寄存器 GPIOx_CRH:端口配置高寄存器 GPIOx_IDR:端口输入寄存器 GPIOx_ ...

  5. STC89C52单片机 点亮LED灯

    点亮LED灯 一.什么是LED LED全称为半导体发光二极管,采用半导体材料制成的,以直接将电能转化为光能,电号转换成光信号的发光器件:其特点是功耗低.高亮度.色彩艳丽.坑振动.寿命长(正常发光8-1 ...

  6. Raspberry PI 系列 —— 裸机点亮LED灯

    Raspberry PI 系列 -- 裸机点亮LED灯 背景 近期刚买了Raspberry PI B+,配置执行了官方提供的Raspbian系统,折腾了一周Linux系统,感觉没啥意思,于是就试着想了 ...

  7. 蓝桥杯小白系列之汇编点亮led灯

    蓝桥杯小白系列之汇编点亮led灯 1.源代码 2.逐条分析 (1)ORG 0000H (2)START: 伪指令,编译器可识别,单片机不可识别,可以随便起. (3)蜂鸣器设置 蓝桥板插电以后蜂鸣器常会 ...

  8. 【STM32】STM32CubeMX教程二--基本使用(新建工程点亮LED灯)

    前言 在配置好CubeMX之后,就是新建工程的开始了,那么首先我们需要一些准备,本片博客我们会很详细的介绍STM32CubeMx的基本使用和如何创建一个新的工程并且点亮LED灯  面向初学者   如果 ...

  9. STM8学习笔记---点亮LED灯

    对单片机操作时一般有三个步骤,1.系统时钟选择.2.单片机外设初始化.3主程序编写. 同样要点亮LED灯时,也要按照这个步骤来. 首先选择系统时钟,打开STM8S中文参考手册,找到时钟寄存器 可以看到 ...

最新文章

  1. 深度学习可解释性问题如何解决?图灵奖得主Bengio有一个解
  2. 2021-02-23 如何用简单易懂的例子解释条件随机场(CRF)模型?它和HMM有什么区别?从HMM、MEMM、CRF某牛自己总结的
  3. java JMS消息队列
  4. json解析 子类和父类同名属性如何赋值_想学变量的解构赋值?看完这一篇就够了...
  5. Redis与其他缓存框架的对比
  6. c#获取本地ip地址网关子网掩码_教你如何修改路由器LAN口IP地址的方法
  7. 二维随机变量期望公式_概率论笔记-Ch4期望与方差
  8. SQL Server相关知识
  9. IT人不要一直做技术(转载)
  10. 计算机打不开菜鸟打印组件,菜鸟打印常见问题
  11. Spark-SQL常用内置日期时间函数
  12. 三体和银河帝国基地孰优孰劣?
  13. 最高奖励68万!多邻国英语测试设立研究基金
  14. Python基于PyTorch实现BP神经网络ANN分类模型项目实战
  15. MindSpore实现语音指令识别(迁移tf入门教程)
  16. 网络优化——注册表语句分析
  17. http://cs.dartmouth.edu/~xy/blog/facel/
  18. Scrapy部署蜘蛛爬虫项目
  19. dx.bat转换jar 包(java 1.8)出现 unsupported class file version 52.0 …while parsing
  20. 清华大学计算机陈蓓,2010年安徽文科总分头名陈蓓:20岁赴新加坡读研

热门文章

  1. 在word中添加mendeley插件
  2. JAVA 阿里云的OOS文件上传和下载
  3. 解决客户投诉的7个步骤
  4. Blockchain技术之区块链的概念和起源以及区块链的运行方式、发展前景和应用领域分析
  5. Guitar Pro8.1最新中文版自动扒谱编写吉他谱 新功能讲解
  6. 高中在线计算机,高中计算机考试试题集-20210414015151.docx-原创力文档
  7. 小熊肝了十个小时,搞出一本 go 语言精进之路
  8. 回溯法--最大团(部队护卫队问题)
  9. 关于计算机的英语谜语,英语谜语大全及答案100个|英语谜语(50条)
  10. spark on yarn启用动态分配