您的位置:首页 > 运维架构 > Linux

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一切皆文件,并不符合标准的文件操作方法,规范化写法将在后面给出。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息