linux内核驱动 第一个led的 程序思想过程

发布者:雅致人生最新更新时间:2023-09-05 来源: elecfans关键字:linux  内核驱动  led 手机看文章 扫描二维码
随时随地手机看文章

linux 内核写led的驱动如图所示:

按照图 的方式我们发现我们需要写两个部分 一个是APP,一个是底层的驱动。其中APP是通过C库和系统层最后调用到底层的驱动的。


linux系统首先会把底层驱动以文件的形式挂载到dev文件夹内,然后APP利用文件写或者读的方式对底层的代码进行操作。


所以程序会分为两部分1. 写驱动并且挂载到linux内核2. 写APP程序去按照文件的方式调用linux挂载的内核。


1. 首先是写驱动的程序。


主要的程序有:


static int first_drv_open(struct inode *inode, struct file *file)

这个是led初始化的函数 其中函数名字可以随便起 但是参数要按照 static struct file_operations first_drv_fops 里面的参数去做写。

static ssize_t first_drv_write(struct file *file, const char __user *buf, size_t count, loff_t* ppos)

这个函数是led的写状态函数, 其中函数的名字可以随便起 但是参数要按照 static struct file_operations first_drv_fops 里面的参数去做写。

static struct file_operations first_drv_fops

这个是linux内核里面的结构体,我们app驱动都是以文件的形式读写,所以我们写的驱动最后必须挂载到这些结构体上面。


int first_drv_init(void)

这个函数里面 major = register_chrdev(0, "first_drv", &first_drv_fops); 是让系统自己去给驱动分配一个设备号,


firstdrv_class = class_create(THIS_MODULE, "firstdrv");  建立一个led驱动的类


firstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xyz");

利用上面建立的类我们建立一个驱动  这个驱动将会返回一个驱动设备号。

module_init(first_drv_init);这个函数我们把led初始化驱动注册到内核里面

module_exit(first_drv_exit); 把led从内核中去除。

 first_drv_exit 取消注册


  1 #include

  2 #include

  3 #include

  4 #include

  5 #include

  6 #include

  7 #include

  8 #include

  9 #include

 10 #include

 11 

 12 static struct class *firstdrv_class;

 13 static struct class_device *firstdrv_class_dev;

 14 

 15 volatile unsigned long *gpfcon = NULL;

 16 volatile unsigned long  *gpfdat = NULL;

 17 

 18  static int first_drv_open(struct inode *inode, struct file *file)

 19      {

 20      //   printk("first_drv_openrn");

 21        /* ÅäÖÃGPF4,5,6 ΪÊä³ö*/

 22         *gpfcon &= ~((0x3 << (4*2)) | (0x3 << (6*2)) | (0x03 << (5*2)));

 23         *gpfcon |= ((0x1 << (4*2)) | (0x1 << (6*2)) | (0x01 << (5*2)));

 24           return 0;

 25 

 26     }

 27 static ssize_t first_drv_write(struct file *file, const char __user *buf, size_t count, loff_t* ppos)

 28 {

 29 //  printk("first_drv_writern");

 30   int val ;

 31   copy_from_user(&val, buf, count);    //from user to kernel

 32 

 33   // copy_to_user  from kernel to app

 34   if(val == 1)

 35       {

 36          *gpfdat |= (1<<4) | (1<<5) | (1<<6);

 37 

 38        }

 39   else

 40       {

 41 

 42            *gpfdat &= ~((1<<4) | (1<<5) | (1 << 6));

 43 

 44         }

 45 

 46   

 47    return 0;

 48 }

 49 

 50 static struct file_operations first_drv_fops = {          //¶¨ÒåÒ»¸öfile operation ½Ó¿Ú

 51 

 52    .owner = THIS_MODULE,

 53    .open  = first_drv_open,

 54    .write =  first_drv_write,

 55 

 56 

 57 };

 58 

 59 int major = 0;

 60 int first_drv_init(void)   //Èë¿Úº¯Êý

 61 {

 62     major = register_chrdev(0, "first_drv", &first_drv_fops);//×¢²áÇý¶¯³ÌÐò

 63      //major ÊÇÖ÷É豸ºÅ

 64     firstdrv_class = class_create(THIS_MODULE, "firstdrv");    //create a class of first drive

 65 

 66    gpfcon  = (volatile unsigned long *)ioremap(0x56000050, 16);

 67 

 68    gpfdat = gpfcon + 1;  //ÕâÀïµØÖ·ÊÇ+4 µÄ ÒòΪÎÒÃÇÿһ´Î¶ÁÈ¡µÄÊÇ4¸ö×Ö½Ú©

 69    //unsigned long ÊÇ4¸ö×Ö½Ú

 70    

 71     if(IS_ERR(firstdrv_class))

 72         return PTR_ERR(firstdrv_class);

 73 

 74     //and create a new device according to the new class eshtablished above

 75    firstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xyz");

 76     return 0;

 77 }

 78 

 79 //ÐÞÊÎÈë¿Úº¯Êý

 80 module_init(first_drv_init);  //Äں˻áµ÷ÓÃÕâ¸ö½á¹¹Ìå

 81 

 82 //³ö¿Úº¯Êý

 83 

 84 int first_drv_exit(void)   //Èë¿Úº¯Êý

 85 {

 86     unregister_chrdev(major , "first_drv");//×¢²áÇý¶¯³ÌÐò

 87     //major ÊÇÖ÷É豸ºÅ

 88     class_device_unregister(firstdrv_class_dev);   //dismount the dev from kernel

 89     class_destroy(firstdrv_class);                          //remove registed class

 90     iounmap(gpfcon);

 91     return 0;

 92 }

 93 

 94 module_exit(first_drv_exit);

 95 

 96 

 97 

 98 /*the code below discribe some info for kernel not necessary but can fix some bugs*/

 99 MODULE_AUTHOR("WWW.GOOGLE.COM");

