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\n");

        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\n");

        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 "\tinitialized\n");

    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 "\texit!\n");

  }

  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;

    }

  }

posted @ 2016-06-03 20:40  yxgfc  阅读(227)  评论(0编辑  收藏  举报