驱动代码:

#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 = ; /* 主设备号 */
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(),
S5PV210_MP04(),
S5PV210_MP04(),
S5PV210_MP04(), };
#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 = ; i < ; i++) {
// 设置GPIO引脚的功能:本驱动中LED所涉及的GPIO引脚设为输出功能
s3c_gpio_cfgpin(led_table[i], S3C_GPIO_OUTPUT);
}
return ;
} //LEDS all light on
static void leds_all_on()
{
int i;
for (i=; i<; i++) {
gpio_set_value(led_table[i], );
}
} //LEDs all light off
static void leds_all_off()
{
int i;
for (i=; i<; i++) {
gpio_set_value(led_table[i], );
}
} /* 应用程序对设备文件/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], );
break; case IOCTL_LED_OFF:
printk("in the IOCTL_LED_OFF!!\n");
// 设置指定引脚的输出电平为1
gpio_set_value(led_table[arg], );
break; case IOCTL_LED_RUN:
// 跑马灯
{
printk("in the IOCTL_LED_RUN!!\n");
int i,j;
leds_all_off();
//printk("IOCTL_LED_RUN");
for (i=;i<arg;i++)
for (j=;j<;j++) {
gpio_set_value(led_table[j], );
mdelay(); //delay 400ms
gpio_set_value(led_table[j], );
mdelay(); //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=;i<arg;i++) {
for (j=;j<;j++)
gpio_set_value(led_table[j], );
mdelay(); //delay 400ms
for (j=;j<;j++)
gpio_set_value(led_table[j], );
mdelay();
}
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 ;
} /* 这个结构是字符设备驱动程序的核心
* 当应用程序操作设备文件时所调用的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, );
/* 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, );
char dev_name[]="led"; /* 加载模式后,执行”cat /proc/devices”命令看到的设备名称 */ /*gpio_request*/
int i,ret;
for (i = ; 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());//output
gpio_set_value(led_table[i],);
} /* Figure out our device number. */
if (led_major)
result = register_chrdev_region(dev, , dev_name);
else {
result = alloc_chrdev_region(&dev, , , dev_name);
led_major = MAJOR(dev);
}
if (result < ) {
printk(KERN_WARNING "leds: unable to get major %d\n", led_major);
return result;
}
if (led_major == )
led_major = result; /* Now set up cdev. */
led_setup_cdev(&LedDevs, , &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 ; } /*
* 执行”rmmod leds”命令时就会调用这个函数
*/
static void __exit leds_exit(void)
{
/*gpio_free*/
int i;
for (i = ; i < LED_NUM; i++)
{ gpio_free(led_table[i]);
} /* 卸载驱动程序 */
cdev_del(&LedDevs);
unregister_chrdev_region(MKDEV(led_major, ), );
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 = -;
unsigned int count=; if (argc > || argc == )
goto err; fd = open("/dev/led", ); // 打开设备
if (fd < ) {
printf("Can't open /dev/led\n");
return -;
} if (argc == ) {
if (!strcmp(argv[], "on")) {
ioctl(fd, IOCTL_LED_ALLON, count); // 点亮它
} else if (!strcmp(argv[], "off")) {
ioctl(fd, IOCTL_LED_ALLOFF, count); // 熄灭它
} else if (!strcmp(argv[], "run")) {
ioctl(fd, IOCTL_LED_RUN, count); //运行跑马灯
} else if (!strcmp(argv[], "shine")) {
ioctl(fd, IOCTL_LED_SHINE, count); //闪烁
} else {
goto err;
}
} if (argc == ) {
led_no = atoi(argv[]); // 操作哪个LED?
if (led_no > )
goto err;
if (!strcmp(argv[], "on")) {
ioctl(fd, IOCTL_LED_ON, led_no); // 点亮
} else if (!strcmp(argv[], "off")) {
ioctl(fd, IOCTL_LED_OFF, led_no); // 熄灭
} else {
goto err;
}
} close(fd);
return ; err:
if (fd > )
close(fd);
usage(argv[]);
return -; }

