LCD背光控制的实现(PWM应用)(2)

LCD背光控制的实现(PWM应用)(2)

.3背光驱动的实现

本RSU系统使用一个通用的背光层驱动和用户及内核的其他模块交互。该背光驱动作为PWM模块和用户/内核其他模块交互的中间层,接收来自用户或内核模块的命令,然后转化为对PWM的控制命令,如开启、关闭、调整等。

在用户接口方面,使用Linux 2.6内核特有的sysfs文件系统,实现内核与用户间的交互。Sysfs是一个可读写的文件系统,通过提供一些变量,内核输出设备的属性,如LCD背光的当前亮度值,最大亮度值等。用户可以通过改变这些变量的值,设置设备的属性。Sysfs文件系统提供的用户接口如下:

/* interface for exporting device attributes */

struct device_attribute {

       struct attribute       attr;

       ssize_t (*show)(struct device *dev, struct device_attribute *attr,      char *buf);

       ssize_t (*store)(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);

};

其中,attr是设备的标识,show和store是两个函数指针。内核通过show向用户输出设备属性,用户层则通过store设置设备的属性。在LCD背光驱动中,定义了以下结构:

#define __ATTR(_name,_mode,_show,_store) { \

       .attr = {.name = __stringify(_name), .mode = _mode },     \

       .show     = _show,                             \

       .store      = _store,                             \

}

static struct device_attribute bl_device_attributes[] = {

       __ATTR(bl_power, 0644, backlight_show_power, backlight_store_power),

       __ATTR(brightness, 0644, backlight_show_brightness, backlight_store_brightness),

       __ATTR(actual_brightness, 0444, backlight_show_actual_brightness, NULL),

       __ATTR(max_brightness, 0444, backlight_show_max_brightness, NULL),

              __ATTR_NULL,

};

如上,系统向用户层输出bl_power,brightness,actual_brightness,max_brightness四个属性值,其中前两个是可写的,后两个是只读的。例如,内核通过backlight_show_power向用户层输出属性bl_power的值。通过backlight_store_power接受来自用户层的输入值,然后将其设置为bl_power属性的当前值。

通过sysfs文件系统,本手持RSU系统为用户层提供两种背光调整方式。一为亮度等级的调整(bl_power),值为0~4,0为高亮,1、2、3次之,4为全灭。另一种是线性调整方式(brightness),其值为从0~TCNTB,其值越大,背光的亮度越高。

本系统通过通知链表(Notifier Chain)[8]技术,实现LCD背光驱动与内核其他模块(如LCD)的交互。通知链表是内核模块间的一种通讯方式,它的工作方式和中断类似。一旦某个模块有事件发生,它便通知已经注册到这个模块链表的其他模块。这样,其他模块就可以根据所发生的事件,调用相应的处理例程。

首先定义一个通知链表。LCD驱动中定义的通知链表如下:

static BLOCKING_NOTIFIER_HEAD(fb_notifier_list);

接着,外部模块注册到这个通知链表中,背光驱动注册如下:

blocking_notifier_chain_register(&fb_notifier_list, nb);

其中,参数nb是如下一个结构,由外部模块提供:

struct notifier_block {

    int (*notifier_call)(struct notifier_block *, unsigned long, void *);

    struct notifier_block *next;

    int priority;

};

完成注册操作后,一旦LCD模块有事件发生,它便会以该事件(even)作为参数,调用如下函数:

blocking_notifier_call_chain(&fb_notifier_list, val, v);

该函数遍历在这个链表中注册过的notifier_block,并执行其中的处理例程。例如,当LCD发生UNBLANK事件时,它遍历相应的通知链表,执行背光系统注册的处理例程,将升压开关调整器的使能端置为0,关闭背光的输出。

综上,整个背光的控制流程如图4所示。

图4 LCD背光控制的框图

通过测试,可以得到如表2所示的和背光能耗相关一些数值。

表2 LCD功耗列表

TCMPB1

(TCNB1)

电流

(mA)

电压

(V)

功率

(mW)

1

113

20.0

2260.0

3/4

83

19.1

1585.3

1/2

55

18.0

990.0

1/4

23

16.9

388.7

1/8

10

16.2

162.0

1/16

5

15.9

79.5

在实际使用的过程中,设置1/2值的亮度即可,只有在特殊的场合才需要设置为高亮。而在系统等待的时候,可以将其值设置为1/16,这时背光的功耗只有79mW,约为最大功耗的1/28,大大节省了能耗。
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值