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

发布者:BlissfulSpirit最新更新时间:2025-02-06 来源: cnblogs关键字:Linux  流水灯  LED驱动 手机看文章 扫描二维码
随时随地手机看文章

驱动代码


#include <linux/errno.h>

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include gpio.h>


#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                    for (j=0;j<4;j++) {

                        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                    for (j=0;j<4;j++)

                        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++)

    {

[1] [2]
关键字:Linux  流水灯  LED驱动 引用地址:Linux下实现流水灯等功能的LED驱动代码及测试实例

上一篇:Linux下18b20温度传感器驱动代码及测试实例
下一篇:基于等待队列及poll机制的按键驱动代码分析和测试代码

推荐阅读最新更新时间:2026-03-24 15:05

Linux驱动入门(三)Led驱动
一、注册字符设备驱动 二、操作硬件 2.1 控制led 2.2 通用方式实现 2.3 gpiolib实现 三、源码 3.1 通用方式实现 3.2 gpiolib实现 四、测试 目的:实现一个led驱动,应用层写入1led亮,写0led灭 一、注册字符设备驱动 led驱动是一个字符设备驱动,编写led驱动首先要注册字符设备,生成设备节点,然后再是完善文件操作集合 关于如何注册字符设备和生成设备字节,在Linux驱动入门(一)字符设备驱动基础中讲得比较详细了,这里给出代码 #include linux/module.h #include linux/init.h #include linux/fs.h #include linux/c
[单片机]
Linux内核LED驱动来理解字符设备驱动开发流程
开发环境 环境说明 详细信息 备注信息 操作系统 Ubunut 18.04.3 LTS 开发板 S3C2440(JZ2440-V3) kernel版本 linux-3.4.2 官网地址 busybox版本 busybox-1.22.1 官网地址 编译器 arm-linux-gcc-4.4.3 下载地址 编译器路径 /opt/FriendlyARM/toolschain/4.4.3/bin 绝对路径 1. Linux字符设备驱动的组成 引自宋宝华《Linux设备驱动开发详解--基于最新的Linux 4.0内核》P138内容: 在Linux中,字符设备驱动由如下几个部分组成。 1. 字符设备
[单片机]
从<font color='red'>Linux</font>内核<font color='red'>LED驱动</font>来理解字符设备驱动开发流程
Linux平台驱动-LED驱动(Micro2440 + linux 2.6.39)
由于LINUX使用了MINI2440的配置,MICRO2440与MINI2440的硬件资料基本一样。因此LED驱动也是通用的,默认的MINI2440配置已经添加对板上4个LED的支持,这里只需要对其配置和测试进行简单的说明。 a) menuconfig配置 MICRO2440的LED驱动被定义为一LED类平台设备,使用该类型驱动需要在menuconfig中打开对LED类设备的支持。 # make menuconfig Device Drivers --- -*- LED Support --- -*- LED Cl
[单片机]
<font color='red'>Linux</font>平台驱动-<font color='red'>LED驱动</font>(Micro2440 + <font color='red'>linux</font> 2.6.39)
Linux内核模块驱动之---led驱动
开发板:tiny6410 内核:linux2.6.38 要写led驱动首先要复习的是混杂设备驱动的设计流程、 内核file_ops结构体、硬件通信IO端口和IO内存、 ioctl系统调用的实现步骤和方法 按照顺序来对已经学习的内容复习 并把led模块驱动写出来 第一步:复习ioctl系统调用函数 一、什么是ioctl系统调用函数,驱动中的iodtl函数是什么样子的?为什么需要ioctl函数?》 虽然file_ops结构体提供了相当多的文件操作函数,但是要想对硬件操作,这个file_ops结构体无法完成了,所以操作系统又提供了另一个对硬件操作的函数,就是ioctl,ioctl分为在应用层 和 在驱动层。ioc
[单片机]
tiny6410 linux混杂设备 led驱动
#include linux/miscdevice.h #include linux/kernel.h #include linux/module.h #include linux/init.h #include linux/fs.h #include linux/types.h #include linux/errno.h #include linux/ioctl.h #include linux/cdev.h #include linux/device.h #include linux/ioport.h #include asm/io.h #include asm/uaccess.h #define
[单片机]
OK6410A学习笔记三:嵌入式Linux驱动之LED驱动
开发环境: Windows7 + vmware workstation 6.5 + Ubuntu9.10 Linux Source Code: FORLINX_linux-3.0.1.tar.gz ARM CROSS GCC: arm-linux-gcc v4.3.2 源码: //s3c6410_led.c driver file #include linux/kernel.h #include linux/module.h #include linux/fs.h #include linux/mm.h #include linux/io.h #define DEV_MAJOR 176 #define DEV_N
[单片机]
OK6410A学习笔记三:嵌入式<font color='red'>Linux</font>驱动之<font color='red'>LED驱动</font>
《逗比小憨憨51单片机Proteus仿真系列》第20期基于单片机的简易流水灯仿真
源代码: #include reg52.h void Delay1ms(unsigned int count) { unsigned int i,j; for(i=0;i count;i++) for(j=0;j 120;j++); } void main(void) { unsigned char LEDIndex = 0; bit LEDDirection = 1; while(1) { if(LEDDirection) P1 = ~(0x01 LEDIndex); else P1 = ~(0x80 LEDIndex); if(LEDIndex==7) LEDDirection = !
[单片机]
《逗比小憨憨51单片机Proteus仿真系列》第1期51单片机的流水灯仿真
源代码: #include reg51.h #include "intrins.h" /* 文件描述:第1期基于单片机的花式流水灯设计与仿真 作者:逗比小憨憨 备注:收录至(逗比小憨憨51单片机Proteus仿真系列视频) */ void main(void) { unsigned char i,rol; void delay_ms(unsigned int nms); rol = 0xfe; while(1) { for(i=0;i 8;i++) { P1 = rol; delay_ms(200); rol = _crol_(rol
[单片机]
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved