历史上的今天
今天是:2025年03月10日(星期一)
2020年03月10日 | Tiny6410 简单的LED字符设备驱动
2020-03-10 来源:eefocus
首先分析原来:
1.查看用户手册

led1、led2、led3、led4 连接的分别是 GPK4、GPK5、GPK6、GPK7
2、查询6410芯片手册



下面还需要3个步骤:
1、设置GPIO为OUTPUT。
将GPK4、GPK5、GPK6、GPK7设置为输出output=0001
即GPKCON0的19:28都配置为0001
2、设置GPIO的数据。
将GPKDATA的4:7位赋值为0
3、设置GPKUP为上拉。
将GPKUP的4:7位设置为10
3、代码
led_driver.c
#include #include #include #include #include #include #include #include #define LED_MAJOR 243 #define LED_ON 1 #define LED_OFF 0 #define LED_1_ON 2 #define LED_1_OFF 3 #define LED_2_ON 4 #define LED_2_OFF 5 #define LED_3_ON 6 #define LED_3_OFF 7 #define LED_4_ON 8 #define LED_4_OFF 9 static int led_open (struct inode *inode,struct file *filp) { unsigned tmp; tmp = readl(S3C64XX_GPKCON); tmp = (tmp&0x0000ffff)| 0x1111ffff; writel(tmp, S3C64XX_GPKCON); printk("#########open######n"); return 0; } static int led_read (struct file *filp, char __user *buf, size_t count,loff_t *f_pos) { return count; } static int led_write (struct file *filp, const char __user *buf, size_t count,loff_t *f_pos) { char wbuf[10]; unsigned tmp; if(copy_from_user(wbuf,buf,count)) return -EFAULT; switch(wbuf[0]) { case LED_ON: tmp = readl(S3C64XX_GPKDAT); tmp &= (0x0f); writel(tmp, S3C64XX_GPKDAT); printk("turn on!n"); break; case LED_OFF: tmp = readl(S3C64XX_GPKDAT); tmp |= (0xf0); writel(tmp, S3C64XX_GPKDAT); printk("turn off!n"); break; case LED_1_ON: tmp = readl(S3C64XX_GPKDAT); tmp &= (0xef); writel(tmp, S3C64XX_GPKDAT); printk("turn off!n"); break; case LED_1_OFF: tmp = readl(S3C64XX_GPKDAT); tmp |= (0xf0); writel(tmp, S3C64XX_GPKDAT); printk("turn on!n"); break; case LED_2_ON: tmp = readl(S3C64XX_GPKDAT); tmp &= (0xdf); writel(tmp, S3C64XX_GPKDAT); printk("turn off!n"); break; case LED_2_OFF: tmp = readl(S3C64XX_GPKDAT); tmp |= (0xf0); writel(tmp, S3C64XX_GPKDAT); printk("turn on!n"); break; case LED_3_ON: tmp = readl(S3C64XX_GPKDAT); tmp &= (0xbf); writel(tmp, S3C64XX_GPKDAT); printk("turn off!n"); break; case LED_3_OFF: tmp = readl(S3C64XX_GPKDAT); tmp |= (0xf0); writel(tmp, S3C64XX_GPKDAT); printk("turn on!n"); break; case LED_4_ON: tmp = readl(S3C64XX_GPKDAT); tmp &= (0x7f); writel(tmp, S3C64XX_GPKDAT); printk("turn off!n"); break; case LED_4_OFF: tmp = readl(S3C64XX_GPKDAT); tmp |= (0xf0); writel(tmp, S3C64XX_GPKDAT); printk("turn on!n"); break; default : break; } return 0; } int led_release (struct inode *inode, struct file *filp) { printk("#########release######n"); return 0; } struct file_operations led_fops = { .owner = THIS_MODULE, .open = led_open, .read = led_read, .write = led_write, .release = led_release, }; int __init led_init (void) { int rc; printk ("Test led devn"); rc = register_chrdev(LED_MAJOR,"led",&led_fops); if (rc <0) { printk ("register %s char dev errorn","led"); return -1; } printk ("ok!n"); return 0; } void __exit led_exit (void) { unregister_chrdev(LED_MAJOR,"led"); printk ("module exitn"); return ; } module_init(led_init); module_exit(led_exit); Makefile obj-m := led_driver.o KDIR :=/home/workdir/kernel/linux-2.6.38 all: make -C $(KDIR) M=$(shell pwd) modules install: cp driver_led.ko /tftpboot/ clean: make -C $(KDIR) M=$(shell pwd) clean 测试文件 test_led.c #include #include #include #include #define LED_OFF 0 #define LED_ON 1 #define LED_1_ON 2 #define LED_1_OFF 3 #define LED_2_ON 4 #define LED_2_OFF 5 #define LED_3_ON 6 #define LED_3_OFF 7 #define LED_4_ON 8 #define LED_4_OFF 9 int main (void) { int i=0; int fd; char buf[10]={ LED_ON , LED_OFF , LED_1_ON, LED_1_OFF, LED_2_ON, LED_2_OFF, LED_3_ON, LED_3_OFF, LED_4_ON, LED_4_OFF, }; fd = open("/dev/led",O_RDWR); if (fd < 0) { printf ("Open /dev/led file errorn"); return -1; } while(i<10) { write(fd,&buf[i],4); sleep(1); i++; } close (fd); return 0; } 上述编译没有问题,就可以下到板子测试了。 加载驱动 insmod led_driver.ko 创建设备文件 mknod /dev/led c 243 0 其中243要跟驱动文件中的设备号一致 运行测试文件 ./test_led 完成。 ------------------------------------------------------------------------------------------ 参考资料: #include #include #include #include #include #include #include #include #include #define DEVICE_NAME "leds" /* 加载模式后,执行”cat /proc/devices”命令看到的设备名称 */ #define LED_MAJOR 231 /* 主设备号 */ /* 应用程序执行ioctl(fd, cmd, arg)时的第2个参数 */ #define IOCTL_LED_ON 1 #define IOCTL_LED_OFF 0 /* 用来指定LED所用的GPIO引脚 */ static unsigned long led_table [] = { S3C2410_GPB5, S3C2410_GPB6, S3C2410_GPB7, S3C2410_GPB8, }; /* 用来指定GPIO引脚的功能:输出 */ static unsigned int led_cfg_table [] = { S3C2410_GPB5_OUTP, S3C2410_GPB6_OUTP, S3C2410_GPB7_OUTP, S3C2410_GPB8_OUTP, }; struct leds_type { struct cdev cdev; }; struct leds_type *my_leds_dev; /* 应用程序对设备文件/dev/EmbedSky-leds执行open(...)时, * 就会调用EmbedSky_leds_open函数 */ static int EmbedSky_leds_open(struct inode *inode, struct file *file) { int i; for (i = 0; i < 4; i++) { // 设置GPIO引脚的功能:本驱动中LED所涉及的GPIO引脚设为输出功能 s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]); } return 0; } /* 应用程序对设备文件/dev/EmbedSky-leds执行ioclt(...)时, * 就会调用EmbedSky_leds_ioctl函数 */ static int EmbedSky_leds_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { if (arg > 4) { return -EINVAL; } switch(cmd) { case IOCTL_LED_ON: // 设置指定引脚的输出电平为0 s3c2410_gpio_setpin(led_table[arg], 0); return 0; case IOCTL_LED_OFF: // 设置指定引脚的输出电平为1 s3c2410_gpio_setpin(led_table[arg], 1); return 0; default: return -EINVAL; } } /* 这个结构是字符设备驱动程序的核心 * 当应用程序操作设备文件时所调用的open、read、write等函数, * 最终会调用这个结构中指定的对应函数 */ static struct file_operations EmbedSky_leds_fops = { .owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */ .open = EmbedSky_leds_open, .ioctl = EmbedSky_leds_ioctl, }; static char __initdata banner[] = "TQ2440/SKY2440 LEDS, (c) 2008,2009 www.embedsky.net/n";
史海拾趣
|
我的这块就是KS0108控制器不带汉字库的 datasheet :http://www.datasheetarchive.com/pdf-datasheets/Datasheets-312/166945.pdf 可不可以提供显示图形的程序.具体电路图… 查看全部问答> |
|
麻烦各位了,小弟新手,有几个问题在这里求教: 1.wince自带手写识别软件不能识别简体,请问怎样做才能让它识别简体? 2.如果要编写一个自己的识别软件,难度大吗?编写的大概步骤是什么?(希望能 比帮助文档具体一点)恳请赐告!谢谢 … 查看全部问答> |
|
in [求助] 中, 换了一个电源带来的问题 我的问题这样的, 主机只是简单的扫描端口, 子机负责把信息显示出来(用LED),开机时会读取一下EEPROM中字符,总共才20个字符。 原来我用子机的电源,主机的电源也是从子机那里拉过来的,很正常,也很 ...… 查看全部问答> |
|
本帖最后由 paulhyde 于 2014-9-15 09:47 编辑 传闻今年没有无线通信题目了,不知是否属实。 如果真的没有了,以前做无线通信的该怎么准备呢? … 查看全部问答> |
|
ARM启动代码学习(一)RO和RW还有ZI代表什么?(转载) 一般而言,一个程序包括只读的代码段和可读写的数据段。在ARM的集成开发环境中,只读的代码段和常量被称作RO段(ReadOnly);可读写的全局变量和静态变量被称作RW段(ReadWrite);RW段中要被初始化为零的变量被称为ZI段(ZeroInit) ...… 查看全部问答> |
|
就像叔本华所说的,“要么是孤独,要么就是庸俗”。我不会去想别人的、世俗的感受,我只追求内心的、精神的满足。这就是26岁的我所想的。 1987年出生,我今年刚好26岁。 工作已经五年,在社会这个酱缸里混了五年,在这个肖申克监狱里待了五 ...… 查看全部问答> |
|
晒WEBENCH设计的过程+变送器电源 进入“WEBENCH® 设计中心” http://www.ti.com.cn/lsds/ti_zh/analog/webench/overview.page 输入参数:输入电压12V~36V,输出24V,开始设计 WEBENCH 为设计者提供了多种应用方案 选择其中一个方案 开始 ...… 查看全部问答> |




