驱动代码:

#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. 学习笔记之Shell脚本的输出重定向

    shell http://baike.baidu.com/link?url=qN3THt5ZJhQtwRJJkakWdz5-vZp4V9H3OmNP97XNhaoL-dqU-6rrFrYfHXmYv6 ...

  2. PHP为fopen,file_get_contents等函数请求web地址时增加Http头的方法

    我们在使用fsockopen时可以方便的自定义自己请求的http头内容来访问某些对客户端请求头有特殊限制的网站,但是使用fopen,file_get_contents等函数请求web地址时怎么来灵活定 ...

  3. php输出错误信息

    error_reporting(E_ALL);  ini_set('display_errors','on'); header("Content-Type:text/html;charset ...

  4. 【转】Adobe CC 的下载地址

    http://trials3.adobe.com/AdobeProducts/AEFT/12/win64/AfterEffects_12_LS20.7z http://trials3.adobe.co ...

  5. Swift数据类型

    1.Swift中常用数据类型:首字母大写 Int.Float.Double.Bool.Character.String Array.Dictionary.元组类型(Tuple).可选类型Optiona ...

  6. [转]使用Oracle SQL Developer连接数据库并创建用户

    本文转自:http://blog.csdn.net/xw13106209/article/details/6594738 1.使用sys账户创建数据库连接 安装Oracle 11g会自带一个叫做SQL ...

  7. Lodash Filter

    var persons = [{name:'1',age:'20'}, {name:'2', age:'25'}];_.filter(persons, {'age': '25'}); //return ...

  8. C#扫盲之:==/Equals /ReferenceEquals 异同的总结,相等性你真的知道吗?

    1.前言 == Equals ReferenceEquals 三个相等性测试,是.NET提供给程序员使用的三个方法,他们之间有什么联系和区别,你真的仔细研究过?虽然之前也多多少少知道一点,但是有时候又 ...

  9. 动态上传多个文件(asp)

    CreateElements.html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" &quo ...

  10. Android M Developer Preview - API Preview(一)

    API Overview The M Developer Preview gives you an advance look at the upcoming release for the Andro ...