打印

用设备驱动控制LED(转)

[复制链接]
457|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Orchids|  楼主 | 2017-9-28 11:10 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
用设备驱动控制LED




首先要确定一下到底是使用什么硬件……后来楼主终于在破烂堆里找到了一个led,好,就来它啦。

参照手册里下面这两张图,楼主也搭建了测试用的电路,没错一样一样的,楼主用的面包板和它不一样而已,LED的颜色好像也不一样。
好像它用了100欧的电阻,这个楼主实在是没有,于是拿了个470欧的。






恩,没错,用了GPIO44

BBB真的铺垫了很多事情,以至于我控制IO口根本不需要看芯片手册,操作文件就好了:

第一步:向/sys/class/gpio/export写入要控制的GPIO号,这里直接写入44
  •                 filp = filp_open("/sys/class/gpio/export",O_WRONLY,0);
  •                 filp->f_op->write(filp, "44", 3, &filp->f_pos);
  •                 filp_close(filp, NULL);

[color=rgb(51, 102, 153) !important]复制代码

这样就在其目录出现了相应GPIO的目录和文件

第二步:向/sys/class/gpio/gpio44/direction写入相应GPIO的方向

  •                 filp = filp_open("/sys/class/gpio/gpio44/direction",O_WRONLY,0);
  •                 filp->f_op->write(filp, "out", 4, &filp->f_pos);
  •                 filp_close(filp, NULL);

[color=rgb(51, 102, 153) !important]复制代码


第三步就可以写入0和1到/sys/class/gpio/gpio44/value,以控制该pin的输出电平啦。

当然,楼主实现了LED闪动的效果,闪动的频率是可以改变的,所以需要有一个timer

  •                 init_timer(&this_drv_timer);
  •                 this_drv_timer.function = timer_handler;
  •                 this_drv_timer.expires = jiffies + timeout;
  •                 add_timer(&this_drv_timer);

[color=rgb(51, 102, 153) !important]复制代码


