驱动代码:

#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. 已超过了锁请求超时时段。 (Microsoft SQL Server,错误: 1222)

    操作SQLServer数据库时.遇到这种问题:已超过了锁请求超时时段. (Microsoft SQL Server,错误: 1222) 经过查找材料了解为资源抢占,照成死锁,杀死进程就OK了.详细操作 ...

  2. 设计模式之Composite模式(笔记)

    组合模式:将对象组合成树形结构以表示"部分-总体"的层次结构. 组合模式使得用户对单个对象和组合对象的使用具有一致性. 适用场合:当需求中是体现部分与总体层次的结构时,以及希望用户 ...

  3. string与数值之间的转换

    9.50 编写程序处理一个vector<string>,其元素都表示整数型.计算vector中所有元素之和.修改程序,使之计算表示浮点值的string之和. 程序如下: #include& ...

  4. 进程关系之tcgetpgrp、tcsetpgrp和tcgetsid函数

    需要有一种方法来通知内核哪一个进程组是前台进程组,这样,终端设备驱动程序就能了解将终端输入和终端产生的信号送到何处. #include <unistd.h> pid_t tcgetpgrp ...

  5. php实用函数整理

    1. 排序:array_multisort 可以对多位数组的多个字段进行排序 例子1如下: //自定义数组排序--按转发数从高到低排序 function sortSelfRc($oneLayer){ ...

  6. Asp.Net 5使用第三方容器

    这几天在学习Asp.Net 5,现在文档以及博客之类的资料实在太少了,不看源码几乎举步维艰,好在全都是开源的,看看微软的代码也获益良多. 看到DependencyInjection的代码里除了默认的容 ...

  7. 探索高效jQuery的奥秘

    讨论jQuery和javascript性能的文章并不罕见.然而,本文我计划总结一些速度方面的技巧和我本人的一些建议,来提升你的jQuery和javascript代码.好的代码会带来速度的提升.快速渲染 ...

  8. compile ffmpeg

    download SDL 1.2.xxx version source code. 1) configure 2) make & make instll download recent ffm ...

  9. oracle学习总结5(游标、触发器、过程、方法)

    1:捕获plsql抛出的异常 declarev_ename emp.ename%type;beginselect ename into v_ename from emp where empno=10; ...

  10. TamperData火狐插件启用

    今天第一次在准备学习sqlmap的时候看到有人使用了这个TamperData火狐的插件,所以我也安装来看看,光是安装了,但是重启浏览器之后不知道怎么启用,得不到想要的运行界面,所以在这里记录一下,为自 ...