Linux下实现流水灯等功能的LED驱动代码及测试实例的更多相关文章

  1. Linux下简易蜂鸣器驱动代码及测试实例

    驱动代码: #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> ...

  2. 《Linux下cp XXX1 XXX2的功能》的实现

    <Linux下cp XXX1 XXX2的功能>的实现 一.题目要求 编写MyCP.java 实现类似Linux下cp XXX1 XXX2的功能,要求MyCP支持两个参数: java MyC ...

  3. 编写MyCP.java 实现类似Linux下cp XXX1 XXX2的功能

    题目:编写MyCP.java 实现类似Linux下cp XXX1 XXX2的功能 要求:MyCP支持两个参数: java MyCP -tx XXX1.txt XXX2.bin 用来把文本文件(内容为十 ...

  4. 20175303 Mycp实现Linux下cp xxx1 xxx2的功能

    20175303 Mycp实现Linux下cp xxx1 xxx2的功能 一.题目要求 编写MyCP2.java 实现类似Linux下cp XXX1 XXX2的功能,要求MyCP2支持两个参数: ja ...

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

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

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

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

  7. 补交 20155202 蓝墨云班课 编写MyCP.java 实现类似Linux下cp XXX1 XXX2的功能

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

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

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

  9. [转帖]linux下的CPU、内存、IO、网络的压力测试

    linux下的CPU.内存.IO.网络的压力测试 https://www.cnblogs.com/zhuochong/p/10185881.html 一.对CPU进行简单测试: 1.通过bc命令计算特 ...

随机推荐

  1. insert erase和replace的例子

    9.43 编写一个函数,接受三个string参数s.oldVal和newVal.使用迭代器及insert和erase函数将s中所有oldval替换为newVal.测试程序,用它替换通用的简写形式,如, ...

  2. html页面docutype前面出现字符会导致IE678 margin:0 auto;失效

    html页面<!DOCTYPE html>前面出现字符会导致IE678 margin:0 auto;失效

  3. C# 指针(unsafe与fixed的使用)

    c#在默认情况下生成的都是安全代码,即进行了代码托管(.NET的CLR机制好处之一是,进行代码托管,适时的释放内存,程序员便不必考虑资源的回收问题),而此时,指针不能出现在安全代码的编译条件下. 一. ...

  4. View绘制详解,从LayoutInflater谈起

    自定义View算是Android开发中的重中之重了,很多小伙伴可能或多或少都玩过自定义View,对View的绘制流程也有一定的理解.那么现在我想通过几篇博客来详细介绍View的绘制流程,以便使我们更加 ...

  5. 考试宝典-真题园安卓AppV2.1.0新版发布啦,全新界面,全新体验,全面适配Android 5.0&6.0系统!

    真题园移动客户端是真题园网 http://www.zhentiyuan.com 旗下的一款学习考试应用App. 1.全新适配Android5.0.6.0系统,重新优化架构网络通信模块. 2.全新清爽U ...

  6. next nextval

    1 KMP算法中next与nextval值的计算 以上两张图代表了next值的求法,本人总结后做如下叙述: 根据公式可知: next[1]=0 next[2]=1 next[3]的求法根据公式可以直接 ...

  7. CSS——伪元素与伪类

    伪类与伪元素 伪类:在特殊性中占据0,0,1,0 :link 向未访问的链接添加特殊的样式.也就是说,链接所指的 URI 尚未出现在用户代理的历史中.这种状态与 :visited状态是互斥的. :vi ...

  8. HTML5中表单元素的formaction属性

    在submit按钮中,根据不同的submit按钮,将表单提交到不同的页面中: <form id="test" action="test.jsp"> ...

  9. oracle 不转义 &

    在为表加注释,遇到有些注释包含'&' 但又不想写eacape, 在sqlplus下,set define off   即可将&输入到数据库中.

  10. 【排障】tomact未能看到网页

    [排障]tomact未能看到网页 文:食梦貘 这是几个月前的事情了,那时候我在安装xwiki,需要用到tomcat,但是初次安装好时碰上过一个故障: 安装tomcat后,客户机用IE网址上输入:服务端 ...