驱动代码:
#include <linux/errno.h>
#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //-------------class_create,device_create------ #include /*用udev机制自动添加设备节点*/ struct class *led_class; static int led_major = 0; /* 主设备号 */ static struct cdev LedDevs; /* 应用程序执行ioctl(fd, cmd, arg)时的第2个参数 */ #define LED_MAGIC 'k' #define IOCTL_LED_ON _IOW (LED_MAGIC, 1, int) #define IOCTL_LED_OFF _IOW (LED_MAGIC, 2, int) #define IOCTL_LED_RUN _IOW (LED_MAGIC, 3, int) #define IOCTL_LED_SHINE _IOW (LED_MAGIC, 4, int) #define IOCTL_LED_ALLON _IOW (LED_MAGIC, 5, int) #define IOCTL_LED_ALLOFF _IOW (LED_MAGIC, 6, int) /* 用来指定LED所用的GPIO引脚 */ static unsigned long led_table [] = { S5PV210_MP04(4), S5PV210_MP04(5), S5PV210_MP04(6), S5PV210_MP04(7), }; #define LED_NUM ARRAY_SIZE(led_table) /* 应用程序对设备文件/dev/led执行open(...)时, * 就会调用leds_open函数 */ static int leds_open(struct inode *inode, struct file *file) { int i; for (i = 0; i < 4; i++) { // 设置GPIO引脚的功能:本驱动中LED所涉及的GPIO引脚设为输出功能 s3c_gpio_cfgpin(led_table[i], S3C_GPIO_OUTPUT); } return 0; } //LEDS all light on static void leds_all_on() { int i; for (i=0; i<4; i++) { gpio_set_value(led_table[i], 0); } } //LEDs all light off static void leds_all_off() { int i; for (i=0; i<4; i++) { gpio_set_value(led_table[i], 1); } } /* 应用程序对设备文件/dev/leds执行ioctl(...)时, * 就会调用leds_ioctl函数 */ static int leds_ioctl(struct file *file, unsigned int cmd, unsigned long arg)//没有inode,用邋unlocked_ioctl { printk('in the leds_ioctl!!n'); // if (__get_user(data, (unsigned int __user *)arg)) //方法二:指针参数传递 // return -EFAULT; printk('arg is %d!!n',arg); switch(cmd) { case IOCTL_LED_ON: printk('in the IOCTL_LED_ON!!n'); // 设置指定引脚的输出电平为0 gpio_set_value(led_table[arg], 0); break; case IOCTL_LED_OFF: printk('in the IOCTL_LED_OFF!!n'); // 设置指定引脚的输出电平为1 gpio_set_value(led_table[arg], 1); break; case IOCTL_LED_RUN: // 跑马灯 { printk('in the IOCTL_LED_RUN!!n'); int i,j; leds_all_off(); //printk('IOCTL_LED_RUN'); for (i=0;i gpio_set_value(led_table[j], 0); mdelay(400); //delay 400ms gpio_set_value(led_table[j], 1); mdelay(400); //delay 400ms } break; } case IOCTL_LED_SHINE: // LED 闪烁 { printk('in the IOCTL_LED_SHINE!!n'); int i,j; leds_all_off(); printk('IOCTL_LED_SHINEn'); for (i=0;i gpio_set_value(led_table[j], 0); mdelay(400); //delay 400ms for (j=0;j<4;j++) gpio_set_value(led_table[j], 1); mdelay(400); } break ; } case IOCTL_LED_ALLON: printk('in the IOCTL_LED_ALLON!!n'); // 设置指定引脚的输出电平为0 leds_all_on(); break; case IOCTL_LED_ALLOFF: printk('in the IOCTL_LED_ALLOFF!!n'); // 设置指定引脚的输出电平为1 leds_all_off(); break; default: printk('in the default!!n'); return -EINVAL; } return 0; } /* 这个结构是字符设备驱动程序的核心 * 当应用程序操作设备文件时所调用的open、read、write等函数, * 最终会调用这个结构中指定的对应函数 */ static struct file_operations leds_fops = { .owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */ .open = leds_open, .unlocked_ioctl = leds_ioctl, }; /* * Set up the cdev structure for a device. */ static void led_setup_cdev(struct cdev *dev, int minor, struct file_operations *fops) { int err, devno = MKDEV(led_major, minor); cdev_init(dev, fops); dev->owner = THIS_MODULE; dev->ops = fops; err = cdev_add (dev, devno, 1); /* Fail gracefully if need be */ if (err) printk (KERN_NOTICE 'Error %d adding Led%d', err, minor); } /* * 执行“insmod leds.ko”命令时就会调用这个函数 */ static int __init leds_init(void) { int result; dev_t dev = MKDEV(led_major, 0); char dev_name[]='led'; /* 加载模式后,执行”cat /proc/devices”命令看到的设备名称 */ /*gpio_request*/ int i,ret; for (i = 0; i < LED_NUM; i++) { ret=gpio_request(led_table[i],'LED'); if(ret)//注意,是ret { printk('%s:request GPIO %d for LED failed,ret= %dn',dev_name,led_table[i],ret); return ret; } s3c_gpio_cfgpin(led_table[i],S3C_GPIO_SFN(1));//output gpio_set_value(led_table[i],1); } /* Figure out our device number. */ if (led_major) result = register_chrdev_region(dev, 1, dev_name); else { result = alloc_chrdev_region(&dev, 0, 1, dev_name); led_major = MAJOR(dev); } if (result < 0) { printk(KERN_WARNING 'leds: unable to get major %dn', led_major); return result; } if (led_major == 0) led_major = result; /* Now set up cdev. */ led_setup_cdev(&LedDevs, 0, &leds_fops); /*udev机制可以自动添加设备节点,只需要添加xxx_class这个类,以及device_create()*/ led_class = class_create(THIS_MODULE, 'led_class');/*在sys目录下创建xx_class这个类,/sys/class/~*/ device_create(led_class, NULL, LedDevs.dev, dev_name, dev_name);/*自动创建设备/dev/$DEVICE_NAME*/ printk('Led device installed, with major %dn', led_major); printk('The device name is: %sn', dev_name); return 0; } /* * 执行”rmmod leds”命令时就会调用这个函数 */ static void __exit leds_exit(void) { /*gpio_free*/ int i; for (i = 0; i < LED_NUM; i++) {
上一篇:Linux下18b20温度传感器驱动代码及测试实例
下一篇:基于等待队列及poll机制的按键驱动代码分析和测试代码
推荐阅读最新更新时间:2026-03-24 15:05
- 支持 BLE 连接、由 4mA 至 20mA 电流回路供电的现场发送器参考设计
- AM2DM-0515DH60-NZ ±15 Vout、2W 双路输出 DC-DC 转换器的典型应用
- LTC6261IDC 音频耳机桥式驱动器运算放大器的典型应用
- LTC1775CS 2.5V/5A 可调输出降压稳压器的典型应用电路
- AD8601ARTZ-REEL7 符合 PC100 标准的线路输出放大器的典型应用
- 一种基于分立的 315MHz 振荡器解决方案,用于使用 BFR182 射频双极晶体管的远程无钥匙进入系统
- 使用 ROHM Semiconductor 的 BD49E39G-TR 的参考设计
- AM30EW-2405SZ 5V 三路输出 DC/DC 转换器的典型应用
- LTC3564 的电池在 1.2A 应用中达到 1.2V
- AL1676EV2,基于 AP1676 高亮度降压 LED 驱动控制器的评估板



Linux技术手册
【2025 DigiKey创意大赛】 学伴智盒 - 代码
智能机械臂
非常经典的关于LLC的杨波博士论文
XC6406PP60DL






京公网安备 11010802033920号