tiny4412开发板LED灯驱动写法
2017-11-12 15:08
323 查看
简介
led灯成本很低,操控简单,在嵌入式产品中不可或缺,可以作为调试标识,状态指示等等,高级用法还可以作为呼吸灯进一步增强其美观性。本章介绍只控制led灯的亮灭,
tiny4412开发板有四个
LED灯在核心板上供用户操作,led灯亮灭靠
cpu
IO口输出电平,具体操控看实际电路。
电路图
在tiny4412开发板上,led灯电路如下:与CPU连接如下:
可以看到CPU相应引脚输出相关电平,就可以控制灯的亮灭,cpu引脚输出低电平led灯亮,接下来就是操作相关寄存器,这些寄存器与GPM4相关,一个是控制寄存器,一个是数据寄存器。
命令寄存器
数据寄存器
驱动代码
//驱动代码 #include<linux/kernel.h> #include<linux/module.h> #include<linux/init.h> #include <asm/io.h> #include <asm/uaccess.h> #include<linux/fs.h> #include<linux/cdev.h> #include<linux/kdev_t.h> #include<linux/slab.h> #include<linux/device.h> //增加自动创建设备头文件 #include<linux/uaccess.h> //定义字符设备结构体 static struct cdev *leddriver_cdev; //定义设备号(包含主次) static dev_t leddriver_num=0; //定义设备类 static struct class *leddriver_class; //定义设备结构体 static struct device *leddriver_device; //定义错误返回类型 static int err; //定义设备名称 #define LEDDRIVER_NAME "myled" #define GPM4CON_ADDR 0x110002E0 #define GPM4DAT_ADDR 0X110002E4 static volatile unsigned long *gpm4con=NULL; static volatile unsigned long *gpm4dat=NULL; #define GPM4CON *gpm4con #define GPM4DAT *gpm4dat static ssize_t leddriver_read(struct file *file, char __user *usr, size_t size, loff_t *loft) { unsigned char LED_STATUE; copy_from_user(&LED_STATUE,usr,1); printk("leddriver read is %d\r\n",LED_STATUE); switch(LED_STATUE) { case 10:GPM4DAT |= (0x1<<0);break; case 11:GPM4DAT &=~(0X1<<0);break; case 20:GPM4DAT |= (0x1<<1);break; case 21:GPM4DAT &=~(0X1<<1);break; case 30:GPM4DAT |= (0x1<<2);break; case 31:GPM4DAT &=~(0X1<<2);break; case 40:GPM4DAT |= (0x1<<3);break; case 41:GPM4DAT &=~(0X1<<3);break; } return 0; } ssize_t leddriver_write (struct file *file, const char __user *usr, size_t size, loff_t *loft) { printk("leddriver write is ok\r\n"); return 0; } int leddriver_open (struct inode *node, struct file *file) { printk("files open is success\r\n"); return 0; } int leddriver_release (struct inode *node, struct file *file) { printk("leddriver close is success\r\n"); return 0; } //文件操作函数结构体 static struct file_operations leddriver_fops={ .owner=THIS_MODULE, .open=leddriver_open, .release=leddriver_release, .read=leddriver_read, .write=leddriver_write, }; static __init int ldedriver_init(void) { //分配字符设备结构体,前面只是定义没有分配空间 leddriver_cdev=cdev_alloc(); //判断分配成功与否 if(leddriver_cdev==NULL) { err=-ENOMEM; printk("leddriver alloc is err\r\n"); goto err_leddriver_alloc; } //动态分配设备号 err=alloc_chrdev_region(&leddriver_num, 0, 1, LEDDRIVER_NAME); //错误判断 if(err<0) { printk("alloc leddriver num is err\r\n"); goto err_alloc_chrdev_region; } //初始化结构体 cdev_init(leddriver_cdev,&leddriver_fops); //驱动注册 err=cdev b62e _add(leddriver_cdev,leddriver_num,1); if(err<0) { printk("cdev add is err\r\n"); goto err_cdev_add; } //创建设备类 leddriver_class=class_create(THIS_MODULE,"led_class"); err=PTR_ERR(leddriver_class); if(IS_ERR(leddriver_class)) { printk("leddriver creat class is err\r\n"); goto err_class_create; } //创建设备 leddriver_device=device_create(leddriver_class,NULL, leddriver_num,NULL, "leddevice"); err=PTR_ERR(leddriver_device); if(IS_ERR(leddriver_device)) { printk("leddriver device creat is err \r\n"); goto err_device_create; } //led灯寄存器配置 gpm4con=ioremap(GPM4CON_ADDR, 4); gpm4dat=ioremap(GPM4DAT_ADDR, 4); GPM4CON &= ~(0XFFFF<<0); GPM4CON |= (0x1111<<0); GPM4DAT |= (0XF<<0); printk("leddriver init is success\r\n"); return 0; err_device_create: class_destroy(leddriver_class); err_class_create: cdev_del(leddriver_cdev); err_cdev_add: unregister_chrdev_region(leddriver_num, 1); err_alloc_chrdev_region: kfree(leddriver_cdev); err_leddriver_alloc: return err; } static __exit void leddriver_exit(void) { //取消映射 iounmap(gpm4con); iounmap(gpm4dat); device_destroy(leddriver_class,leddriver_num); class_destroy(leddriver_class); cdev_del(leddriver_cdev); unregister_chrdev_region(leddriver_num, 1); printk("leddriver is exit\r\n"); } module_init(ldedriver_init); module_exit(leddriver_exit); MODULE_LICENSE("GPL");
app代码
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> int main(int argc,char *argv[]) { unsigned char LED_STATUE,shi; int ge; int led_fp; led_fp = open(argv[1],O_RDWR); // LED_STATUE=(unsigned char)atoi(argv[2]); while(1) { for(shi=1;shi<=4;shi++) { for(ge=1;ge>=0;ge--) { LED_STATUE=shi*10+ge; read(led_fp,&LED_STATUE,1); sleep(1); } } } close(led_fp); }
Makefile
KERN_DIR = /zhangchao/linux3.5/linux-3.5 all: make -C $(KERN_DIR) M=`pwd` modules cp: cp ./* /zhangchao/rootfs/zhangchao clean: make -C $(KERN_DIR) M=`pwd` modules clean rm -rf modules.order obj-m += led.o
说明
虽然调用read write函数,来实现对灯的控制,并不符合函数操作规范,这里的led灯并不能看做是一个文件操作,并没有体现出linux一切皆文件,并不符合标准的文件操作方法,规范化写法将在后面给出。
相关文章推荐
- 基于tiny4412开发板LED灯驱动标准的llseek函数写法
- tiny4412内核自带led驱动分析
- 第三十三天:Tiny4412驱动开发之LED驱动和u-boot移植
- [FrameBuffer驱动]利用Libjpeg库通过C语言向tiny4412开发板刷一幅jpg图片
- Tiny4412之蜂鸣器驱动与led灯驱动
- S3C2440开发板LED驱动——ioremap 映射
- FL2440开发板 platform_led驱动及应用程序
- 往开发板写led驱动时出现错误:insmod: can't insert 's3c_led.ko': unknown symbol in module or invalid parameter
- Tiny210开发板wm8960驱动
- 【4412开发板使用经验分享】迅为4412开发板I2C驱动问题
- Tiny 4412 lcd 驱动分析
- 手把手教你写Linux设备驱动---input子系统(四)--电容屏驱动ft5x06编写(一)(基于友善之臂4412开发板)
- s5pv210开发板 led驱动学习笔记
- Uboot的启动流程--以友善之臂tiny4412开发板为例
- tiny4412开发板 之 浅谈为什么使用 内嵌汇编
- 迅为4412开发板Linux驱动教程/硬件知识及原理图的使用
- 手把手教你从零实现Linux misc设备驱动二(基于友善之臂4412开发板)
- tiny4412-arm嵌入式开发裸板驱动 (二):arm基础GPIO操作
- 从零开始写linux字符设备驱动程序(三)(基于友善之臂tiny4412开发板)
- 4412驱动-fifth_fasyn 控制led 蜂鸣器 按键