• LED:控制发光二极管


    1、LED驱动实现原理,如图:

    2、编写LED驱动

    (1)创建LED驱动的设备文件

      第一步:使用cdev_init函数初始化cdev

      第二步:指定设备号

      第三步:使用cdev_add函数将字符设备添加到内核中的字符设备数组中

      第四步:使用class_create宏创建struct class

      第五步:使用device_create函数创建设备文件

      #define DEVICE_NAME "s3c6410_leds"  //定义设备文件名称

      #define DEVICE_COUNT 1  //创建设备文件的数量

      #define S3C6410_LEDS_MAJOR 0  //默认主设备号

      #define S3C6410_LEDS_MINOR 234  //默认次设备号

      static int major = S3C6410_LEDS_MAJOR;  //主设备号

      static int minor = S3C6410_LEDS_MINOR;  //次设备号

      static dev_t dev_number;  //设备号

      static struct class *leds_class = NULL;  //struct class

      static struct file_operations dev_ops =

      {

        .owner = THIS_MODULES,

        .unlocked_ioctl = s3c6410_leds_ioctl,

        .write = s3c6410_leds_write

      };

      static struct cdev led_cdev;  //描述字符设备的struct cdev

      //创建设备文件

      static int leds_create_device(void)

      {

        int ret = 0;

        int err = 0;

        cdev_init(&leds_cdev, &dev_fops);

        leds_cdev.owner = THIS_MODULES;

        if (major > 0)

        {

          dev_number = MKDEV(major, minor);

          err = register_chrdev_region(dev_number, DEVICE_COUNT, DEVOCE_NAME);

          if (err < 0)

          {

            printk(KERN_WARNING "register_chrdev_region() failed ");

            return err;

          }

        } 

        else

        {

          err = alloc_chrdev_region(&leds_cdev.dev, 10, DEVICE_COUNT, DEVICE_NAME);

          if (err < 0)

          {

            printk(KERN_WARNING "alloc_chrdev_region() failed ");

            return err;

          }

          major = MAJOR(leds_cdev.dev);

          minor = MINOR(leds_cdev.dev);

          dev_number = leds_cev.dev;

        } 

        ret = cdev_add(&leds_cdev, dev_number, DEVICE_COUNT);

        leds_class = class_create(THIS_MODULE, DEVICE_NAME);

        device_create(leds_class, NULL, dev_number, NULL, DEVICE_NAME);

        return ret;

      }

    (2)LED驱动初始化函数

      static int leds_init(void)

      {

        int ret;

        ret = leds_crerate_device();

        printk(DEVICE_NAME " initialized ");

        return ret; 

      }

      module_init(leds_init);

    (3)LED驱动卸载函数

      static void leds_destroy_device(void)

      {

        device_destory(led_class, dev_number);  //移除通过device_create函数创立的字符设备

        if (leds_class)  //销毁struct class

          class_destroy(leds_class);

        unregister_chrdev_region(dev_number, DEVICE_NUMBER);  

      }

      static void leds_exit(void)

      {

        leds_destroy_device();

        printk(DEVICE_NAME " exit! ");

      }

      module_exit(leds_exit);

    (4)设置寄存器与初始化LED驱动

      static int leds_state = 1;

      static void leds_init_gpm(int leds_default)

      {

        //初始化S3C64XX_GPMCON

        int tmp = 0;

        tmp = ioread32(S3C64XX_GPMCON);

        tmp &= (~0xFFFF);

        tmp |= 0x1111;

        iowrite32(tmp, S3C64XX_GPMCON);

        //初始化S3C64XX_GPMPUD

        tmp = ioread32(S3C64XX_GPMPUD);

        tmp &= (~0xFF);

        tmp |= 0xAA;

        iowrite32(tmp, S3C64XX_GPMPUD);

        //初始化S3C64XX_GPMDAT

        tmp = ioread32(S3C64XX_GPMDAT);

        tmp &= (~0xF);

        tmp |= leds_default;

        iowrite32(tmp, S3C64XX_GPMDAT);

      }

      static int leds_init(void)

      {

        int ret;

        ret = leds_create_device();

        leds_init_gpm(~leds_state);

        return ret;

      }

    (5)控制LED

      通过字符串控制LED

      static unsigned char mem[4];

      static ssize_t s3c6410_leds_write(struct file *file, const char _user *buf, size_t count, loff_t *ppos)

      {

        unsigned tmp = count;

        unsigned long i = 0;

        memset(mem, 0, 4);

        if (count > 4)

        {

          tmp = 4;

        }

        copy_from_user(mem, buf, tmp)

        for(i = 0; i < 4; i++)

        {

          tmp = ioread32(S3C64XX_GPMDAT);

          if (mem[i] == '1')

          {

            tmp &= (~(1 << i));

          }

          else

          {

            tmp |= (1 << i);

          }

          iowrite32(tmp, S3C64XX_GPMDAT);

        }

        return count;

      }

      通过I/O命令控制LED

      static long s3c6410_leds_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)

      {

        switch (cmd)

        {

          unsigned tmp;

          case 0:

          case 1:

          if (arg > 4)

            return -EINVAL;

          tmp = ioreade32(tmp, S3C64XX_GPMDAT);

          if (cmd == 1)

            tmp &= (~(1 << arg));

          else

            tmp |=(1 << arg);

          iowrite32(tmp, S3C64XX_GPMDAT);

          return 0;

          default:

          return -EINVAL;

        }

      }

  • 相关阅读:
    lightdb特性之内置数据库规范检查和违约拦截
    lightdb匿名块及其事务支持
    PHP系列 | PHP中的stdClass是什么?
    霍金斯能量层级图解析 辉
    golang 解释器
    golang 1.18 plugin 热更新|插件化终极方案 2022经验实战总结
    WSL connect: Network is unreachable解决方案
    Git 修改文件后,文件夹目录层级未显示红色
    Apache Hudi 源码分析 JavaClient
    【ESXi】失败 – “scsi0:0”的磁盘类型 2 不受支持或无效。请确保磁盘已导入
  • 原文地址:https://www.cnblogs.com/hello3399/p/5546211.html
Copyright © 2020-2023  润新知