Linux内核LED子系统、请务必看
前言
LED子系統你要是說很難嘛,但是它就是控制一些簡單的GPIO口,但是你要是說它很簡單嘛,但是我也不見得一個初學者很快就能掌握,你如果是剛入門這部分的話,我覺得你還是要去仔細研究下這些驅動。前兩天在網上看到一句話,初學者喜歡研究語法,大牛喜歡研究數據結構,Linux下的數據結構非常多,把這些東西搞明白對你非常有幫助。
簡單說下LED子系統
應用的話不是很想解釋,應用就是調用驅動的接口,打開、關閉、設置等等操作。
核心是為驅動和效果和應用服務的,所以我們很多東西都依賴于核心,所以會有一些基本的數據結構,注冊、卸載等函數。
驅動的用法很簡單,但是在簡單的用法后面蘊藏著巨大的秘密,Linux下的很多驅動都是如此,填充好一些數據結構,然后調用register函數注冊,這樣之后,就能把驅動注冊起來。
trigger指的是一種效果,比如亮、滅、是一個效果,驅動里面就做成了default-on的效果,還有閃爍、呼吸等,都是不同的效果。
AW9110 LED驅動芯片
我們分析下這個芯片的硬件連接吧,先分析下硬件有啥特點。
這是一款I2C接口的LED驅動IC,默認的驅動電流大小是37mA,有256個驅動等級,讀到這里我們應該可以知道,我們可以用這個IC做呼吸的功能。
看一個驅動的流程理解
我吹幾句
我們寫程序的時候,需要注意的是在dts里面可以設置什么,這個應該是關鍵,如果這個是一個LED燈驅動,那么,在dts里面就需要設置LED的屬性,比如這個LED燈有什么效果,默認效果是什么。
還有就是要注意led_classdev,因為register注冊的時候就是把這個結構體填充的東西給注冊起來的。
dts
+???????aw9110b:?aw9110b@5b?{ +???????????????compatible?=?"aw9110b-leds"; +???????????????gpio_out_drv?=?<AW9110B_TOTEM_POLE>; +???????????????shdn-gpio?=?<&pio?19?GPIO_ACTIVE_HIGH>; +???????????????reg?=?<0x5b>; +???????????????#address-cells?=?<1>; +???????????????#size-cells?=?<0>; +???????????????status?=?"okay"; + +???????????????led1:?led@1?{ +???????????????????????????????label?=?"led_cam1"; +???????????????????????????????reg?=?<1>; +???????????????????????????????flags?=?<AW_MAKE_FLAGS(AW_GROUPB,?AW_OUT0,?AW_MODE_LED,?255)>; +???????????????????????????????led-max-microamp?=?<10000>; +???????????????????????????????linux,default-trigger?=?"default-on"; +???????????????}; }led_classdev 結構體
struct?led_classdev?{const?char??*name;enum?led_brightness??brightness;enum?led_brightness??max_brightness;int????flags;/*?Lower?16?bits?reflect?status?*/ #define?LED_SUSPENDED??(1?<<?0)/*?Upper?16?bits?reflect?control?information?*/ #define?LED_CORE_SUSPENDRESUME?(1?<<?16) #define?LED_BLINK_ONESHOT?(1?<<?17) #define?LED_BLINK_ONESHOT_STOP?(1?<<?18) #define?LED_BLINK_INVERT?(1?<<?19) #define?LED_SYSFS_DISABLE?(1?<<?20) #define?SET_BRIGHTNESS_ASYNC?(1?<<?21) #define?SET_BRIGHTNESS_SYNC?(1?<<?22) #define?LED_DEV_CAP_FLASH?(1?<<?23)/*?Set?LED?brightness?level?*//*?Must?not?sleep,?use?a?workqueue?if?needed?*/void??(*brightness_set)(struct?led_classdev?*led_cdev,enum?led_brightness?brightness);/**?Set?LED?brightness?level?immediately?-?it?can?block?the?caller?for*?the?time?required?for?accessing?a?LED?device?register.*/int??(*brightness_set_sync)(struct?led_classdev?*led_cdev,enum?led_brightness?brightness);/*?Get?LED?brightness?level?*/enum?led_brightness?(*brightness_get)(struct?led_classdev?*led_cdev);/**?Activate?hardware?accelerated?blink,?delays?are?in?milliseconds*?and?if?both?are?zero?then?a?sensible?default?should?be?chosen.*?The?call?should?adjust?the?timings?in?that?case?and?if?it?can't*?match?the?values?specified?exactly.*?Deactivate?blinking?again?when?the?brightness?is?set?to?a?fixed*?value?via?the?brightness_set()?callback.*/int??(*blink_set)(struct?led_classdev?*led_cdev,unsigned?long?*delay_on,unsigned?long?*delay_off);struct?device??*dev;const?struct?attribute_group?**groups;struct?list_head??node;???/*?LED?Device?list?*/const?char??*default_trigger;?/*?Trigger?to?use?*/unsigned?long???blink_delay_on,?blink_delay_off;struct?timer_list??blink_timer;int????blink_brightness;void???(*flash_resume)(struct?led_classdev?*led_cdev);struct?work_struct?set_brightness_work;int???delayed_set_value;#ifdef?CONFIG_LEDS_TRIGGERS/*?Protects?the?trigger?data?below?*/struct?rw_semaphore??trigger_lock;struct?led_trigger?*trigger;struct?list_head??trig_list;void???*trigger_data;/*?true?if?activated?-?deactivate?routine?uses?it?to?do?cleanup?*/bool???activated; #endif/*?Ensures?consistent?access?to?the?LED?Flash?Class?device?*/struct?mutex??led_access; };LED trigger 的理解
我這里打開的是呼吸的trigger,這個trigger是用來實現呼吸效果的,但是我們這個IC沒有自主呼吸的功能,所以我們需要實現呼吸的話,肯定是離不開定時器的,我們使用一個定時器在一個時間段內不斷的改變輸出的電流,以此來改變輸出的亮度。這樣讓用戶就看到呼吸的效果了。
我簡單的說下這個呼吸曲線,因為人眼對亮度的觀察并不是線性的,舉個例子,理想的做法是,我們的曲線在一個時間內遞增一樣大小的電流,這樣輸出看到的亮度也是曲線增加的,但是因為我們人眼對亮度觀察并不是理想的,所以我們可能看到的是突然變亮,變滅的過程也會極其尷尬。
贈送一段不健全的呼吸曲線
static?const?uint8_t?s_breath_effect[]?=?{0,?0,?0,?0,?1,?2,?3,?4,?6,?8,10,?12,?14,?16,?19,?22,?25,?28,?32,?36,40,?44,?48,?52,?57,?62,?67,?72,?78,?84,90,?96,?102,?108,?115,?122,?129,?136,?144,?152,160,?168,?176,?184,?193,?202,?211,?220,?230,?240,250,?240,?230,?220,?211,?202,?193,?184,?176,?168,160,?152,?144,?136,?129,?122,?115,?108,?102,?96,90,?84,?78,?72,?67,?62,?57,?52,?48,?44,40,?36,?32,?28,?25,?22,?19,?16,?14,?12,10,?8,?6,?4,?3,?2,?1,?0,?0,?0, };LED sys節點
節點
android:/sys/class/leds?#?ls blue??????????led_cam_b?led_key1?屬性
android:/sys/class/leds/led_key1?#?ls brightness?device?max_brightness?power?subsystem?trigger?ueventtrigger
android:/sys/class/leds/led_key1?#?cat?trigger [none]?rc-feedback?nand-disk?mmc0?timer?oneshot?heartbeat?breath? 推薦閱讀:
? 專輯|Linux文章匯總
? 專輯|程序人生
? 專輯|C語言
嵌入式Linux
微信掃描二維碼,關注我的公眾號
總結
以上是生活随笔為你收集整理的Linux内核LED子系统、请务必看的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于FPGA ZC706的AD9371A
- 下一篇: linux通过I2C地址查看设备名称