简单侶途  发表于 2015-11-12 09:14:52

满月 发表于 2015-11-11 20:32 static/image/common/back.gif
666666 有深度!

:lol你的支持,我进步的动力

简单侶途  发表于 2015-11-12 09:14:47

满月 发表于 2015-11-11 20:32 static/image/common/back.gif
666666 有深度!

:lol你的支持,我进步的动力

简单侶途  发表于 2015-11-13 15:51:34

本帖最后由 简单侶途  于 2015-11-13 16:09 编辑

期待大家的不断改进我的代码!!{:soso_e100:}

简单侶途  发表于 2015-11-13 15:58:01

满月 发表于 2015-11-11 20:32 static/image/common/back.gif
666666 有深度!

多谢支持,希望你也来共享点资源啊,求学艰苦!:'(

简单侶途  发表于 2015-11-13 16:07:16

本帖最后由 简单侶途  于 2015-11-13 16:12 编辑

第五个程序目的是控制不同的LED实现方法是利用程序里面申请主设备号:
major = register_chrdev(0, "led", &leddrv_fops);
利用自动分配申请的major主设备号,接着利用major下自我分配利用的次设备号实现匹配同一类的不同minor,系统自动分配完major后,默认分配次设备号minor = 0,接着我们就在minor那里作文章了,minor使用范围是0~255
这个minor就可以让我们识别同一类设备类下的不同led设备节点
下图所示:242为major,242后面的0,1,2就是minor了

1.驱动程序部分:#include<linux/fs.h>
#include<linux/module.h>
#include<linux/errno.h>
#include<linux/kernel.h>
#include<linux/init.h>
#include<linux/cdev.h>
#include<linux/uaccess.h>
#include<linux/device.h>
#include<linux/types.h>
#include <asm/gpio.h>
#include <linux/gpio.h>
#include <plat/sys_config.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <asm/io.h>

#include <linux/moduleparam.h>
#include <linux/poll.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/ipmi.h>
#include <linux/mutex.h>
#include <linux/compat.h>


/*两种方法寻找GPIO寄存器地址*/
//#define PIO_BASE   0x01C20800
#define PH_BASE   (PIO_BASE + 7*0x24)

#define PH_CFG2   (PH_BASE + 0x08)
#define PH_DAT    (PH_BASE + 0x10)

//#define PH_BASE(PIO_BASE + 0xFC)
//#define PH_CFG2(PIO_BASE + 0x104)
//#define PH_DAT   (PIO_BASE + 0X10C)

static volatile unsigned int *ph_cfg2;
static volatile unsigned int *ph_dat;

//设备类
static struct class *leddrv_class;
//分配 cdev
static struct class_device *leddrv_class_dev;
//主设备号
static int major;

static int led_open(struct inode *inode, struct file *file)
{
      /*bit20,bit21
         *open the roange_led and blue_led GPIO output
         *Output is 001
         */

      *ph_cfg2 &= ~((7<<16) | (7<<20));//清零000,这个步骤很重要,注释掉可以看下效果如何blue_led不能控制了
      *ph_cfg2 |= ((1<<16) | (1<<20));//设置001
      return 0;
}


static ssize_t led_write (struct file *file,char __user *buf,
                                                size_t count,loff_t *f_pos)
{
      int val;
      int minor = MINOR(file->f_dentry->d_inode->i_rdev);

      /*1.从用户空间读取数据到内核空间*/
      copy_from_user(&val,buf,4);

      /*2.判断传入值val,进行GPIO电平控制*/
      switch (minor){
      case 0:      /*/dev/leds*/
      {
                if(val == 1)
                        *ph_dat |= ((1<<20) | (1<<21));               
                else
                        *ph_dat &= ~((1<<20) | (1<<21));
      }
      break;
      case 1:/*/dev/led1*/
      {
                if(val == 1)
            *ph_dat |= (1<<20);
            else
            *ph_dat &= ~(1<<20);
      }
      break;
      case 2: /*/dev/led2*/
      {
                if(val == 1)
            *ph_dat |=(1<<21);
      else
            *ph_dat &=~(1<<21);
      }
      break;
      }
      return 0;
}

//分配驱动操作
static struct file_operations leddrv_fops = {

      .owner   =    THIS_MODULE,
      .open         =    led_open,
      .write   =    led_write,
};

static intled_init(void)
{      
      int minor = 0;
      
      ph_cfg2 = ioremap(PH_CFG2, 4);
      ph_dat= ioremap(PH_DAT, 4);
      
         major = register_chrdev(0, "led", &leddrv_fops);
      leddrv_class = class_create(THIS_MODULE, "led");
      leddrv_class_dev = device_create(leddrv_class, NULL, MKDEV(major, 0), NULL, "led0"); /* /dev/ledwht */
      
      for(minor=1;minor<3;minor ++)
                leddrv_class_dev = device_create(leddrv_class, NULL, MKDEV(major, minor), NULL,
      return 0;
}

static void led_exit(void)
{
      int minor;
      
      unregister_chrdev(major,"led");
      /*2.删除设备节点*/
      for(minor = 0; minor<3; minor++)
                device_destroy(leddrv_class, MKDEV(major, minor));
      class_destroy(leddrv_class);
      iounmap(ph_cfg2);
      iounmap(ph_dat);
}

module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
2.应用程序部分:#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

/*测试方法
*/led_test on
*/led_test off
*/

int main(int argc, char *argv[])
{
      int fd;
      int val = 1;
      char* filename;

      if (argc != 3) {
      printf("usage:\n%s </dev/led?> <on|off>\n", argv);
      return 0;
      }
      filename = argv;

      fd = open(filename, O_RDWR);
      if (fd < 0) {
         printf("open led failed.\n");
         return 0;
    }
      if (strcmp(argv, "on") == 0) {
      //开灯
                val = 1;
      }
      else if (strcmp(argv, "off") == 0) {
      //关灯
                val = 0;
      }

      write(fd, &val, 4);
      return 0;
}
3.show图ing
操作步骤如下
LED操作显示





gcd0318 发表于 2015-11-17 16:07:41

赞认真学习的态度

北冥 发表于 2016-4-14 15:53:44

楼主 我编译bin2fex fex2bin的时候为什么报错呢
/opt/sunxi-tools/fel.c:1328: undefined reference to `libusb_strerror'
提示这个未定义 我下载的官网文件啊
页: 1 [2]
查看完整版本: 五种方法点亮LED,入门驱动程序,更新完毕