每次timer_handler执行,就会再启动这个timer,
  • static void timer_handler(unsigned long arg)
  • {
  •         init_timer(&this_drv_timer);
  •         this_drv_timer.function = timer_handler;
  •         this_drv_timer.expires = jiffies + timeout;
  •         add_timer(&this_drv_timer);
  •         {
  •                 mm_segment_t old_fs;
  •                 struct file* filp = NULL;
  •                 char value_str[5];

  •                 old_fs = get_fs();
  •                 set_fs(KERNEL_DS);

  •                 filp = filp_open("/sys/class/gpio/gpio44/value",O_WRONLY,0);
  •                 sprintf(value_str, "%d", this_pin_v);
  •                 this_pin_v ^= 1;
  •                 filp->f_op->write(filp, value_str, 2, &filp->f_pos);
  •                 filp_close(filp, NULL);

  •                 set_fs(old_fs);
  •         }

[color=rgb(51, 102, 153) !important]复制代码


这里楼主并没有实验太多的代码,基本是一次成型,只不过编码途中遇到一些需要说明的事情


首先,操作相关的文件,好像不允许是用库函数fopen以及相关函数了,而是要用filp_open及相关方法。(表问我为什么,我只是跟着学)
其次,操作文件时候,要搞一下get_fs和set_fs。(表问我为什么,我只是个初学者)
再次,操作timer,每次timer到时都会把自己撤下来,所以要在定时函数中重新启动timer以实现定周期。(表问我为什么,我只是抄的代码)
还有,timer是不精确的,所以有时候LED闪动并不均匀,而且会有明显的不适。(表问我为什么,timer不是我做的)
再有,还记得aoti吗,它和fopen一样也是不允许使用的,所以看到我用了simple_strtoul。(表问我为什么,但是我确实隐隐觉得atoi也不能用)
最后,不知道出于什么原因你能看到这里,我很感激,谢谢你,祝福你,May the force be with you。以下是我的整个源码文件。结果不重要,过程才重要。

  • /* hello.c -- sjtitr */

  • #include <linux/init.h>
  • #include <linux/module.h>
  • #include <linux/moduleparam.h>

  • #include <linux/kernel.h>  
  • #include <linux/init.h>  
  • #include <linux/platform_device.h>  

  • #include <asm/uaccess.h>
  • #include <linux/kdev_t.h>
  • #include <linux/fs.h>

  • #include <linux/cdev.h>
  • #include <linux/device.h>
  • #include <linux/timer.h>

  • #define THIS_DRV_NAME        "PracticeDriver"


  • /* ------------------------- fileops --------------------------------- */
  • #define FIXED_FILE_SIZE        20

  • int practice_open(struct inode *inode, struct file *filp);
  • int practice_release(struct inode *inode, struct file *filp);
  • ssize_t practice_read(struct file *filp, char __user *buffer, size_t count, loff_t *ppos);
  • ssize_t practice_write(struct file *filp, const char __user *buffer, size_t count, loff_t *ppos);

  • unsigned char vt_file[FIXED_FILE_SIZE];
  • unsigned char vt_file_i = 0;

  • static unsigned int timeout;



  • int practice_open(struct inode *inode, struct file *filp)
  • {
  •         printk(KERN_ERR "FOPS - Open\n");
  •         return 0;
  • }

  • int practice_release(struct inode *inode, struct file *filp)
  • {
  •         printk(KERN_ERR "FOPS - Release\n");
  •         return 0;
  • }

  • ssize_t practice_read(struct file *filp, char __user *buffer, size_t count, loff_t *ppos)
  • {
  •         ssize_t size = (count < FIXED_FILE_SIZE) ? count : FIXED_FILE_SIZE;
  •         copy_to_user(buffer, vt_file, size);
  •         printk(KERN_ERR "FOPS - Read %d bytes\n", size);
  •         return size;
  • }

  • ssize_t practice_write(struct file *filp, const char __user *buffer, size_t count, loff_t *ppos)
  • {
  •         ssize_t size = (count < FIXED_FILE_SIZE) ? count : FIXED_FILE_SIZE;
  •         char *after;
  •         copy_from_user(vt_file, buffer, size);
  •         timeout = simple_strtoul(vt_file, &after, 10) / 2;
  •         printk(KERN_ERR "FOPS - Write %d\n", timeout);
  •         return size;
  • }



  • /* ------------------------- Driver ---------------------------------- */


  • static struct file_operations this_drv_fops =
  • {
  •         .owner                = THIS_MODULE,
  •         .open                = practice_open,
  •         .release        = practice_release,
  •         .read                = practice_read,
  •         .write                = practice_write,
  • };

  • static unsigned int this_dev_t;
  • static struct class *this_class;

  • static struct timer_list this_drv_timer;
  • static unsigned char this_pin_v;


  • static void timer_handler(unsigned long arg)
  • {
  •         init_timer(&this_drv_timer);
  •         this_drv_timer.function = timer_handler;
  •         this_drv_timer.expires = jiffies + timeout;
  •         add_timer(&this_drv_timer);
  •         {
  •                 mm_segment_t old_fs;
  •                 struct file* filp = NULL;
  •                 char value_str[5];

  •                 old_fs = get_fs();
  •                 set_fs(KERNEL_DS);

  •                 filp = filp_open("/sys/class/gpio/gpio44/value",O_WRONLY,0);
  •                 sprintf(value_str, "%d", this_pin_v);
  •                 this_pin_v ^= 1;
  •                 filp->f_op->write(filp, value_str, 2, &filp->f_pos);
  •                 filp_close(filp, NULL);

  •                 set_fs(old_fs);
  •         }
  • }


  • /* ------------------------- Module ---------------------------------- */
  • MODULE_AUTHOR("sjtitr");
  • MODULE_LICENSE("Dual BSD/GPL");

  • static int hello_init(void)
  • {
  •         int ret = 0;        
  •         int major;
  •         
  •         printk(KERN_ALERT "Hello!\n");

  •         if(!ret && (major = register_chrdev(0, THIS_DRV_NAME, &this_drv_fops))<0)  
  •         {  
  •                 printk("Failed to register chrdev\n");  
  •                 ret = 1;  
  •         }

  •         if(!ret)
  •         {
  •                 this_dev_t = MKDEV(major, 0);

  •                 printk(KERN_ERR "make driver fs\n");

  •                 this_class = class_create(THIS_MODULE,THIS_DRV_NAME);
  •                 if (IS_ERR(this_class))
  •                 {
  •                         printk(KERN_ERR "Failed to make driver fs\n");
  •                         unregister_chrdev(MAJOR(this_dev_t), THIS_DRV_NAME);
  •                         ret = 1;
  •                 }
  •                 else
  •                 {
  •                         device_create(this_class, NULL, this_dev_t, NULL, THIS_DRV_NAME"%d", 0);
  •                 }
  •         }

  •         if(!ret)
  •         {
  •                 mm_segment_t old_fs;
  •                 struct file* filp = NULL;
  •                 char value_str[5];

  •                 old_fs = get_fs();
  •                 set_fs(KERNEL_DS);

  •                 filp = filp_open("/sys/class/gpio/export",O_WRONLY,0);
  •                 filp->f_op->write(filp, "44", 3, &filp->f_pos);
  •                 filp_close(filp, NULL);
  •                 filp = filp_open("/sys/class/gpio/gpio44/direction",O_WRONLY,0);
  •                 filp->f_op->write(filp, "out", 4, &filp->f_pos);
  •                 filp_close(filp, NULL);
  •                 filp = filp_open("/sys/class/gpio/gpio44/value",O_WRONLY,0);
  •                 sprintf(value_str, "%d", this_pin_v);
  •                 this_pin_v ^= 1;
  •                 filp->f_op->write(filp, value_str, 2, &filp->f_pos);
  •                 filp_close(filp, NULL);

  •                 set_fs(old_fs);

  •                 timeout = HZ / 2;
  •                 init_timer(&this_drv_timer);
  •                 this_drv_timer.function = timer_handler;
  •                 this_drv_timer.expires = jiffies + timeout;
  •                 add_timer(&this_drv_timer);
  •         }
  •             return 0;  
  • }

  • static void hello_exit(void)
  • {
  •         mm_segment_t old_fs;
  •         struct file* filp = NULL;

  •         old_fs = get_fs();
  •         set_fs(KERNEL_DS);

  •         filp = filp_open("/sys/class/gpio/unexport",O_WRONLY,0);
  •         filp->f_op->write(filp, "44", 3, &filp->f_pos);
  •         filp_close(filp, NULL);

  •         set_fs(old_fs);

  •         device_destroy(this_class, this_dev_t);
  •         class_destroy(this_class);
  •         unregister_chrdev(MAJOR(this_dev_t), THIS_DRV_NAME);  
  •         printk(KERN_ALERT "Goodbye!\n");
  • }

  • module_init(hello_init);
  • module_exit(hello_exit);


[color=rgb(51, 102, 153) !important]复制代码

[color=rgb(51, 102, 153) !important]


相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

697

主题

993

帖子

4

粉丝