100 MODULE_VERSION("v1.0");

101 MODULE_DESCRIPTION("FIRST DRIVER TEST CODE");

102 MODULE_LICENSE("GPL");   //MUST BE INCLUDED


2. 第二部分是APP我们这里的APP是很简短的 现在仅供测试:


 1 #include

 2 #include

 3 #include

 4 #include

 5 

 6 int main(int argc, char** argv)

 7 {

 8     int fd;

 9     int val = 1;

10     fd = open("/dev/xyz", O_RDWR);

11    if(argc != 2)

12        {

13          printf("Usage : n");

14          printf("%s" n"); 

15 

16        }

17 

18    if(fd < 0)

19        printf("can't open!n");

20    if(strcmp(argv[1], "on") == 0)

21        val = 1;

22    else

23        val = 0;

24    

25    write(fd, &val, 4);

26    return 0;

27 

28 }


关键字:linux  内核驱动  led 引用地址:linux内核驱动 第一个led的 程序思想过程

上一篇:GCC的简单指令的分析
下一篇:linux 中断驱动和led驱动读写的函数清单

推荐阅读最新更新时间:2024-11-01 19:16

LED驱动精准控制方式
  提到LED驱动精准度通常会想到恒流误差,其实驱动精度并不仅仅限于电流精度一项。LED是一款典型的电流驱动型器件,精准控制LED驱动电流,可决定包括光效率、电源效率、散热和产品亮度等在内的许多参数。驱动LED主要在于控制它的电流。无论是直接增、缩驱动电流,还是占空比(PWM)减小开关时间比,均是控制电流方式,但达到的目的却不相同。本文将阐述不同的驱动在不同应用中的区别。   分布式恒流驱动原理介绍   在以往的白炽灯和节能灯市场,大公司所形成的规格有限的主流灯具型号, LED很难再继续遵守。LED有它的应用灵活性,在日后的设计中会带来较多的电源规格。我们要避免过多的电源规格,不给日后量产带来诸多障碍。本着在不限制设计灵活
[电源管理]
<font color='red'>LED</font><font color='red'>驱动</font>精准控制方式
利用反相升降压拓扑控制LED亮度
若需控制LED 亮度,就必须具备能够提供恒定、稳压电流的驱动器。而要达到此目标,驱动器拓朴必须能产生足够的输出电压来顺向偏置 LED。那麽当输入和输出电压范围重叠时,设计人员又该如何选择呢?转换器有时可能需要逐渐降低输入电压,但有时也可能需要升高输出电压。以上情况通常出现在那些具有大范围“脏” (dirty) 输入功率来源的应用中,例如车载系统。在这种降压/升压的操作中,几种拓朴可以达到较好的效果,像是 SEPIC 或四次切换升降压拓朴。这些拓朴一般需要大量的元件,设计的材料成本也因而增加。但由於它们可提供正输出电压,因此设计人员通常视其为可接受的方案。不过负输出电压转换器也是另一种不该被忽略的替代解决方案。   图 1 显
[电源管理]
利用反相升降压拓扑控制<font color='red'>LED</font>亮度
LED显示摇棒全套方案及源程序
作者:nim 于 http://www.21icbbs.com 2005-1-7 email: linyige@yahoo.com 本设计版权归作者所有,请勿擅自用于商业目的,转载请注明作者及出处。 情人节我们做电的兄弟们送什么礼物给心仪已久的MM?在离情人节还有一个月的时间,给大家提供一个适合作为礼物的简单电路,自己动手做的漂亮玩具一定会是送给MM的最好的礼物。 显示效果图片upload/2005_01/050117013990931.jpg 原理图http://www.21icsearch.com/buzi/upimage/upfile/20047221015470.jpg 曾经在新手园地发
[应用]
降低LED的温升——热反馈
利用LED实现高亮度照明要求使用厂商允许的最大电流驱动,但LED的平均寿命高度取决于工作温度。工作温度仅上升10℃便可使其寿命缩短一半。这种情况迫使设计人员必须降低调节电流,牺牲亮度来延长使用寿命。如果要求LED在较高的环境温度下工作,则必须进一步降低电流来最小化环境到芯片温升,以保证使用寿命。但是由于存在温度上限,这样做会降低中低环境温度范围的照明亮度。本质上来说,我们是通过降低亮度来实现高温环境工作的。图1显示了一个使用热敏电阻控制运算放大器 (op amp) 的LED驱动电路,其在LED电路板温度上升时降低驱动电流。 图1:检测温度上升时运算放大器降低LED电流。 LED阵列电流通过检测电流检测电阻器R7的电
[电源管理]
降低<font color='red'>LED</font>的温升——热反馈
技术控:LED基本驱动照明电路设计解析
  LED 因其应用广泛,价格公道,而被业界广泛采用,不管是节日的装饰灯还是家庭使用的各种灯具要用到LED的驱动电路,因为它降低的能源的消耗,可长期稳定的工作,今天我就从一个实用的LED电路给大家延伸性的介绍 LED照明 驱动电路。   发光二极管(LED)因其具有高效、节能、寿命长、环保等特点,已成为现今 照明 技术的可选方案,并逐渐被应用于照明。促使人们关注LED照明技术的一个关键因素是,其大大降低了能源的消耗,并可实现长期可靠的工作。    本文先从采用恒流源的电路开始, 本电路中的主要元件三极管,要求其耐压要400V以上,功率也要10W以上的大功率管,如MJE13003、MJE13005等,并且要加上散热片,滤波电容C
[电源管理]
技术控:<font color='red'>LED</font>基本<font color='red'>驱动</font>照明电路设计解析
PIC单片机驱动LED数码管显示程序
;*****该程序用于驱动led数码管显示,在8个LED数码管上依次显示数字1、2、3、4、5、6、7、8******* ;****http://www.51hei.com 单片机学习网经典程序已测试,led数码管共阴和共阳不同请修改码值转换表部分 LIST P=18F458 INCLUDE "P18F458.INC" ;所用的寄存器 XIANR EQU 0X20 ORG 0X00 GOTO MAIN ORG 0X30 ;****************以下为码值转换表******************** CONVERT ADDWF PCL,1 RETLW 0XC0 ;0,显示段码与具体的硬件连接有关 RETLW 0XF9
[单片机]
jz2440裸机开发与分析: 点亮LED灯之汇编语言
LED原理图及2440寄存器说明 汇编语言编写控制LED灯 .text /*.text部分是处理器开始执行代码的地方,指定了后续编译出来的内容放在代码段*/ .global _start; /*.global关键字用来让一个符号对链接器可见,可以供其他链接对象模块使用;*/ /* 告诉编译器后续跟的是一个全局可见的名字*/ /*.global _start让_start符号成为可见的标识符,*/ /*这样链接器就知道跳转到程序中的什么地方并开始执行程序*/ _start: /*_start是一个函数的起始地址,也是编译、链接后程序的起始地址*/ ldr r0, =0x
[单片机]
jz2440裸机开发与分析: 点亮<font color='red'>LED</font>灯之汇编语言
记录tiny6410 jlink 命令行调试linux-2.6.38内核
1\首先启动nandflash uboot- linux内核- 文件系统,进入文件系统命令行 2\启动JLinkGDBServer -device ARM11 3启动arm-none-eabi-gdb vmlinux 在这个命令行中输入 target remote localhost:2331 monitor halt monitor reset b start_kernel list continue 注意 需要烧写与所调试的内核一致的内核
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved