led灯成本很低,操控简单,在嵌入式产品中不可或缺,可以作为调试标识,状态指示等等,高级用法还可以作为呼吸灯进一步增强其美观性。本章介绍只控制led
灯的亮灭,tiny4412
开发板有四个LED
灯在核心板上供用户操作,led灯亮灭靠cpu
IO
口输出电平,具体操控看实际电路。
在tiny4412开发板上,led灯电路如下:
与CPU连接如下:
可以看到CPU相应引脚输出相关电平,就可以控制灯的亮灭,cpu引脚输出低电平led灯亮,接下来就是操作相关寄存器,这些寄存器与GPM4相关,一个是控制寄存器,一个是数据寄存器。
命令寄存器
数据寄存器
//驱动代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include //增加自动创建设备头文件
#include
//定义字符设备结构体
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_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");
#include
#include
#include
#include
#include
#include
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);
}
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一切皆文件,并不符合标准的文件操作方法,规范化写法将在后面给出。