驱动代码:

#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/miscdevice.h>
#include <linux/gpio.h>#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <mach/regs-clock.h>
#include <plat/regs-timer.h>#include <mach/regs-gpio.h>
#include <linux/cdev.h>
//-------------class_create,device_create------
#include <linux/device.h>/*用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");// 设置指定引脚的输出电平为0gpio_set_value(led_table[arg], 0);break;case IOCTL_LED_OFF:printk("in the IOCTL_LED_OFF!!\n");// 设置指定引脚的输出电平为1gpio_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<arg;i++)for (j=0;j<4;j++) {gpio_set_value(led_table[j], 0);mdelay(400); //delay 400msgpio_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_SHINE\n");for (i=0;i<arg;i++) {for (j=0;j<4;j++)gpio_set_value(led_table[j], 0);mdelay(400); //delay 400msfor (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= %d\n",dev_name,led_table[i],ret);return ret;}s3c_gpio_cfgpin(led_table[i],S3C_GPIO_SFN(1));//outputgpio_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 %d\n", 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 %d\n", led_major);printk("The device name is: %s\n", dev_name);return 0;}/** 执行”rmmod leds”命令时就会调用这个函数 */
static void __exit leds_exit(void)
{/*gpio_free*/int i;for (i = 0; i < LED_NUM; i++){gpio_free(led_table[i]);}/* 卸载驱动程序 */cdev_del(&LedDevs);unregister_chrdev_region(MKDEV(led_major, 0), 1);printk("Led device uninstalled\n");
}/* 这两行指定驱动程序的初始化函数和卸载函数 */
module_init(leds_init);
module_exit(leds_exit);/* 描述驱动程序的一些信息,不是必须的 */
MODULE_AUTHOR("");             // 驱动程序的作者
MODULE_DESCRIPTION("LED Driver");   // 一些描述信息
MODULE_LICENSE("Dual BSD/GPL");                             // 遵循的协议

测试代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>#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_test on   //对应四个LED全亮
led_test off  // 对应四个LED全灭
led_test run  // 运行跑马灯实验
led_test shine //4个LED灯全灭、全亮交替闪烁led_test 1 on   //对应LED1点亮
led_test 1 off  // 对应LED1熄灭
...
led_test 4 on   //对应LED4点亮
led_test 4 off  // 对应LED4熄灭*/
void usage(char *exename)
{printf("Usage:\n");printf("    %s <led_no> <on/off>\n", exename);printf("    led_no = 1, 2, 3 or 4\n");
}int main(int argc, char **argv)
{unsigned int led_no;int fd = -1;unsigned int count=10;if (argc > 3 || argc == 1)goto err;fd = open("/dev/led", 0);  // 打开设备if (fd < 0) {printf("Can't open /dev/led\n");return -1;    }    if (argc == 2) {if (!strcmp(argv[1], "on")) {ioctl(fd, IOCTL_LED_ALLON, count);    // 点亮它} else if (!strcmp(argv[1], "off")) {ioctl(fd, IOCTL_LED_ALLOFF, count);   // 熄灭它} else if (!strcmp(argv[1], "run")) {ioctl(fd, IOCTL_LED_RUN, count);   //运行跑马灯} else if (!strcmp(argv[1], "shine")) {ioctl(fd, IOCTL_LED_SHINE, count);   //闪烁} else {goto err;}}if (argc == 3) {led_no = atoi(argv[1]);    // 操作哪个LED?if (led_no > 3)goto err;        if (!strcmp(argv[2], "on")) {ioctl(fd, IOCTL_LED_ON, led_no);    // 点亮} else if (!strcmp(argv[2], "off")) {ioctl(fd, IOCTL_LED_OFF, led_no);   // 熄灭} else {goto err;}}close(fd);return 0;err:if (fd > 0) close(fd);usage(argv[0]);return -1;}

转载于:https://www.cnblogs.com/hello2mhb/p/3282698.html

Linux下实现流水灯等功能的LED驱动代码及测试实例相关推荐

  1. 学号20175313 《实现Linux下cp XXX1 XXX2的功能(一)》第九周

    目录 MyCP 一.题目要求 二.题目理解 三.需求分析 四.设计思路 五.伪代码分析 六.代码链接 七.代码实现过程中遇到的问题 八.运行结果截图 九.参考资料 MyCP 一.题目要求 编写MyCP ...

  2. linux java -cp lt; .txt_补交 20155202 蓝墨云班课 编写MyCP.java 实现类似Linux下cp XXX1 XXX2的功能...

    蓝墨云班课 编写MyCP.java 要求: 编写MyCP.java 实现类似Linux下cp XXX1 XXX2的功能,要求MyCP支持两个参数: java MyCP -tx XXX1.txt XXX ...

  3. linux怎么设置自动缩进,配置Linux下vim自动缩进等功能

    从终端打开配置文件: vim ~/.vimrc 添加如下代码: set tabstop=4 set softtabstop=4 set shiftwidth=4 set autoindent set ...

  4. linux按照学号对文件进行排序,学号20175313 《实现Linux下Sort -t : -k 2功能》第十二周...

    一.题目要求 实现Linux下Sort -t : -k 2的功能 二.题目理解 -t 分隔符,将每一行数据按照该选项指定的分隔符分成多个域.默认情况下是使用tab键或者空格符来分割的. -k 指定用哪 ...

  5. Linux下qt实现个人资源管理功能:记事本,图片浏览,网络聊天,数据库管理

    Linux下qt实现个人资源管理功能:记事本,图片浏览,网络聊天,数据库管理 实验内容和环境:(包括软件平台和硬件平台) QT5.14.1 Ubuntu操作系统 实验内容及步骤 (含源程序): 用QT ...

  6. linux网卡驱动rtl8188cu,linux下编译基于rtl8188cu控制芯片的USB无线网卡驱动 -电脑资料...

    本人因为实验的需要,需要在嵌入式linux环境下添加wifi功能,通过在网上调研,选择基于rtl8188cu控制芯片的水星NW150UM无线USB网卡,现简单记录下配置过程, 1.下载最新的rtl81 ...

  7. linux下的CPU、内存、IO、网络的压力测试

    linux下的CPU.内存.IO.网络的压力测试 要远程测试其实很简单了,把结果放到一个微服务里直接在web里查看就可以了,或者同步到其他服务器上 一.对CPU进行简单测试: 1.通过bc命令计算特别 ...

  8. 51单片机实验——用定时器0实现流水灯,要求每个led轮流显示1s。

    1.实验题目: 用定时器0实现流水灯,要求每个led轮流显示1s. 2.KEIL代码 #include<reg51.h> void main() {TMOD &=0X0F;TMOD ...

  9. linux下GTK图形界面取消关闭按钮和最大化按钮代码

    linux下GTK图形界面取消关闭按钮和最大化按钮代码 由于项目需要,需要将GTK图形界面的关闭按钮和最大化按钮去掉,查阅很多资料终于解决.先分享出来,方便大家学习. 首先创建一个GTK小窗口(代码不 ...

最新文章

  1. 从0到1,Airbnb的深度学习实践经验总结
  2. optee中关于异常向量表、中断等的深入思考
  3. 14行代码AC_Zero Array(思维)
  4. java运行时参数_运行时的Java 8参数名称
  5. Spring Cloud项目MVN编译 -- Non-resolvable import POM
  6. ipsec *** 的总结性谈论
  7. 50道 JavaScript 经典面试题汇总篇
  8. css3弹性盒子、媒体查询、多列布局
  9. 雪城大学信息安全讲义 七、格式化字符串漏洞
  10. spark算子_Spark算子总结
  11. 关于UIText换行
  12. javaweb项目静态资源被拦截的解决方法
  13. 中古调式(调式音阶) 二
  14. Java多线程编程模式实战指南(一):Active Object模式--转载
  15. 向量ab怎么用计算机打出来,向量怎么用wps打出来
  16. 解决百度云离线文件因含有违规内容被系统屏蔽无法下载问题
  17. 【笨木头Cocos2dx 038】战争迷雾效果 第01章_要探索,不要地图全开!
  18. android11原生录屏,终于把安卓这项功能实现了!iOS 11录屏功能演示:超好用
  19. maya2018自带模型的打开
  20. Bootstrap 实例1

热门文章

  1. 循序渐进Python3(十二) --2--  web框架之django简单实现oracle数据库操作
  2. Windbg 查看SSDT表
  3. TCP/IP和HTTP的不同之处
  4. 文件系统错误的解决方案
  5. DOM和BOM的区别
  6. ros开源课程_如何将开源纳入计算机科学课程
  7. 牛客网 [编程题]数字和为sum的方法数
  8. 第二十八章:化学学校
  9. JSON 语法之 JSON 文件
  10. Bootstrap 按钮的外观