欧美色欧美亚洲高清在线观看,国产特黄特色a级在线视频,国产一区视频一区欧美,亚洲成a 人在线观看中文

  1. <ul id="fwlom"></ul>

    <object id="fwlom"></object>

    <span id="fwlom"></span><dfn id="fwlom"></dfn>

      <object id="fwlom"></object>

      S3c2410 LCD驅(qū)動(dòng)學(xué)習(xí)心得[五篇]

      時(shí)間:2019-05-12 07:55:03下載本文作者:會(huì)員上傳
      簡(jiǎn)介:寫(xiě)寫(xiě)幫文庫(kù)小編為你整理了多篇相關(guān)的《S3c2410 LCD驅(qū)動(dòng)學(xué)習(xí)心得》,但愿對(duì)你工作學(xué)習(xí)有幫助,當(dāng)然你在寫(xiě)寫(xiě)幫文庫(kù)還可以找到更多《S3c2410 LCD驅(qū)動(dòng)學(xué)習(xí)心得》。

      第一篇:S3c2410 LCD驅(qū)動(dòng)學(xué)習(xí)心得

      S3c2410 LCD驅(qū)動(dòng)學(xué)習(xí)心得

      一 實(shí)驗(yàn)內(nèi)容簡(jiǎn)要描述 1.實(shí)驗(yàn)?zāi)康?/p>

      學(xué)會(huì)驅(qū)動(dòng)程序的編寫(xiě)方法,配置S3C2410的LCD驅(qū)動(dòng),以及在LCD屏上顯示包括bmp和jpeg兩種格式的圖片 2.實(shí)驗(yàn)內(nèi)容

      (1)分析S3c2410實(shí)驗(yàn)箱LCD以及LCD控制器的硬件原理,據(jù)此找出相應(yīng)的硬件設(shè)置參數(shù),參考xcale實(shí)驗(yàn)箱關(guān)于lcd的設(shè)置,完成s3c2410實(shí)驗(yàn)箱LCD的設(shè)置

      (2)在LCD上顯示一張BMP圖片或JPEG圖片 3.實(shí)驗(yàn)條件(軟硬件環(huán)境)

      PC機(jī)、S3C2410開(kāi)發(fā)板、PXA255開(kāi)發(fā)板 二 實(shí)驗(yàn)原理

      1.S3C2410內(nèi)置LCD控制器分析 1.1 S3C2410 LCD控制器

      一塊LCD屏顯示圖像,不但需要LCD驅(qū)動(dòng)器,還需要有相應(yīng)的LCD控制器。通常LCD驅(qū)動(dòng)器會(huì)以COF/COG的形式與LCD 玻璃基板制作在一起,而LCD控制器則由外部電路來(lái)實(shí)現(xiàn)。而S3C2410內(nèi)部已經(jīng)集成了LCD控制器,因此可以很方便地去控制各種類(lèi)型的LCD屏,例如:STN和TFT屏。S3C2410 LCD控制器的特性如下:(1)STN屏

      支持3種掃描方式:4bit單掃、4位雙掃和8位單掃 支持單色、4級(jí)灰度和16級(jí)灰度屏

      支持256色和4096色彩色STN屏(CSTN)

      支持分辯率為640*480、320*240、160*160以及其它規(guī)格的多種LCD(2)TFT屏

      支持單色、4級(jí)灰度、256色的調(diào)色板顯示模式 支持64K和16M色非調(diào)色板顯示模式

      支持分辯率為640*480,320*240及其它多種規(guī)格的LCD 對(duì)于控制TFT屏來(lái)說(shuō),除了要給它送視頻資料(VD[23:0])以外,還有以下一些信號(hào)是必不可少的,分別是:

      VSYNC(VFRAME):幀同步信號(hào) HSYNC(VLINE):行同步信號(hào) VCLK :像數(shù)時(shí)鐘信號(hào)

      VDEN(VM):數(shù)據(jù)有效標(biāo)志信號(hào)

      由于本項(xiàng)目所用的S3C2410上的LCD是TFT屏,并且TFT屏將是今后應(yīng)用的主流,因此接下來(lái),重點(diǎn)圍繞TFT屏的控制來(lái)進(jìn)行。

      圖1.1是S3C2410內(nèi)部的LCD控制器的邏輯示意圖:

      圖1.1 REGBANK 是LCD控制器的寄存器組,用來(lái)對(duì)LCD控制器的各項(xiàng)參數(shù)進(jìn)行設(shè)置。而 LCDCDMA 則是LCD控制器專(zhuān)用的DMA信道,負(fù)責(zé)將視頻資料從系統(tǒng)總線(System Bus)上取來(lái),通過(guò) VIDPRCS 從VD[23:0]發(fā)送給LCD屏。同時(shí) TIMEGEN 和 LPC3600 負(fù)責(zé)產(chǎn)生 LCD屏所需要的控制時(shí)序,例如VSYNC、HSYNC、VCLK、VDEN,然后從 VIDEO MUX 送給LCD屏。

      1.2 TFT屏?xí)r序分析

      圖1.2是TFT屏的典型時(shí)序。其中VSYNC是幀同步信號(hào),VSYNC每發(fā)出1個(gè)脈沖,都意味著新的1屏視頻資料開(kāi)始發(fā)送。而HSYNC為行同步信號(hào),每個(gè)HSYNC脈沖都表明新的1行視頻資料開(kāi)始發(fā)送。而VDEN則用來(lái)標(biāo)明視頻資料的有效,VCLK是用來(lái)鎖存視頻資料的像數(shù)時(shí)鐘。

      并且在幀同步以及行同步的頭尾都必須留有回掃時(shí)間,例如對(duì)于VSYNC來(lái)說(shuō)前回掃時(shí)間就是(VSPW+1)+(VBPD+1),后回掃時(shí)間就是(VFPD +1);HSYNC亦類(lèi)同。這樣的時(shí)序要求是當(dāng)初CRT顯示器由于電子槍偏轉(zhuǎn)需要時(shí)間,但后來(lái)成了實(shí)際上的工業(yè)標(biāo)準(zhǔn),乃至于后來(lái)出現(xiàn)的TFT屏為了在時(shí)序上于CRT兼容,也采用了這樣的控制時(shí)序。

      圖1.2 S3C2410實(shí)驗(yàn)箱上的LCD是一款3.5寸TFT真彩LCD屏,分辯率為240*320,下圖為該屏的時(shí)序要求。

      圖1.3 通過(guò)對(duì)比圖1.2和圖1.3,我們不難看出: VSPW+1=2-> VSPW=1 VBPD+1=2-> VBPD=1 LINVAL+1=320-> LINVAL=319 VFPD+1=3-> VFPD=2 HSPW+1=4-> HSPW=3 HBPD+1=7-> HBPW=6 HOZVAL+1=240-> HOZVAL=239 HFPD+1=31-> HFPD=30 以上各參數(shù),除了LINVAL和HOZVAL直接和屏的分辯率有關(guān),其它的參數(shù)在實(shí)際操作過(guò)程中應(yīng)以上面的為參考,不應(yīng)偏差太多。

      1.3 LCD控制器主要寄存器功能詳解

      圖1.4 LINECNT :當(dāng)前行掃描計(jì)數(shù)器值,標(biāo)明當(dāng)前掃描到了多少行。

      CLKVAL :決定VCLK的分頻比。LCD控制器輸出的VCLK是直接由系統(tǒng)總線(AHB)的工作頻率HCLK直接分頻得到的。做為240*320的TFT屏,應(yīng)保證得出的VCLK在5~10MHz之間。MMODE :VM信號(hào)的觸發(fā)模式(僅對(duì)STN屏有效,對(duì)TFT屏無(wú)意義)。

      PNRMODE :選擇當(dāng)前的顯示模式,對(duì)于TFT屏而言,應(yīng)選擇[11],即TFT LCD panel。BPPMODE :選擇色彩模式,對(duì)于真彩顯示而言,選擇16bpp(64K色)即可滿足要求。ENVID :使能LCD信號(hào)輸出。

      圖1.5 VBPD,LINEVAL,VFPD,VSPW 的各項(xiàng)含義已經(jīng)在前面的時(shí)序圖中得到體現(xiàn)。

      圖1.6 HBPD,HOZVAL,HFPD 的各項(xiàng)含義已經(jīng)在前面的時(shí)序圖中得到體現(xiàn)。

      圖1.7 HSPW 的含義已經(jīng)在前面的時(shí)序圖中得到體現(xiàn)。MVAL 只對(duì) STN屏有效,對(duì)TFT屏無(wú)意義。

      HSPW 的含義已經(jīng)在前面的時(shí)序圖中得到體現(xiàn),這里不再贅述。MVAL 只對(duì) STN屏有效,對(duì)TFT屏無(wú)意義。

      圖1.8 VSTATUS :當(dāng)前VSYNC信號(hào)掃描狀態(tài),指明當(dāng)前VSYNC同步信號(hào)處于何種掃描階段。HSTATUS :當(dāng)前HSYNC信號(hào)掃描狀態(tài),指明當(dāng)前HSYNC同步信號(hào)處于何種掃描階段。

      BPP24BL :設(shè)定24bpp顯示模式時(shí),視頻資料在顯示緩沖區(qū)中的排列順序(即低位有效還是高位有效)。對(duì)于16bpp的64K色顯示模式,該設(shè)置位無(wú)意義。

      FRM565 :對(duì)于16bpp顯示模式,有2中形式,一種是RGB=5:5:5:1,另一種是5:6:5。后一種模式最為常用,它的含義是表示64K種色彩的16bit RGB資料中,紅色(R)占了5bit,綠色(G)占了6bit,蘭色(B)占了5bit INVVCLK,INVLINE,INVFRAME,INVVD :通過(guò)前面的時(shí)序圖,我們知道,CPU的LCD控制器輸出的時(shí)序默認(rèn)是正脈沖,而LCD需要VSYNC(VFRAME)、VLINE(HSYNC)均為負(fù)脈沖,因此 INVLINE 和 INVFRAME 必須設(shè)為“1 ”,即選擇反相輸出。INVVDEN,INVPWREN,INVLEND 的功能同前面的類(lèi)似。

      PWREN 為L(zhǎng)CD電源使能控制。在CPU LCD控制器的輸出信號(hào)中,有一個(gè)電源使能管腳LCD_PWREN,用來(lái)做為L(zhǎng)CD屏電源的開(kāi)關(guān)信號(hào)。

      ENLEND 對(duì)普通的TFT屏無(wú)效,可以不考慮。

      BSWP 和 HWSWP 為字節(jié)(Byte)或半字(Half-Word)交換使能。由于不同的GUI對(duì)FrameBuffer(顯示緩沖區(qū))的管理不同,必要時(shí)需要通過(guò)調(diào)整 BSWP 和 HWSWP 來(lái)適應(yīng)GUI。2.Linux 驅(qū)動(dòng) 2.1 FrameBuffer Linux是工作在保護(hù)模式下,所以用戶態(tài)進(jìn)程是無(wú)法像DOS那樣使用顯卡BIOS里提供的中斷調(diào)用來(lái)實(shí)現(xiàn)直接寫(xiě)屏,Lin仿顯卡的功能,將顯ux抽象出FrameBuffer這個(gè)設(shè)備來(lái)供用戶態(tài)進(jìn)程實(shí)現(xiàn)直接寫(xiě)屏。Framebuffer機(jī)制模卡硬件結(jié)構(gòu)抽象掉,可以通過(guò)Framebuffer的讀寫(xiě)直接對(duì)顯存進(jìn)行操作。用戶可以將Framebuffer看成是顯示內(nèi)存的一個(gè)映像,將其映射到進(jìn)程地址空間之后,就可以直接進(jìn)行讀寫(xiě)操作,而寫(xiě)操作可以立即反應(yīng)在屏幕上。這種操作是抽象的,統(tǒng)一的。用戶不必關(guān)心物理顯存的位置、換頁(yè)機(jī)制等等具體細(xì)節(jié)。這些都是由Framebuffer設(shè)備驅(qū)動(dòng)來(lái)完成的。

      在Linux系統(tǒng)下,F(xiàn)rameBuffer的主要的結(jié)構(gòu)如圖所示。Linux為了開(kāi)發(fā)FrameBuffer程序的方便,使用了分層結(jié)構(gòu)。fbmem.c處于Framebuffer設(shè)備驅(qū)動(dòng)技術(shù)的中心位置。它為上層應(yīng)用程序提供系統(tǒng)調(diào)用,也為下一層的特定硬件驅(qū)動(dòng)提供接口;那些底層硬件驅(qū)動(dòng)需要用到這兒的接口來(lái)向系統(tǒng)內(nèi)核注冊(cè)它們自己。

      fbmem.c 為所有支持FrameBuffer的設(shè)備驅(qū)動(dòng)提供了通用的接口,避免重復(fù)工作。下將介紹fbmem.c主要的一些數(shù)據(jù)結(jié)構(gòu)。

      2.2 數(shù)據(jù)結(jié)構(gòu)

      2.2.1 Linux FrameBuffer的數(shù)據(jù)結(jié)構(gòu)

      在FrameBuffer中,fb_info可以說(shuō)是最重要的一個(gè)結(jié)構(gòu)體,它是Linux為幀緩沖設(shè)備定義的驅(qū)動(dòng)層接口。它不僅包含了底層函數(shù),而且還有記錄設(shè)備狀態(tài)的數(shù)據(jù)。每個(gè)幀緩沖設(shè)備都與一個(gè)fb_info結(jié)構(gòu)相對(duì)應(yīng)。fb_info的主要成員如下 struct fb_info { int node;struct fb_var_screeninfo var;/* Current var */ struct fb_fix_screeninfo fix;/* Current fix */ struct fb_videomode *mode;/* current mode */

      struct fb_ops *fbops;struct device *device;/* This is the parent */ struct device *dev;/* This is this fb device */

      char __iomem *screen_base;/* Virtual address */ unsigned long screen_size;/* Amount of ioremapped VRAM or 0 */

      ………… };其中node成員域標(biāo)示了特定的FrameBuffer,實(shí)際上也就是一個(gè)FrameBuffer設(shè)備的次設(shè)備號(hào)。fb_var_screeninfo結(jié)構(gòu)體成員記錄用戶可修改的顯示控制器參數(shù),包括屏幕分辨率和每個(gè)像素點(diǎn)的比特?cái)?shù)。fb_var_screeninfo中的xres定義屏幕一行有多少個(gè)點(diǎn), yres定義屏幕一列有多少個(gè)點(diǎn), bits_per_pixel定義每個(gè)點(diǎn)用多少個(gè)字節(jié)表示。其他域見(jiàn)以下代碼注釋。struct fb_var_screeninfo { __u32 xres;/* visible resolution */ __u32 yres;__u32 xoffset;/* offset from virtual to visible */ __u32 yoffset;/* resolution */ __u32 bits_per_pixel;/* bits/pixel */ __u32 pixclock;/* pixel clock in ps(pico seconds)*/ __u32 left_margin;/* time from sync to picture */ __u32 right_margin;/* time from picture to sync */ __u32 hsync_len;/* length of horizontal sync */ __u32 vsync_len;/* length of vertical sync */ ………… };在fb_info結(jié)構(gòu)體中,fb_fix_screeninfo中記錄用戶不能修改的顯示控制器的參數(shù),如屏幕緩沖區(qū)的物理地址,長(zhǎng)度。當(dāng)對(duì)幀緩沖設(shè)備進(jìn)行映射操作的時(shí)候,就是從fb_fix_screeninfo中取得緩沖區(qū)物理地址的。struct fb_fix_screeninfo { char id[16];/* identification string eg “TT Builtin” */ unsigned long smem_start;/* Start of frame buffer mem(physical address)*/ __u32 smem_len;/* Length of frame buffer mem */ unsigned long mmio_start;/* Start of Mem Mapped I/O(physical address)*/ __u32 mmio_len;/* Length of Memory Mapped I/O */ ………… };fb_info還有一個(gè)很重要的域就是fb_ops。它是提供給底層設(shè)備驅(qū)動(dòng)的一個(gè)接口。通常我們編寫(xiě)字符驅(qū)動(dòng)的時(shí)候,要填寫(xiě)一個(gè)file_operations結(jié)構(gòu)體,并使用register_chrdev()注冊(cè)之,以告訴Linux如何操控驅(qū)動(dòng)。當(dāng)我們編寫(xiě)一個(gè)FrameBuffer的時(shí)候,就要依照Linux FrameBuffer編程的套路,填寫(xiě)fb_ops結(jié)構(gòu)體。這個(gè)fb_ops也就相當(dāng)于通常的file_operations結(jié)構(gòu)體。struct fb_ops { int(*fb_open)(struct fb_info *info, int user);int(*fb_release)(struct fb_info *info, int user);ssize_t(*fb_read)(struct file *file, char __user *buf, size_t count, loff_t *ppos);ssize_t(*fb_write)(struct file *file, const char __user *buf, size_t count, loff_t *ppos);int(*fb_set_par)(struct fb_info *info);int(*fb_setcolreg)(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info);int(*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info)int(*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);…………… } 上面的結(jié)構(gòu)體,根據(jù)函數(shù)的名字就可以看出它的作用,這里不在一一說(shuō)明。下圖給出了Linux FrameBuffer的總體結(jié)構(gòu),作為這一部分的總結(jié)。圖2.2

      2.2.2 S3C2410中LCD的數(shù)據(jù)結(jié)構(gòu)

      在S3C2410的LCD設(shè)備驅(qū)動(dòng)中,定義了s3c2410fb_info來(lái)標(biāo)識(shí)一個(gè)LCD設(shè)備,結(jié)構(gòu)體如下: struct s3c2410fb_info { struct fb_info *fb;struct device *dev;struct s3c2410fb_mach_info *mach_info;struct s3c2410fb_hw regs;/* LCD Hardware Regs */ dma_addr_t map_dma;/* physical */ u_char * map_cpu;/* virtual */ u_int map_size;/* addresses of pieces placed in raw buffer */ u_char * screen_cpu;/* virtual address of buffer */ dma_addr_t screen_dma;/* physical address of buffer */ ………… };成員變量fb指向我們上面所說(shuō)明的fb_info結(jié)構(gòu)體,代表了一個(gè)FrameBuffer。dev則表示了這個(gè)LCD設(shè)備。map_dma,map_cpu,map_size這三個(gè)域向了開(kāi)辟給LCD DMA使用的內(nèi)存地址。screen_cpu,screen_dma指向了LCD控制器映射的內(nèi)存地址。另外regs標(biāo)識(shí)了LCD控制器的寄存器。struct s3c2410fb_hw { unsigned long lcdcon1;unsigned long lcdcon2;unsigned long lcdcon3;unsigned long lcdcon4;unsigned long lcdcon5;};這個(gè)寄存器和硬件的寄存器一一對(duì)應(yīng),主要作為實(shí)際寄存器的映像,以便程序使用。這個(gè)s3c2410fb_info中還有一個(gè)s3c2410fb_mach_info成員域。它存放了和體系結(jié)構(gòu)相關(guān)的一些信息,如時(shí)鐘、LCD設(shè)備的GPIO口等等。這個(gè)結(jié)構(gòu)體定義為 struct s3c2410fb_mach_info { unsigned char fixed_syncs;/* do not update sync/border */ int type;/* LCD types */ int width;/* Screen size */ int height;struct s3c2410fb_val xres;/* Screen info */ struct s3c2410fb_val yres;struct s3c2410fb_val bpp;struct s3c2410fb_hw regs;/* lcd configuration registers */ /* GPIOs */ unsigned long gpcup;unsigned long gpcup_mask;unsigned long gpccon;unsigned long gpccon_mask;………… };

      圖2.3 上圖表示了S3C2410驅(qū)動(dòng)的整體結(jié)構(gòu),反映了結(jié)構(gòu)體之間的相互關(guān)系 2.3 主要代碼結(jié)構(gòu)以及關(guān)鍵代碼分析 2.3.1 FrameBuffer驅(qū)動(dòng)的統(tǒng)一管理

      fbmem.c實(shí)現(xiàn)了Linux FrameBuffer的中間層,任何一個(gè)FrameBuffer驅(qū)動(dòng),在系統(tǒng)初始化時(shí),必須向fbmem.c注冊(cè),即需要調(diào)用register_framebuffer()函數(shù),在這個(gè)過(guò)程中,設(shè)備驅(qū)動(dòng)的信息將會(huì)存放入名稱為registered_fb數(shù)組中,這個(gè)數(shù)組定義為 struct fb_info *registered_fb[FB_MAX];int num_registered_fb;它是類(lèi)型為fb_info的數(shù)組,另外num_register_fb則存放了注冊(cè)過(guò)的設(shè)備數(shù)量。

      我們分析一下register_framebuffer的代碼。int register_framebuffer(struct fb_info *fb_info){ int i;struct fb_event event;struct fb_videomode mode;if(num_registered_fb == FB_MAX)return-ENXIO;/* 超過(guò)最大數(shù)量 */ num_registered_fb++;for(i = 0;i < FB_MAX;i++)if(!registered_fb[i])break;/* 找到空余的數(shù)組空間 */ fb_info->node = i;

      fb_info->dev = device_create(fb_class, fb_info->device, MKDEV(FB_MAJOR, i), “fb%d”, i);/* 為設(shè)備建立設(shè)備節(jié)點(diǎn) */ if(IS_ERR(fb_info->dev)){ ………… } else{ fb_init_device(fb_info);/* 初始化改設(shè)備 */ } ………… return 0;} 從上面的代碼可知,當(dāng)FrameBuffer驅(qū)動(dòng)進(jìn)行注冊(cè)的時(shí)候,它將驅(qū)動(dòng)的fb_info結(jié)構(gòu)體記錄到全局?jǐn)?shù)組registered_fb中,并動(dòng)態(tài)建立設(shè)備節(jié)點(diǎn),進(jìn)行設(shè)備的初始化。注意,這里建立的設(shè)備節(jié)點(diǎn)的次設(shè)備號(hào)就是該驅(qū)動(dòng)信息在registered_fb存放的位置,即數(shù)組下標(biāo)i。在完成注冊(cè)之后,fbmem.c就記錄了驅(qū)動(dòng)的fb_info。這樣我們就有可能實(shí)現(xiàn)fbmem.c對(duì)全部FrameBuffer驅(qū)動(dòng)的統(tǒng)一處理。

      2.3.2 實(shí)現(xiàn)消息的分派

      fbmem.c實(shí)現(xiàn)了對(duì)系統(tǒng)全部FrameBuffer設(shè)備的統(tǒng)一管理。當(dāng)用戶嘗試使用一個(gè)特定的FrameBuffer時(shí),fbmem.c怎么知道該調(diào)用那個(gè)特定的設(shè)備驅(qū)動(dòng)呢?

      我們知道,Linux是通過(guò)主設(shè)備號(hào)和次設(shè)備號(hào),對(duì)設(shè)備進(jìn)行唯一標(biāo)識(shí)。不同的FrameBuffer設(shè)備向fbmem.c注冊(cè)時(shí),程序分配給它們的主設(shè)備號(hào)是一樣的,而次設(shè)備號(hào)是不一樣的。于是我們就可以通過(guò)用戶指明的次設(shè)備號(hào),來(lái)覺(jué)得具體該調(diào)用哪一個(gè)FrameBuffer驅(qū)動(dòng)。下面通過(guò)分析fbmem.c的fb_open()函數(shù)來(lái)說(shuō)明。(注:一般我們寫(xiě)FrameBuffer驅(qū)動(dòng)不需要實(shí)現(xiàn)open函數(shù),這里只是說(shuō)明函數(shù)流程。)static int fb_open(struct inode *inode, struct file *file){ int fbidx = iminor(inode);struct fb_info *info;int res;/* 得到真正驅(qū)動(dòng)的函數(shù)指針 */ if(!(info = registered_fb[fbidx]))return-ENODEV;if(info->fbops->fb_open){ res = info->fbops->fb_open(info,1);//調(diào)用驅(qū)動(dòng)的open()if(res)module_put(info->fbops->owner);} return res;} 當(dāng)用戶打開(kāi)一個(gè)FrameBuffer設(shè)備的時(shí),將調(diào)用這里的fb_open()函數(shù)。傳進(jìn)來(lái)的inode就是欲打開(kāi)設(shè)備的設(shè)備號(hào),包括主設(shè)備和次設(shè)備號(hào)。fb_open函數(shù)首先通過(guò)iminor()函數(shù)取得次設(shè)備號(hào),然后查全局?jǐn)?shù)組registered_fb得到設(shè)備的fb_info信息,而這里面存放了設(shè)備的操作函數(shù)集fb_ops。這樣,我們就可以調(diào)用具體驅(qū)動(dòng)的fb_open()函數(shù),實(shí)現(xiàn)open的操作。下面給出了一個(gè)LCD驅(qū)動(dòng)的open()函數(shù)的調(diào)用流程圖,用以說(shuō)明上面的步驟。

      圖2.4

      2.3.3 開(kāi)發(fā)板S3C2410 LCD驅(qū)動(dòng)的流程

      (1)在mach-smdk2410.c中,定義了初始的LCD參數(shù)。注意這是個(gè)全局變量。static struct s3c2410fb_mach_info smdk2410_lcd_cfg = {.regs= {.lcdcon1 = S3C2410_LCDCON1_TFT16BPP | S3C2410_LCDCON1_TFT| S3C2410_LCDCON1_CLKVAL(7),......},.width = 240,.height = 320,.xres = {.min = 240,.max= 240,.defval = 240},.bpp = {.min = 16,.max= 16,.defval = 16},......};(2)內(nèi)核初始化時(shí)候調(diào)用s3c2410fb_probe函數(shù)。下面分析這個(gè)函數(shù)的做的工作。首先先動(dòng)態(tài)分配s3c2410fb_info空間。

      fbinfo = framebuffer_alloc(sizeof(struct s3c2410fb_info),&pdev->dev);把域mach_info指向mach-smdk2410.c中的smdk2410_lcd_cfg。info->mach_info = pdev->dev.platform_data;設(shè)置fb_info域的fix,var,fops字段。

      fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;fbinfo->fix.type_aux = 0;fbinfo->fix.xpanstep = 0;

      fbinfo->var.nonstd = 0;fbinfo->var.activate = FB_ACTIVATE_NOW;fbinfo->var.height = mach_info->height;fbinfo->var.width = mach_info->width;

      fbinfo->fbops = &s3c2410fb_ops;……

      該函數(shù)調(diào)用s3c2410fb_map_video_memory()申請(qǐng)DMA內(nèi)存,即顯存。

      fbi->map_size = PAGE_ALIGN(fbi->fb->fix.smem_len + PAGE_SIZE);fbi->map_cpu = dma_alloc_writecombine(fbi->dev, fbi->map_size, &fbi->map_dma, GFP_KERNEL);

      fbi->map_size = fbi->fb->fix.smem_len;…….設(shè)置控制寄存器,設(shè)置硬件寄存器。

      memcpy(&info->regs, &mach_info->regs,sizeof(info->regs));info->regs.lcdcon1 &= ~S3C2410_LCDCON1_ENVID;……….調(diào)用函數(shù)s3c2410fb_init_registers(),把初始值寫(xiě)入寄存器。

      writel(fbi->regs.lcdcon1, S3C2410_LCDCON1);writel(fbi->regs.lcdcon2, S3C2410_LCDCON2);

      (3)當(dāng)用戶調(diào)用mmap()映射內(nèi)存的時(shí)候,F(xiàn)bmem.c把剛才設(shè)置好的顯存區(qū)域映射給用戶。start = info->fix.smem_start;len = PAGE_ALIGN((start & ~PAGE_MASK)+ info->fix.smem_len);io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, vma->vm_end-vma->vm_start,vma->vm_page_prot);

      ……

      這樣就完成了驅(qū)動(dòng)初始化到用戶調(diào)用的整個(gè)過(guò)程。3.BMP和JPEG圖形顯示程序

      3.1 在LCD上顯示BMP或JPEG圖片的主流程圖

      首先,在程序開(kāi)始前。要在nfs/dev目錄下創(chuàng)建LCD的設(shè)備結(jié)點(diǎn),設(shè)備名fb0,設(shè)備類(lèi)型為字符設(shè)備,主設(shè)備號(hào)為29,次設(shè)備號(hào)為0。命令如下: mknod fb0 c 29 0 在LCD上顯示圖象的主流程圖如圖3.1所示。程序一開(kāi)始要調(diào)用open函數(shù)打開(kāi)設(shè)備,然后調(diào)用ioctl獲取設(shè)備相關(guān)信息,接下來(lái)就是讀取圖形文件數(shù)據(jù),把圖象的RGB值映射到顯存中,這部分是圖象顯示的核心。對(duì)于JPEG格式的圖片,要先經(jīng)過(guò)JPEG解碼才能得到RGB數(shù)據(jù),本項(xiàng)目中直接才用現(xiàn)成的JPEG庫(kù)進(jìn)行解碼。對(duì)于bmp格式的圖片,則可以直接從文件里面提取其RGB數(shù)據(jù)。要從一個(gè)bmp文件里面把圖片數(shù)據(jù)陣列提取出來(lái),首先必須知道bmp文件的格式。下面來(lái)詳細(xì)介紹bmp文件的格式。

      圖3.1

      3.2 bmp位圖格式分析

      位圖文件可看成由四個(gè)部分組成:位圖文件頭、位圖信息頭、彩色表和定義位圖的字節(jié)陣列。如圖3.2所示。

      圖3.2 文件頭中各個(gè)段的地址及其內(nèi)容如圖3.3。

      圖3.3 位圖文件頭數(shù)據(jù)結(jié)構(gòu)包含BMP圖象文件的類(lèi)型,顯示內(nèi)容等信息。它的數(shù)據(jù)結(jié)構(gòu)如下定義: Typedef struct {

      int bfType;//表明位圖文件的類(lèi)型,必須為BM long bfSize;//表明位圖文件的大小,以字節(jié)為單位 int bfReserved1;//屬于保留字,必須為本0 int bfReserved2;//也是保留字,必須為本0 long bfOffBits;//位圖陣列的起始位置,以字節(jié)為單位 } BITMAPFILEHEADER; 圖3.4 位圖文件頭的數(shù)據(jù)結(jié)構(gòu)

      (2)信息頭中各個(gè)段的地址及其內(nèi)容如圖3.5所示。圖3.5 位圖信息頭的數(shù)據(jù)結(jié)構(gòu)包含了有關(guān)BMP圖象的寬,高,壓縮方法等信息,它的C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)如圖3.6所示。Typedef struct { long biSize; //指出本數(shù)據(jù)結(jié)構(gòu)所需要的字節(jié)數(shù) long biWidth;//以象素為單位,給出BMP圖象的寬度 long biHeight;//以象素為單位,給出BMP圖象的高度 int biPlanes;//輸出設(shè)備的位平面數(shù),必須置為1 int biBitCount;//給出每個(gè)象素的位數(shù) long biCompress;//給出位圖的壓縮類(lèi)型 long biSizeImage;//給出圖象字節(jié)數(shù)的多少 long biXPelsPerMeter;//圖像的水平分辨率 long biYPelsPerMeter;//圖象的垂直分辨率 long biClrUsed;//調(diào)色板中圖象實(shí)際使用的顏色素?cái)?shù) long biClrImportant;//給出重要顏色的索引值 } BITMAPINFOHEADER;

      圖3.6 BITMAPINFOHEADER數(shù)據(jù)結(jié)構(gòu)

      (3)對(duì)于象素小于或等于16位的圖片,都有一個(gè)顏色表用來(lái)給圖象數(shù)據(jù)陣列提供顏色索引,其中的每塊數(shù)據(jù)都以B、G、R的順序排列,還有一個(gè)是reserved保留位。而在圖形數(shù)據(jù)區(qū)域存放的是各個(gè)象素點(diǎn)的索引值。它的C語(yǔ)言結(jié)構(gòu)如圖3.7所示。

      圖3.7 顏色表數(shù)據(jù)結(jié)構(gòu)

      (4)對(duì)于24位和32位的圖片,沒(méi)有彩色表,他在圖象數(shù)據(jù)區(qū)里直接存放圖片的RGB數(shù)據(jù),其中的每個(gè)象素點(diǎn)的數(shù)據(jù)都以B、G、R的順序排列。每個(gè)象素點(diǎn)的數(shù)據(jù)結(jié)構(gòu)如圖3.8所示。

      圖3.8 圖象數(shù)據(jù)陣列的數(shù)據(jù)結(jié)構(gòu)

      (5)由于圖象數(shù)據(jù)陣列中的數(shù)據(jù)是從圖片的最后一行開(kāi)始往上存放的,因此在顯示圖象時(shí),是從圖象的左下角開(kāi)始逐行掃描圖象,即從左到右,從下到上。

      (6)對(duì)S3C2410或PXA255開(kāi)發(fā)板上的LCD來(lái)說(shuō),他們每個(gè)象素點(diǎn)所占的位數(shù)為16位,這16位按B:G:R=5:6:5的方式分,其中B在最高位,R在最低位。而從bmp圖象得到的R、G、B數(shù)據(jù)則每個(gè)數(shù)據(jù)占8位,合起來(lái)一共24位,因此需要對(duì)該R、G、B數(shù)據(jù)進(jìn)行移位組合成一個(gè)16位的數(shù)據(jù)。移位方法如下:

      b >>= 3;g >>= 2;r >>= 3;RGBValue =(r<<11 | g << 5 | b);基于以上分析,提取各種類(lèi)型的bmp圖象的流程如圖3.9所示

      圖 3.9

      3.3 實(shí)現(xiàn)顯示任意大小的圖片

      開(kāi)發(fā)板上的LCD屏的大小是固定的,S3C2410上的LCD為:240*320,PXA255上的為:640*480。比屏幕小的圖片在屏上顯示當(dāng)然沒(méi)問(wèn)題,但是如果圖片比屏幕大呢?這就要求我們通過(guò)某種算法對(duì)圖片進(jìn)行縮放。

      縮放的基本思想是將圖片分成若干個(gè)方塊,對(duì)每個(gè)方塊中的R、G、B數(shù)據(jù)進(jìn)行取平均,得到一個(gè)新的R、G、B值,這個(gè)值就作為該方塊在LCD屏幕上的映射??s放的算法描述如下:

      (1)、計(jì)算圖片大小與LCD屏大小的比例,以及方塊的大小。為了適應(yīng)各種屏幕大小,這里并不直接給lcd_width和lcd_height賦值為240和320。而是調(diào)用標(biāo)準(zhǔn)的接口來(lái)獲取有關(guān)屏幕的參數(shù)。具體如下:

      // Get variable screen information if(ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)){ printf(“Error reading variable information.”);exit(3);} unsigned int lcd_width=vinfo.xres;unsigned int lcd_height=vinfo.yres;

      計(jì)算比例:

      widthScale=bmpi->width/lcd_width;heightScale=bmpi->height/lcd_height;本程序中方塊的大小以如下的方式確定: unsigned int paneWidth= unsigned int paneHeight=;符號(hào) 代表向上取整。

      (2)、從圖片的左上角開(kāi)始,以(i* widthScale,j* heightScale)位起始點(diǎn),以寬paneWidth 高paneHeight為一個(gè)小方塊,對(duì)該方塊的R、G、B數(shù)值分別取平均,得到映射點(diǎn)的R、G、B值,把該點(diǎn)作為要在LCD上顯示的第(i , j)點(diǎn)存儲(chǔ)起來(lái)。這部分的程序如下: //-------------取平均--------for(i=0;ir=div_round(color_sum_r,paneHeight*paneWidth);RGBvalue_256->g=div_round(color_sum_g,paneHeight*paneWidth);RGBvalue_256->b=div_round(color_sum_b,paneHeight*paneWidth);} } 3.4 圖片數(shù)據(jù)提取及顯示的總流程

      通過(guò)以上的分析,整個(gè)圖片數(shù)據(jù)提取及顯示的總流程如圖3.10 所示。圖 3.10 三 實(shí)驗(yàn)過(guò)程與結(jié)果 1.Linux 源代碼的修改

      首先修改arch/arm/mach-smdk2410.c文件,加入以下代碼。static struct s3c2410fb_mach_info smdk2440_lcd_cfg __initdata = {.regs = {.lcdcon1 = S3C2410_LCDCON1_TFT16BPP | S3C2410_LCDCON1_TFT | S3C2410_LCDCON1_CLKVAL(7),.lcdcon2 = S3C2410_LCDCON2_VBPD(4)| S3C2410_LCDCON2_LINEVAL(319)| S3C2410_LCDCON2_VFPD(1)| S3C2410_LCDCON2_VSPW(1),.lcdcon3 = S3C2410_LCDCON3_HBPD(26)| S3C2410_LCDCON3_HOZVAL(239)| S3C2410_LCDCON3_HFPD(30),.lcdcon4 = S3C2410_LCDCON4_HSPW(13)| S3C2410_LCDCON4_MVAL(13),.lcdcon5 = S3C2410_LCDCON5_FRM565 | S3C2410_LCDCON5_INVVLINE | S3C2410_LCDCON5_INVVFRAME | S3C2410_LCDCON5_PWREN | S3C2410_LCDCON5_HWSWP, },.lpcsel =((0xCE6)& ~7)| 1<<4,.width = 240,.height = 320,.xres = {.min = 240,.max = 240,.defval = 240, },.yres = {.min = 320,.max = 320,.defval = 320, },.bpp = {.min = 16,.max = 16,.defval = 16, }, };在函數(shù)smdk2410_machine_init()函數(shù)中加入LCD的初始化代碼,見(jiàn)下 static void __init smdk2410_machine_init(void){ s3c24xx_fb_set_platdata(&smdk2440_lcd_cfg);smdk_machine_init();} 2.編譯內(nèi)核,產(chǎn)生zImage文件,放入tftp目錄下。

      3.在nfs的dev目錄下建立FrameBuffer的設(shè)備節(jié)點(diǎn),使用命令: mknod fb0 c 29 0 4.啟動(dòng)開(kāi)發(fā)板,加載內(nèi)核和文件系統(tǒng)。5.編寫(xiě)LCD的應(yīng)用程序,程序見(jiàn)附錄。

      6.采用arm-linux-gcc 編譯應(yīng)用程序,產(chǎn)生可執(zhí)行文件,放入nfs目錄中。7.在開(kāi)發(fā)板上運(yùn)行編譯好的可執(zhí)行文件,便可。

      8.下圖是BMP位圖顯示程序,在S3C2410上的運(yùn)行結(jié)果。

      四 實(shí)驗(yàn)心得體會(huì)

      1. LCD驅(qū)動(dòng)的主要問(wèn)題是沒(méi)有LCD屏的文檔,我們找不到它的那些參數(shù)值,后來(lái)只能參照Linux源碼里面的其他LCD屏的參數(shù)進(jìn)行實(shí)驗(yàn)。

      2. 在驅(qū)動(dòng)差錯(cuò)的過(guò)程中,我們采用跟蹤打印的方法進(jìn)行調(diào)試。剛開(kāi)始的時(shí)候,內(nèi)核打印出一行找不到LCD設(shè)備。我們定位到輸出這行提示的代碼處,進(jìn)行反向跟蹤。發(fā)現(xiàn)傳給函數(shù)的設(shè)備指針為空,于是往上排查,終于發(fā)現(xiàn)源代碼中沒(méi)有定義LCD的設(shè)備信息。于是驅(qū)動(dòng)問(wèn)題也就順利解決了。

      3. 原來(lái)一直以為,只要LCD驅(qū)動(dòng)工作正常了,內(nèi)核起來(lái)的時(shí)候,液晶屏?xí)@示出Logo。當(dāng)時(shí)搞了很久一直沒(méi)有,還以為是驅(qū)動(dòng)的問(wèn)題。后來(lái)隨便寫(xiě)了一個(gè)LCD應(yīng)用程序,竟然能用。

      4. 在調(diào)試過(guò)程應(yīng)用程序中發(fā)現(xiàn),在讀取文件頭的時(shí)候,如果直接定義一個(gè)bitmapfileheader為它動(dòng)態(tài)分配內(nèi)存:

      *bmph=(bitmapfileheader*)malloc(sizeof(bitmapfileheader));然后用fread((char*)bmph,sizeof(bitmapfileheader),1,f)把文件頭一次性讀出來(lái),讀出來(lái)的文件頭是錯(cuò)誤的,經(jīng)過(guò)調(diào)試發(fā)現(xiàn)原因是bitmapfileheader這個(gè)結(jié)構(gòu)體中的type屬性原本應(yīng)該占2字節(jié),但是被編譯器在分配內(nèi)存的時(shí)候進(jìn)行了內(nèi)存對(duì)齊的優(yōu)化,給他分配了4個(gè)字節(jié)的空間,造成讀文件的錯(cuò)誤。因此在編程中要特別注意內(nèi)存對(duì)齊的影響。typedef struct { WORD type;(被優(yōu)化)DWORD bfsize;DWORD reserved;DWORD offbits;} bitmapfileheader;5. 在嵌入式應(yīng)用程序的移植過(guò)程中,我們?cè)瓉?lái)認(rèn)為ARM和PC機(jī)大小尾順序是不同的,因此在應(yīng)用程序中,也對(duì)這個(gè)差別進(jìn)行了處理。當(dāng)時(shí),在調(diào)試過(guò)程中發(fā)現(xiàn),PC機(jī)程序可以直接移植到ARM上,不需要任何改動(dòng)。但是我們的程序,的確存在會(huì)產(chǎn)生大小尾問(wèn)題代碼(在使用fread()讀入時(shí))。這究竟是為什么?有人說(shuō),ARM是可以設(shè)置大小尾順序的。后來(lái)這個(gè)問(wèn)題也沒(méi)有深究下去。五 參考文獻(xiàn)

      (1)嵌入式系統(tǒng)設(shè)計(jì)與應(yīng)用開(kāi)發(fā):鄭靈翔.北京:北京航天航空大學(xué)出版社 2006

      第二篇:linux驅(qū)動(dòng)及g-sensor學(xué)習(xí)心得

      目錄

      1.MODULE_INIT和MODULE_EXIT..............................................................................................2 2.I2C_DRIVER......................................................................................................................................2 3.LINUX的INPUT子系統(tǒng)..................................................................................................................3 3.1 從驅(qū)動(dòng)層到核心層.......................................................................................................................3 3.2 事件處理層的處理.......................................................................................................................3 3.3 設(shè)備結(jié)點(diǎn)的創(chuàng)建...........................................................................................................................4 3.4 設(shè)備的注銷(xiāo)和釋放.......................................................................................................................4 4.WORK QUEUE..................................................................................................................................4 5.HAL層開(kāi)發(fā)........................................................................................................................................5 5.1 HAL_MODULE_INFO_SYM.....................................................................................................5 5.2 對(duì)設(shè)備文件的訪問(wèn).......................................................................................................................7 6.BMA250功能描述..............................................................................................................................7 6.1 電源管理.......................................................................................................................................7 6.2 操作模式.......................................................................................................................................7 6.3 電源模式.......................................................................................................................................8 6.4 SENSOR數(shù)據(jù)..................................................................................................................................8 6.4.1 加速度....................................................................................................................................8 6.4.2 溫度........................................................................................................................................8 6.5 偏移補(bǔ)償.......................................................................................................................................9 6.5.1 慢補(bǔ)償....................................................................................................................................9 6.5.2 快補(bǔ)償....................................................................................................................................9 6.5.3 手動(dòng)補(bǔ)償..............................................................................................................................10 6.5.4 內(nèi)嵌校準(zhǔn)..............................................................................................................................10 6.6 非易失性存儲(chǔ)器.........................................................................................................................10 6.7 中斷控制器.................................................................................................................................10 6.7.1 new data中斷.......................................................................................................................11 6.7.2 slope中斷.............................................................................................................................11 6.7.3 tap中斷.................................................................................................................................12 6.7.4 orientation中斷....................................................................................................................12 6.7.5 flat中斷................................................................................................................................14 6.7.6 low-g中斷.............................................................................................................................15 6.7.7 high-g中斷...........................................................................................................................15 7.SENSOR驅(qū)動(dòng)開(kāi)發(fā)步驟...................................................................................................................15 附錄 BMA250寄存器表......................................................................................................................17 linux驅(qū)動(dòng)及g-sensor學(xué)習(xí)心得

      通過(guò)對(duì)g-sensor driver code的研究學(xué)習(xí),我對(duì)linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)和g-sensor有了一定的了解,現(xiàn)將學(xué)習(xí)所得歸納如下。

      1.module_init和module_exit

      在pd318 project的g-sensor驅(qū)動(dòng)程序bma250.c中,首先包含了兩個(gè)頭文件。其中init.h定義了驅(qū)動(dòng)的初始化和退出相關(guān)的函數(shù),module.h則定義了內(nèi)核模塊相關(guān)的函數(shù)、變量和宏。module_init和module_exit這兩個(gè)宏就被定義在init.h中。

      module_init的作用是聲明一個(gè)驅(qū)動(dòng)程序的入口函數(shù),在init.h中可以看到對(duì)這個(gè)宏的定義如下:

      #define module_init(x)__initcall(x);#define __initcall(fn)device_initcall(fn)#define device_initcall(fn)__define_initcall(“6”,fn,6)#define __define_initcall(level,fn,id)static initcall_t __initcall_##fn##id __used __attribute__((__section__(“.initcall” level “.init”)))= fn

      如果驅(qū)動(dòng)程序要以func函數(shù)作為驅(qū)動(dòng)的入口,則可以這樣聲明:module_init(func)。經(jīng)過(guò)上面的宏處理以后,變成__initcall_func6 __used加入到內(nèi)核映射的“.initcall”區(qū)。內(nèi)核加載的時(shí)候,會(huì)搜索“.initcall”區(qū)內(nèi)的所有條目,并按優(yōu)先級(jí)加載它們。通過(guò)module_init聲明的驅(qū)動(dòng)程序優(yōu)先級(jí)為6,優(yōu)先級(jí)越小越先加載。

      對(duì)于驅(qū)動(dòng)入口函數(shù)func,一般要加上__init屬性,這個(gè)宏告訴編譯器如果這個(gè)模塊被編譯到內(nèi)核,則把這個(gè)函數(shù)放到(.init.text)段。而module_exit用于聲明驅(qū)動(dòng)程序的出口,對(duì)于驅(qū)動(dòng)出口函數(shù),一般要加上__exit屬性,這個(gè)宏與__init類(lèi)似,如果驅(qū)動(dòng)被編譯進(jìn)內(nèi)核,則__exit宏會(huì)忽略清理函數(shù)。

      在內(nèi)核初始化后期,所有帶__init屬性的函數(shù)會(huì)被放在同一個(gè)section里,在用完之后,一次性釋放掉整個(gè)section。當(dāng)函數(shù)初始化完成后,這個(gè)區(qū)域可以被清除掉以節(jié)約系統(tǒng)內(nèi)存。

      2.i2c_driver 在pd318 project中,g-sensor的PS pin連接VDDIO,操作模式采用帶I2C接口的general mode,在bma250.c中可以了解到bma250的i2c_driver的結(jié)構(gòu)定義如下:

      struct i2c_driver bma250_driver = {.driver = {

      .owner = THIS_MODULE,.name = SENSOR_NAME, },.id_table = bma250_id,.probe = bma250_probe,.remove };= bma250_remove, 在這個(gè)結(jié)構(gòu)中,定義了驅(qū)動(dòng)所屬module、驅(qū)動(dòng)名、驅(qū)動(dòng)的id表、驅(qū)動(dòng)初始化以及移除接口。可以通過(guò)i2c_add_driver將sensor driver添加進(jìn)module中,通過(guò)i2c_del_driver將driver移除。

      3.linux的input子系統(tǒng)

      Linux系統(tǒng)提供了input子系統(tǒng),可以用以實(shí)現(xiàn)系統(tǒng)中大多數(shù)輸入設(shè)備的設(shè)備驅(qū)動(dòng),pd318中g(shù)-sensor的設(shè)備驅(qū)動(dòng)就是通過(guò)它來(lái)實(shí)現(xiàn)的。

      input子系統(tǒng)由核心層、驅(qū)動(dòng)層和事件處理層三部分組成。當(dāng)輸入設(shè)備產(chǎn)生了一個(gè)輸入事件時(shí),由驅(qū)動(dòng)層對(duì)事件加以識(shí)別,然后提交給核心層,核心層根據(jù)事件的類(lèi)型將事件交給事件處理層處理,事件處理層將處理結(jié)果再反饋給用戶。其中核心層由/drivers/input/input.c及相關(guān)頭文件實(shí)現(xiàn),對(duì)下提供了設(shè)備驅(qū)動(dòng)的接口,對(duì)上提供了事件處理層的編程接口。這樣,一個(gè)輸入設(shè)備的輸入過(guò)程可以分離為獨(dú)立的兩部分:驅(qū)動(dòng)層到核心層,核心層到事件處理層,整個(gè)鏈路的這兩部分的接口的創(chuàng)建是獨(dú)立的。

      3.1 從驅(qū)動(dòng)層到核心層

      驅(qū)動(dòng)層負(fù)責(zé)和底層的硬件設(shè)備打交道,將底層硬件對(duì)用戶輸入的響應(yīng)轉(zhuǎn)換為標(biāo)準(zhǔn)的輸入事件以后再向上發(fā)送給核心層。

      驅(qū)動(dòng)層先要調(diào)用input_allocate_device接口來(lái)分配一個(gè)設(shè)備,對(duì)設(shè)備進(jìn)行一些屬性賦值,如設(shè)備名、總線類(lèi)型、響應(yīng)事件類(lèi)型及事件參數(shù)、驅(qū)動(dòng)數(shù)據(jù)等等,然后通過(guò)input_register_device函數(shù)向input子系統(tǒng)中注冊(cè)所要驅(qū)動(dòng)的輸入設(shè)備。對(duì)于g-sensor來(lái)說(shuō),驅(qū)動(dòng)需要響應(yīng)EV_ABS事件,該事件需要向核心層提供一個(gè)絕對(duì)坐標(biāo),事件參數(shù)ABS_X、ABS_Y、ABS_Z分別對(duì)應(yīng)g-sensor在x、y、z軸上的偏移量。當(dāng)g-sensor發(fā)生坐標(biāo)變化時(shí),驅(qū)動(dòng)程序需要從相應(yīng)寄存器中讀出偏移量,然后通過(guò)input_report_abs接口上報(bào)給input子系統(tǒng),由input子系統(tǒng)負(fù)責(zé)將事件及參數(shù)變化發(fā)送給事件處理層處理。

      3.2 事件處理層的處理

      驅(qū)動(dòng)層只是把輸入設(shè)備注冊(cè)到input子系統(tǒng)中,在驅(qū)動(dòng)中的code中并不創(chuàng)建設(shè)備結(jié)點(diǎn)。應(yīng)用程序用來(lái)與設(shè)備打交道的設(shè)備結(jié)點(diǎn)的創(chuàng)建由事件處理層調(diào)用核心層的函數(shù)來(lái)實(shí)現(xiàn)。而對(duì)于常用輸入設(shè)備(如mouse、keyboard、joystick等),在創(chuàng)建具體的設(shè)備結(jié)點(diǎn)之前,事件處理層需要先通過(guò)input_register_handler注冊(cè)一類(lèi)設(shè)備的輸入事件處理函數(shù)及相關(guān)接口。以鼠標(biāo)事件處理為例,mouse input_handler定義如下:

      static struct input_handler mousedev_handler = {.event = mousedev_event, //向系統(tǒng)報(bào)告input事件,系統(tǒng)通過(guò)read方法讀取

      .connect = mousedev_connect, //和input_dev匹配后調(diào)用connect構(gòu)建

      .disconnect = mousedev_disconnect,.fops = &mousedev_fops, //event設(shè)備文件的操作方法.minor = MOUSEDEV_MINOR_BASE, //次設(shè)備號(hào)基準(zhǔn)值

      .name = “mousedev”,.id_table = mousedev_ids, //匹配規(guī)則 };

      在linux中沒(méi)有對(duì)g-sensor事件處理register的通用標(biāo)準(zhǔn)定義,對(duì)于這類(lèi)事件,事件處理層會(huì)統(tǒng)一地當(dāng)作evdev事件處理,為設(shè)備創(chuàng)建一個(gè)對(duì)應(yīng)的設(shè)備文件,在HAL層可以通過(guò)open該設(shè)備文件來(lái)實(shí)現(xiàn)與底層的通信。

      3.3 設(shè)備結(jié)點(diǎn)的創(chuàng)建

      向input子系統(tǒng)注冊(cè)一個(gè)硬件設(shè)備后,在input_register_handler中調(diào)用已經(jīng)注冊(cè)的所有類(lèi)型的input handler的connect函數(shù),每一個(gè)connect函數(shù)會(huì)根據(jù)注冊(cè)設(shè)備所支持的事件類(lèi)型判斷是否與自己有關(guān),如果有關(guān)就調(diào)用input_register_minor創(chuàng)建一個(gè)具體的設(shè)備結(jié)點(diǎn)。

      此外,如果已經(jīng)注冊(cè)了一些硬件設(shè)備,此后再注冊(cè)一類(lèi)新的input handler,則同樣會(huì)對(duì)所有已注冊(cè)的設(shè)備調(diào)用新的input handler的connect函數(shù)以確定是否需要?jiǎng)?chuàng)建新的設(shè)備結(jié)點(diǎn)。

      3.4 設(shè)備的注銷(xiāo)和釋放

      在remove driver同時(shí)注銷(xiāo)掉所注冊(cè)的input設(shè)備,通過(guò)input_unregister_device函數(shù)注銷(xiāo)設(shè)備,通過(guò)input_free_device接口釋放設(shè)備資源。

      4.work queue 在pd318 bma250.c的bma25_probe函數(shù)中可以看到,對(duì)于g-sensor狀態(tài)的獲取和report是通過(guò)linux的work queue機(jī)制來(lái)實(shí)現(xiàn)的。這里可以看到一個(gè)宏:INIT_DELAYED_WORK。這個(gè)宏被定義在/linux/workqueue.h中,具體定義如下:

      #define INIT_WORK(_work, _func)

      do {

      __INIT_WORK((_work),(_func), 0);} while(0)

      #define INIT_DELAYED_WORK(_work, _func)

      do {

      INIT_WORK(&(_work)->work,(_func));

      init_timer(&(_work)->timer);

      } while(0)

      從這個(gè)定義中可以看到,INIT_DELAYED_WORK就是帶有timer的INIT_WORK,而INIT_WORK所做的事情就是初始化一個(gè)工作,但是并不馬上執(zhí)行,需要將來(lái)某個(gè)時(shí)刻去觸發(fā)執(zhí)行。INIT_DELAYED_WORK(INIT_WORK)需要兩個(gè)參數(shù),一個(gè)是struct delayed_work(struct work_struct)結(jié)構(gòu)體,一個(gè)是一個(gè)函數(shù)指針_func。這個(gè)初始化實(shí)際上就是為一個(gè)struct work_struct結(jié)構(gòu)體綁定一個(gè)函數(shù)。在/linux/workqueue.h中可以看到struct work_struct的定義如下:

      struct work_struct { atomic_long_t data;#define WORK_STRUCT_PENDING 0 /* T if work item pending execution */ #define WORK_STRUCT_STATIC 1 /* static initializer(debugobjects)*/ #define WORK_STRUCT_FLAG_MASK(3UL)#define WORK_STRUCT_WQ_DATA_MASK(~WORK_STRUCT_FLAG_MASK)struct list_head entry;work_func_t func;#ifdef CONFIG_LOCKDEP struct lockdep_map lockdep_map;#endif };

      在這個(gè)結(jié)構(gòu)體中有一個(gè)成員函數(shù)func,初始化的目的就是使這個(gè)func指向INIT_WORK的第二個(gè)參數(shù)_func。以后調(diào)用schedule_delayed_work(schedule_work)時(shí),只要傳遞struct delayed_work(struct work_struct)結(jié)構(gòu)體參數(shù)即可,不需要再傳遞_func。這是因?yàn)?,處理work的線程實(shí)際上跑的是一個(gè)死循環(huán),有事情就處理,沒(méi)事情就睡眠,而schedule_delayed_work(schedule_work)的作用就是喚醒這個(gè)線程。

      INIT_DELAYED_WORK與schedule_delayed_work,INIT_WORK與schedule_work是對(duì)應(yīng)著使用的,兩者的區(qū)別就是schedule_work在喚醒線程的同時(shí)立刻執(zhí)行_func,而schedule_delayed_work在喚醒線程后delay一段時(shí)間再執(zhí)行。bma250.c通過(guò)使用INIT_DELAYED_WORK與schedule_delayed_work,實(shí)現(xiàn)g-sensor對(duì)不同取樣頻率的支持。

      關(guān)于workqueue還有兩個(gè)函數(shù),它們是cancel_delayed_work和flush_scheduled_work。cancel_delayed_work的作用是對(duì)于一個(gè)延遲執(zhí)行的工作而言,在工作還未執(zhí)行的時(shí)候就把它給取消掉。而flush_scheduled_work的作用是為了防止有競(jìng)爭(zhēng)條件的出現(xiàn)。一般在cancel_delayed_work之后都得調(diào)用flush_scheduled_work,函數(shù)會(huì)一直等待,直到隊(duì)列中所有工作都被執(zhí)行以后才返回。

      5.HAL層開(kāi)發(fā)

      5.1 HAL_MODULE_INFO_SYM HAL層,即硬件抽象層,android層對(duì)于硬件的調(diào)用一般通過(guò)HAL的方式來(lái)完成。要想HAL的編寫(xiě)方法,首先需要了解HAL的運(yùn)行機(jī)制??碼ndroid源碼,可以發(fā)現(xiàn)android中實(shí)現(xiàn)調(diào)用HAL是通過(guò)hw_get_module來(lái)實(shí)現(xiàn)的。

      int hw_get_module(const char *id, const struct hw_module_t **module);上面的是其函數(shù)原型,id會(huì)指定Hardware的id,這是一個(gè)字符串,比如sensor的id是#define SENSORS_HARDWARE_MODULE_ID “sensors”。如果找到了對(duì)應(yīng)的hw_module_t結(jié)構(gòu)體,會(huì)將其指針?lè)湃?module中。代碼實(shí)現(xiàn)如下:

      for(i=0;i

      if(i < HAL_VARIANT_KEYS_COUNT){ /* 獲取“ro.hardware”、“ro.product.board”、“ro.board.platform”、“ro.arch”等key的值*/

      if(property_get(variant_keys[i], prop, NULL)== 0){

      continue;

      }

      /* 獲取并訪問(wèn)HAL動(dòng)態(tài)鏈接庫(kù) */

      snprintf(path, sizeof(path), “%s/%s.%s.so”,HAL_LIBRARY_PATH1, id, prop);

      if(access(path, R_OK)== 0)break;

      snprintf(path, sizeof(path), “%s/%s.%s.so”,HAL_LIBRARY_PATH2, id, prop);

      if(access(path, R_OK)== 0)break;

      } else {

      snprintf(path, sizeof(path), “%s/%s.default.so”,HAL_LIBRARY_PATH1, id);

      if(access(path, R_OK)== 0)break;

      } }

      status =-ENOENT;if(i < HAL_VARIANT_KEYS_COUNT+1){

      /* 調(diào)用load函數(shù)打開(kāi)動(dòng)態(tài)鏈接庫(kù)*/

      status = load(id, path, module);}

      這個(gè)函數(shù)的作用,就是獲取動(dòng)態(tài)鏈接庫(kù)并調(diào)用load函數(shù)打開(kāi)它。再看load函數(shù),可以發(fā)現(xiàn)該函數(shù)中出現(xiàn)了一個(gè)宏HAL_MODULE_INFO_SYM_AS_STR。HAL_MODULE_INFO_SYM_AS_STR是硬件模塊在動(dòng)態(tài)鏈接庫(kù)中的標(biāo)志,定義在hardware.h中如下:

      #define HAL_MODULE_INFO_SYM HMI #define HAL_MODULE_INFO_SYM_AS_STR “HMI”

      再去對(duì)照一個(gè)sensors.app中的代碼:

      extern “C” const struct sensors_module_t HAL_MODULE_INFO_SYM = { common :{

      tag : HARDWARE_MODULE_TAG,version_major : 1,version_minor : 0,id : SENSORS_HARDWARE_MODULE_ID,name : “Bosch sensor module”,author : “Bosch Sensortec”,methods : &sensors_module_methods,dso : NULL,reserved : {}, },get_sensors_list : sensors__get_sensors_list };這里的sensors_module_t結(jié)構(gòu)體的定義為: struct sensors_module_t {

      struct hw_module_t common;

      int(*get_sensors_list)(struct sensors_module_t* module,struct sensor_t const** list);};它定義了一個(gè)hw_module_t類(lèi)型的common成員,和獲取sensors list的接口函數(shù)sensors__get_sensors_list。注意,這里的HAL_MODULE_INFO_SYM必須為這個(gè)名字,這樣編譯器才會(huì)將這個(gè)結(jié)構(gòu)體的導(dǎo)出符號(hào)變?yōu)椤癏MI”。

      從以上分析可以知道,HAL層開(kāi)發(fā)就是要定義一個(gè)hw_module_t結(jié)構(gòu)體,結(jié)構(gòu)體名稱命名為HAL_MODULE_INFO_SYM,然后實(shí)現(xiàn)結(jié)構(gòu)體的相關(guān)內(nèi)容即可。也就是說(shuō),HAL模塊的入口地址就是HAL_MODULE_INFO_SYM變量,通過(guò)它,我們可以訪問(wèn)到HAL模塊中所有想要外部訪問(wèn)到的方法。

      5.2 對(duì)設(shè)備文件的訪問(wèn)

      在HAL層可以通過(guò)訪問(wèn)3.2節(jié)中evdev.c生成的設(shè)備文件來(lái)實(shí)現(xiàn)對(duì)硬件設(shè)備的訪問(wèn)。對(duì)于g-sensor來(lái)說(shuō),要實(shí)現(xiàn)對(duì)于sensor的poll、setDelay、activate、close等函數(shù)接口。在poll接口中,程序通過(guò)一個(gè)循環(huán)去獲取設(shè)備文件中顯示出的sensor的坐標(biāo)變化,在收到EV_SYN事件時(shí),將sensor的坐標(biāo)變化反饋給android系統(tǒng),android對(duì)獲取到的狀態(tài)變化作出相應(yīng)的處理。

      6.bma250功能描述

      6.1 電源管理

      VDD :主電源,為所有內(nèi)部模擬/數(shù)字功能塊供電。VDDIO:專(zhuān)為數(shù)字I/O供電的單獨(dú)電源引腳。

      6.2 操作模式

      General mode :sensor作為外部總線的一個(gè)從設(shè)備,可以配置、使用外部中斷引腳INT1和INT2。

      Dedicated mode :sensor作為一個(gè)獨(dú)立設(shè)備,沒(méi)有外部中斷功能,使用內(nèi)部中斷機(jī)制,一次只能夠被指派處理orientation recognition、tap sensing、slope detection三種中斷中的一種。

      PS引腳的連接狀態(tài)決定了sensor采用哪種操作模式。PS = GND

      general mode with SPI interface PS = VDDIO

      general mode with I2C interface PS = float dedicated mode

      6.3 電源模式

      bma250具有三種電源模式:normal mode、low-power mode和suspend mode。normal mode :電路全開(kāi),整個(gè)g-sensor處于正常工作狀態(tài)。

      low-power mode :周期性地在睡眠和喚醒狀態(tài)之間切換。睡眠狀態(tài)下,除振蕩器外所有器件不工作;喚醒狀態(tài)下工作在正常狀態(tài)。

      suspend mode :包括振蕩器在內(nèi)的整個(gè)board處于power down狀態(tài),僅可以讀取寄存器、寫(xiě)suspend位和softreset寄存器。

      三種模式之間可能的狀態(tài)切換如圖1所示。

      圖1 電源模式切換圖

      6.4 sensor數(shù)據(jù)

      6.4.1 加速度

      每一個(gè)軸上的加速度數(shù)據(jù)都是10個(gè)bit,分為兩個(gè)寄存器來(lái)存儲(chǔ)(MSB :9~2 bit,LSB :1~0 bit)。x、y、z三個(gè)軸的加速度數(shù)據(jù)存儲(chǔ)在寄存器0x02~0x07,依次存儲(chǔ)x、y、z軸加速度的LSB、MSB數(shù)據(jù)。

      加速度數(shù)據(jù)可以使用兩種不同的數(shù)據(jù)流:unfiltered和filtered。使用哪種數(shù)據(jù)流由0x13寄存器的data_high_bw位決定。

      unfiltered :采樣頻率為 2kHz,data_high_bw = 1。filtered : 采樣頻率為帶寬的兩倍,data_high_bw = 0。filtered加速度數(shù)據(jù)帶寬由0x10寄存器的bw位決定。另外,bma250支持四種不同的加速度度量范圍(range),分別為±2g、±4g、±8g和±16g,這由0x0F寄存器的低四位決定。

      6.4.2 溫度 由0x08寄存器決定,溫度范圍為-40°C ~ 87.5°C。

      6.5 偏移補(bǔ)償

      偏移補(bǔ)償就是根據(jù)ADC值對(duì)加速度數(shù)據(jù)作出一個(gè)補(bǔ)償。不過(guò)用于補(bǔ)償?shù)墓布拇嫫鳎╬ublic register)0x38 ~ 0x3D對(duì)每個(gè)軸用于讀寫(xiě)補(bǔ)償?shù)闹挥? bit,而內(nèi)部寄存器(internal register)對(duì)于每個(gè)加速度值都是用10 bit(MSB + LSB)來(lái)存儲(chǔ)的。在這之間需要一個(gè)轉(zhuǎn)換,補(bǔ)償轉(zhuǎn)換原則如圖2所示。

      圖2 8-bit/10-bit補(bǔ)償轉(zhuǎn)換原則圖

      從上圖可以看出,根據(jù)設(shè)定的range,公共寄存器的補(bǔ)償值將要對(duì)輸出的加速度數(shù)據(jù)作出補(bǔ)償。例如,公共寄存器值為00000001b,從圖2中得到加速度數(shù)據(jù)補(bǔ)償為±7.8mg,對(duì)應(yīng)內(nèi)部寄存器為±2 LSB。

      bma250支持四種偏移補(bǔ)償方式:慢補(bǔ)償、快補(bǔ)償、手動(dòng)補(bǔ)償和內(nèi)嵌校準(zhǔn)。對(duì)于慢補(bǔ)償和快補(bǔ)償來(lái)說(shuō),0x37寄存器的offset_target_x、offset_target_y、offset_target_z決定了sensor在x、y、z軸上的目標(biāo)值。而0x36的offset_reset位如果被置為1,則所有的偏移補(bǔ)償寄存器都reset為0。

      6.5.1 慢補(bǔ)償

      如果連續(xù)一定數(shù)量的采樣加速度大于(小于)0x37寄存器所設(shè)置的目標(biāo)值,偏移補(bǔ)償值寄存器0x38 ~ 0x3D的值減少(增加)4 LSB。加速度數(shù)據(jù)的采樣周期由0x37的cut_off位決定,如果cut_off位為0,采樣周期為8,反之為16。

      在x、y、z軸是否采用慢補(bǔ)償分別由寄存器0x36中的hp_x_en、hp_y_en和hp_z_en決定。

      6.5.2 快補(bǔ)償

      連續(xù)取16個(gè)加速度值,計(jì)算出平均值,將這個(gè)平均值與0x37寄存器所設(shè)置的目標(biāo)值的差值寫(xiě)入0x37寄存器中。0x36寄存器的cal_trigger決定了對(duì)哪個(gè)軸實(shí)行快補(bǔ)償。cal_trigger = 00b none cal_trigger = 01b x軸 cal_trigger = 10b y軸 cal_trigger = 11b z軸

      當(dāng)正在進(jìn)行快補(bǔ)償時(shí),慢補(bǔ)償被阻斷。

      6.5.3 手動(dòng)補(bǔ)償

      通過(guò)數(shù)字接口去手動(dòng)設(shè)置補(bǔ)償值。在手動(dòng)補(bǔ)償時(shí)要注意不要影響正在進(jìn)行的偏移補(bǔ)償,所以一般在獲得new data中斷后立刻執(zhí)行。在慢補(bǔ)償有效或快補(bǔ)償正在運(yùn)行時(shí),不允許對(duì)偏移補(bǔ)償寄存器作出寫(xiě)操作。

      6.5.4 內(nèi)嵌校準(zhǔn)

      通過(guò)前面所提到的偏移補(bǔ)償方法計(jì)算出合適的補(bǔ)償值,然后將這些補(bǔ)償值存放在EEPROM中。在每一次設(shè)備重置時(shí),補(bǔ)償值被load進(jìn)image寄存器作為偏移補(bǔ)償,直到它被用其他的補(bǔ)償方式重寫(xiě)。

      6.6 非易失性存儲(chǔ)器

      bma250具有三種存儲(chǔ)器:hard-wired、valatile和non-valatile。non-valatile存儲(chǔ)器通過(guò)EEPROM來(lái)實(shí)現(xiàn),可以通過(guò)訪問(wèn)image寄存器來(lái)訪問(wèn)它。在bma250中共有八個(gè)image寄存器(0x38 ~ 0x3F),0x38 ~ 0x3D被用作存儲(chǔ)偏移補(bǔ)償值,0x3E和0x3F保留備用。

      在兩種情況下EEPROM內(nèi)容會(huì)被load到image寄存器中去,一種情況是設(shè)備重置時(shí),另一種情況是將0x33寄存器中的nvm_load值置為1。只要image寄存器還沒(méi)有l(wèi)oad完成,nv_ram位就為1,在完成后被置成0。image寄存器可以像其他寄存器一樣執(zhí)行讀寫(xiě)操作。

      寫(xiě)EEPROM要經(jīng)過(guò)三步:

      1)將新內(nèi)容寫(xiě)入image寄存器;

      2)將0x33寄存器中的nvm_prog_mode置成1,unlock EEPROM ;

      3)將0x33寄存器中的nvm_prog_trig置為1,并保持nvm_prog_mode為1,激活寫(xiě)操作。

      每次寫(xiě)EEPROM總是要更新整個(gè)EEPROM內(nèi)容,可以通過(guò)讀取0x33寄存器的nvm_rdy位來(lái)檢測(cè)寫(xiě)狀態(tài)。nvm_rdy等于1,表示寫(xiě)操作正在進(jìn)行中;nvm_rdy等于0,表示寫(xiě)操作已完成。在寫(xiě)EEPROM時(shí),電源模式必須處于normal mode,而且不能對(duì)image寄存器作出更新。

      6.7 中斷控制器

      中斷的清除取決于所選擇的中斷模式,bma250支持三種模式:non-latched、latched和temporary。中斷模式可以通過(guò)0x21寄存器的低四位latch_int來(lái)設(shè)置,具體對(duì)應(yīng)關(guān)系如表1所示。

      只要滿足中斷激活條件,就會(huì)產(chǎn)生一個(gè)中斷。在non-latched模式下,除了new data、orientation和flat中斷會(huì)在一個(gè)固定時(shí)間后自動(dòng)重置,其他中斷只要激活條件不再有效,中斷狀態(tài)位和所選擇的pin腳(INT1 and/or INT2)就會(huì)立刻被清除。

      latched模式下,必須通過(guò)將0x21寄存器的reset_init位置為1來(lái)清除中斷狀態(tài)和pin腳。清除時(shí)如果中斷條件仍然保持,中斷狀態(tài)會(huì)在加速度寄存器下次變化時(shí)再次被宣稱。

      表1 中斷模式選擇對(duì)應(yīng)表

      在temporary模式下,中斷狀態(tài)和pin腳在一段時(shí)間后被清除,這段時(shí)間由latch_int的具體值來(lái)決定。

      bma250支持七種中斷機(jī)制,分別為:new data、tap、slope、high-g、low-g、orientation和flat。其中,new data、tap、slope、high-g和low-g既可以使用filtered data也可以使用unfiltered data作為輸入,這分別由0x1E寄存器的int_src_data、int_src_tap、int_src_slope、int_src_high和int_src_low位決定。而orientation和flat只能使用filtered data作為輸入。

      可以通過(guò)0x19 ~ 0x1B寄存器來(lái)建立中斷類(lèi)型到中斷引腳的映射關(guān)系。例如,將0x19寄存器的int1_flag位置為1,就是建立了flat中斷到INT1中斷引腳的映射關(guān)系。

      6.7.1 new data中斷

      new data中斷提供了一個(gè)同步讀取加速度數(shù)據(jù)的服務(wù)。它在將一個(gè)z軸的新值寫(xiě)入數(shù)據(jù)寄存器時(shí)產(chǎn)生,在下一次數(shù)據(jù)獲取循環(huán)開(kāi)始的時(shí)候自動(dòng)清除。通過(guò)將0x17寄存器的data_en位置為1來(lái)使能new data中斷,中斷狀態(tài)存儲(chǔ)在0x0A的data_int位中。

      6.7.2 slope中斷

      在sensor移動(dòng)中產(chǎn)生連續(xù)的加速度信號(hào),當(dāng)一定數(shù)量的連續(xù)兩個(gè)加速度信號(hào)的值差大于一個(gè)預(yù)設(shè)的臨界值時(shí),會(huì)產(chǎn)生一個(gè)slope中斷。而在一定數(shù)量的連續(xù)兩個(gè)加速度信號(hào)的值差小于這個(gè)預(yù)設(shè)值時(shí),中斷被清除??梢酝ㄟ^(guò)0x28寄存器的slope_th位來(lái)設(shè)置這個(gè)臨界值,1 LSB slope_th對(duì)應(yīng)1 LSB的加速度數(shù)據(jù)。

      連續(xù)兩個(gè)加速度信號(hào)的取值時(shí)間差取決于所選擇的帶寬,Δt=1/(2*bw)。而取值的數(shù)量由0x27寄存器的slope_dur來(lái)決定,N = slope_dur + 1。

      通過(guò)設(shè)置0x16寄存器的slope_en_x、slope_en_y和slope_en_z為1來(lái)使能在x、y、z軸上的slope中斷。在dedicated mode喚醒狀態(tài)時(shí),三個(gè)軸的slope中斷都被使能,0x16寄存器上的這三個(gè)值無(wú)效。

      中斷狀態(tài)存儲(chǔ)在0x09的slope_int位。檢測(cè)到的slope中斷狀態(tài)信息存放在0x0B寄存器中,slope_first_x、slope_first_y、slope_first_z分別標(biāo)識(shí)了觸發(fā)中斷的軸狀態(tài),slope_sign位標(biāo)識(shí)了正負(fù)(0為正,1為負(fù))。

      6.7.3 tap中斷

      tap中斷類(lèi)似于鼠標(biāo)按鍵的click,當(dāng)至少在一個(gè)軸上的加速度slope大于一個(gè)預(yù)定義的值時(shí),該中斷產(chǎn)生。

      有兩種tap事件:single tap和double tap。single tap是在一次tap事件后,緊跟著是一段安靜時(shí)間,類(lèi)似于鼠標(biāo)的單擊;而double tap是在一段定義好的時(shí)間內(nèi),連續(xù)發(fā)生兩次tap事件,類(lèi)似于鼠標(biāo)的雙擊。

      同一時(shí)間,只能有一種tap中斷被使能。0x16寄存器的s_tap_en為1表示single tap使能,d_tap_en為1表示double tap使能。如果s_tap_en和d_tap_en同時(shí)被置為1,s_tap_en無(wú)效,只有double tap使能。

      single tap的中斷狀態(tài)存儲(chǔ)在0x09寄存器的s_tap_int位,double tap的中斷狀態(tài)存儲(chǔ)在0x09寄存器的d_tap_int位。

      通過(guò)設(shè)置0x2B寄存器的tap_th值來(lái)設(shè)置tap中斷的slope預(yù)設(shè)臨界值,在不同的range下,slope_th表示不同的數(shù)值。1 LSB的tap_th對(duì)應(yīng)于2g-range下的62.5mg slope,4g-range下的125mg slope,8g-range下的250mg slope,16g-range下的500mg slope。

      0x2A寄存器的tap_shock和tap_quiet對(duì)single tap和double tap都是有效的,tap_dur僅對(duì)double tap有效。在tap_shock的持續(xù)時(shí)間里,任何新的tap事件都會(huì)被忽略;在slope_quiet的持續(xù)時(shí)間里,不能有新的tap事件發(fā)生,否則第一次tap事件將會(huì)被取消。tap_shock為0(1)表示tap_shock的持續(xù)時(shí)間為50 ms(75 ms),tap_quiet為0(1)表示tap_quiet的持續(xù)時(shí)間為30 ms(20 ms)。tap_dur的持續(xù)時(shí)間如表2所示。

      表2 tap_dur對(duì)應(yīng)持續(xù)時(shí)間值表

      tap中斷產(chǎn)生后12.5 ms后會(huì)被自動(dòng)清除。

      0x0B 寄存器的tap_sign位標(biāo)識(shí)了觸發(fā)tap中斷的第一次tap的slope正負(fù)(0為正,1為負(fù))。觸發(fā)中斷的軸狀態(tài)分別被存放在0x0B寄存器的tap_first_x、tap_first_y和tap_first_z中。

      在低電模式(low-power mode)下,在喚醒狀態(tài)時(shí),對(duì)取樣數(shù)量有一個(gè)限制,這由0x2B寄存器的tap_samp決定。tap_samp = 00b(01b、10b、11b),表示取樣數(shù)量為2(4、8、16)。

      6.7.4 orientation中斷

      orientation表示的是sensor相對(duì)于重力域矢量g的方向變化,假設(shè)z軸與g的夾角為θ,x軸與水平方向的夾角為φ,如下圖3所示。

      圖3 sensor角度矢量圖

      假設(shè)x、y、z軸上的加速度分別為acc_x、acc_y和acc_z,則可以得到: acc_x = 1g * sinθ * cosφ acc_y =-1g * sinθ * sinφ acc_z = 1g * cosθ

      有三種不同的orientation計(jì)算模式,在這三種模式下具有不同的轉(zhuǎn)換臨界值。這三種模式分別為:對(duì)稱、高非對(duì)稱和低非對(duì)稱。這取決于0x2C寄存器的orient_mode值。orient_mode等于01b,工作在高非對(duì)稱模式;orient_mode等于10b,工作在低非對(duì)稱模式;否則,工作在對(duì)稱模式。對(duì)于每一種orienttaion模式,0x0C寄存器的orient表示不同的意思。三種模式下,orient的意思分別如表

      3、表

      4、表5所示。

      圖3 對(duì)稱模式下的0x0C寄存器orient意思示表

      圖4 高非對(duì)稱模式下的0x0C寄存器orient意思示表

      圖5 低非對(duì)稱模式下的0x0C寄存器orient意思示表

      在以上三張表中,‘hyst’ 表示一個(gè)延遲,這個(gè)值通過(guò)0x0C寄存器的orient_hyst設(shè)置。1 LSB的orient_hyst對(duì)應(yīng)于62.5 mg。

      通過(guò)將0x16寄存器的orient_en位置為1來(lái)使能orientation中斷。當(dāng)0x0C寄存器的orient發(fā)生變化時(shí),中斷產(chǎn)生,一段之間后自動(dòng)清除。中斷狀態(tài)存儲(chǔ)在0x09寄存器的orient_int位。

      0x0C寄存器的orient位發(fā)生變化后,中斷的產(chǎn)生可能會(huì)被阻斷,這可以通過(guò)0x2C寄存器的orient_blocking進(jìn)行設(shè)置。

      orient_blocking = 00b表示沒(méi)有阻斷; orient_blocking = 01b表示θ阻斷;

      orient_blocking = 10b表示θ阻斷,或任一軸上的加速度slope > 0.2 g;

      orient_blocking = 11b表示θ阻斷,或任一軸上的加速度slope > 0.4 g,或orient值超過(guò)100 ms一直不穩(wěn)定。

      θ阻斷通過(guò)下面的不等式定義:

      參數(shù)blocking_theta由0x2D寄存器的orient_theta決定,由此可知阻斷角度θ的取值范圍為0° ~ 44.8°。

      6.7.5 flat中斷

      flat中斷,顧名思義,用于檢測(cè)sensor是否位于水平狀態(tài),判斷設(shè)備位于水平狀態(tài)的條件時(shí):

      參數(shù)parameter_theta由0x2E寄存器的flat_theta決定,由此可知,flat角度可能取值范圍也是0° ~ 44.8°。

      通過(guò)將0x16寄存器的flat_en置為1使能flat中斷。當(dāng)0x0C寄存器的flat值發(fā)生變化,并且這個(gè)值保持穩(wěn)定一段時(shí)間后,flat中斷產(chǎn)生。保持穩(wěn)定的時(shí)間的最小值由0x2F寄存器的flat_hold_time決定。flat_hold_time等于00b、01b、10b、11b分別表示0、512 ms、1024 ms、2048 ms。這個(gè)中斷在一段之間后自動(dòng)清除。flat中斷狀態(tài)存儲(chǔ)在0x09寄存器的flat_int位。

      6.7.6 low-g中斷

      這個(gè)中斷是基于比較加速度數(shù)據(jù)和low-g臨界值而產(chǎn)生的,比如對(duì)自由落體的偵測(cè)。通過(guò)設(shè)置0x17寄存器的low_en位使能該中斷。low-g中斷有兩種模式:single mode和sum mode。single mode是只比較某一個(gè)軸的加速度,而sum mode是比較三個(gè)軸加速度的絕對(duì)值總和。這由0x24寄存器的low_mode位決定,0表示single mode,1表示sum mode。

      low-g臨界值通過(guò)0x23寄存器的low_th設(shè)置,1 LSB low_th對(duì)應(yīng)于7.81 mg的加速度??梢酝ㄟ^(guò)設(shè)置0x24寄存器的low_hy來(lái)設(shè)置滯后值,1 LSB low_hy對(duì)應(yīng)于125 mg的加速度值。

      當(dāng)某一軸上的加速度絕對(duì)值(single mode)或三軸加速度絕對(duì)值的總和(sum mode)小于臨界值超過(guò)一段時(shí)間(這個(gè)時(shí)間由0x22寄存器的low_dur決定)后,中斷產(chǎn)生;當(dāng)某一軸上的加速度絕對(duì)值(single mode)或三軸加速度絕對(duì)值的總和(sum mode)大于臨界值減去滯后值至少超過(guò)一個(gè)數(shù)據(jù)的獲取時(shí)間后,中斷被重置。

      low-g中斷產(chǎn)生前的延遲時(shí)間與low_dur的關(guān)系為:delay [ms] = [(0x22)low_dur + 1] * 2 ms。所以,延遲時(shí)間的可能范圍為2 到512 ms。

      6.7.7 high-g中斷

      這個(gè)中斷是基于比較加速度數(shù)據(jù)和high-g臨界值而產(chǎn)生的,主要用于對(duì)震動(dòng)或其他的一些高加速度事件的偵測(cè)。

      通過(guò)設(shè)置0x17寄存器的hign_en_x、high_en_y和high_en_z使能sensor在x、y和z軸上的high-g終端。

      high-g臨界值通過(guò)0x26寄存器的high_th設(shè)置,1 LSB high_th對(duì)應(yīng)于2g-range下的7.81mg,4g-range下的15.63mg,8g-range下的31.25mg,16g-range下的62.5mg??梢酝ㄟ^(guò)設(shè)置0x24寄存器的high_hy來(lái)設(shè)置滯后值,1 LSB high_hy對(duì)應(yīng)于2g-range下的125mg,4g-range下的250mg,8g-range下的500mg,16g-range下的1000mg。

      當(dāng)至少一個(gè)使能軸的加速度絕對(duì)值高于high-g臨界值超過(guò)一段時(shí)間(這個(gè)時(shí)間由0x25寄存器的high_dur決定)后,中斷產(chǎn)生。當(dāng)所有使能軸的加速度絕對(duì)值都低于high-g臨界值減去滯后值一段時(shí)間(由0x25寄存器的high_dur決定)后,中斷被重置。

      high-g中斷產(chǎn)生前的延遲時(shí)間與high_dur的關(guān)系為:delay [ms] = [(0x22)high_dur + 1] * 2 ms。所以,延遲時(shí)間的可能范圍為2 到512 ms。

      7.sensor驅(qū)動(dòng)開(kāi)發(fā)步驟 綜上所述,sensor驅(qū)動(dòng)開(kāi)發(fā)可以歸納為以下步驟來(lái)完成: 1.read && verify spec,確認(rèn)chip功能以及register配置;

      2.按照spec所述,在code中加入主要的配置數(shù)據(jù),如電源模式、主要寄存器的配置、range支持、bandwidth支持、中斷配置等; 3.設(shè)計(jì)主要的數(shù)據(jù)結(jié)構(gòu);

      4.實(shí)現(xiàn)sensor數(shù)據(jù)的設(shè)置和獲取接口;

      5.通過(guò)module_init和module_exit接口加入driver層入口和出口函數(shù)函數(shù);

      6.定義i2c_driver,設(shè)置driver的probe和remove函數(shù)入口,通過(guò)i2c_add_driver和i2c_del_driver接口添加/移除driver; 7.實(shí)現(xiàn)driver的probe函數(shù)功能,函數(shù)中實(shí)現(xiàn)sensor的硬件配置,并通過(guò)linux的input子系統(tǒng)實(shí)現(xiàn)sensor數(shù)據(jù)的上報(bào);

      8.實(shí)現(xiàn)driver的remove函數(shù)功能,函數(shù)中實(shí)現(xiàn)設(shè)備的移除、資源的釋放等。

      9.HAL層中注冊(cè)hw_module_t結(jié)構(gòu)體,將結(jié)構(gòu)體名稱命名為HAL_MODULE_INFO_SYM;

      10.判斷sensor設(shè)備文件是否存在,通過(guò)open_input_device訪問(wèn)設(shè)備文件,并注冊(cè)設(shè)備文件的poll、activate、close等函數(shù); 11.實(shí)現(xiàn)sensor list的獲取函數(shù);

      12.實(shí)現(xiàn)對(duì)設(shè)備文件的主要操作接口,完成上層與硬件設(shè)備的通信; 13.調(diào)試sensor功能。附錄 bma250寄存器表

      第三篇:創(chuàng)新驅(qū)動(dòng)發(fā)展戰(zhàn)略學(xué)習(xí)心得范文

      精品學(xué)習(xí)資料范文

      創(chuàng)新驅(qū)動(dòng)發(fā)展戰(zhàn)略學(xué)習(xí)心得

      創(chuàng)新驅(qū)動(dòng)發(fā)展戰(zhàn)略學(xué)習(xí)心得

      通過(guò)將近一個(gè)月的課程學(xué)習(xí),我獲益匪淺,對(duì)“創(chuàng)新”有了新的理解和認(rèn)識(shí)。創(chuàng)新是一種探索未知事物、尋找科學(xué)真理的活動(dòng),意味著新的嘗試,走新的道路。創(chuàng)新是引領(lǐng)發(fā)展的第一動(dòng)力,必須擺在國(guó)家發(fā)展全局的核心位置,深入實(shí)施創(chuàng)新驅(qū)動(dòng)發(fā)展戰(zhàn)略。作為黨員領(lǐng)導(dǎo)干部,更應(yīng)該樹(shù)立創(chuàng)新意識(shí),自覺(jué)運(yùn)用創(chuàng)新思維方式和方法謀劃自身工作。

      一、要樹(shù)立創(chuàng)新的勇氣

      中國(guó)的改革航船已經(jīng)駛?cè)牍?jiān)克難的深水區(qū)。只有創(chuàng)新思維,沖破思想觀念的束縛,突破利益固化的藩籬,攻克體制機(jī)制上的頑癥痼疾,才能進(jìn)一步發(fā)展社會(huì)生產(chǎn)力和增強(qiáng)社會(huì)活力。創(chuàng)新,需要敢于冒險(xiǎn)的勇氣和魄力。中國(guó)改革創(chuàng)新,束縛怎么沖破? 藩籬如何突破? 頑癥痼疾又怎樣攻克? 倘若沒(méi)有一往無(wú)前的勇氣,沒(méi)有壯士斷腕的決心,沒(méi)有背水一戰(zhàn)的氣概,沒(méi)有迎難而上的擔(dān)當(dāng),這艘改革航船將注定無(wú)法抵達(dá)勝利的彼岸。我們要拿出逢山開(kāi)路的闖勁兒,拿出甩開(kāi)膀子的干勁兒,拿出抓鐵有痕的韌勁兒,拿出眾人拾柴的心勁兒,拿出

      精品學(xué)習(xí)資料范文

      勇毅篤行的穩(wěn)勁兒,用今天的改革為明天的遠(yuǎn)行鋪路搭橋。

      二、要講究創(chuàng)新的方法

      實(shí)現(xiàn)創(chuàng)新,需要具備追求卓越的意識(shí)、開(kāi)拓創(chuàng)先的精神和獨(dú)具卓識(shí)的方法。要學(xué)會(huì)掌握和運(yùn)用逆向思維、發(fā)散思維和聯(lián)想思維等方法,克服思維的單一性、孤立性,善于多角度、多層次、全方位地解決、學(xué)習(xí)實(shí)踐中的各種問(wèn)題,力爭(zhēng)達(dá)到獨(dú)創(chuàng)性、系統(tǒng)性?!皠?chuàng)新是民族進(jìn)步的靈魂,創(chuàng)新是國(guó)家興旺發(fā)達(dá)不竭的動(dòng)力”創(chuàng)新就在于創(chuàng)造,創(chuàng)造就在于人腦的訓(xùn)練。創(chuàng)新思維是發(fā)散思維和集中思維的結(jié)合,發(fā)散思維是構(gòu)成創(chuàng)造性思維的主導(dǎo)成分。發(fā)散思維是在思維過(guò)程中通過(guò)重組所給的和記憶中的信息,得到眾多可能的答案、設(shè)想或解決方案。它的特點(diǎn)為是以一個(gè)問(wèn)題為中心,充分發(fā)揮人的聯(lián)想力和想象力,突破原有的知識(shí)圈,從一點(diǎn)向四面八方想開(kāi)去,從各個(gè)不同的角度或側(cè)面進(jìn)行思考,讓思維多向流動(dòng),以便獲得解決問(wèn)題的全部可能。這種思考無(wú)一定方向、無(wú)一定范圍、不墨守成規(guī)、不拘于傳統(tǒng)方法,可以標(biāo)新立異、異想天開(kāi),從已知的領(lǐng)域去探求未知的境界。所以,發(fā)散思維是一種創(chuàng)新思維方法,集中體現(xiàn)了創(chuàng)造性思維的本質(zhì)牲特征。我們要有意識(shí)的訓(xùn)練運(yùn)用這些思維方式和方法,創(chuàng)造性的開(kāi)展自身的工作。

      精品學(xué)習(xí)資料范文

      三、要在實(shí)踐中創(chuàng)新

      創(chuàng)新思維來(lái)自于實(shí)踐,服務(wù)于實(shí)踐。要把創(chuàng)新思維和社會(huì)實(shí)踐結(jié)合起來(lái),在實(shí)踐中統(tǒng)籌兼顧,用整體、全面的觀點(diǎn)和方法處理和解決發(fā)展中的各種復(fù)雜性問(wèn)題。日常學(xué)習(xí)和生活中,在一個(gè)有限的范圍內(nèi),人們接觸了一定的類(lèi)似的概念后,會(huì)習(xí)慣性地形成一種思維定勢(shì),會(huì)“想當(dāng)然”地認(rèn)為事情就是大多數(shù)認(rèn)為的那樣,容易陷入“知其然而不知其所以然”的怪圈,不能看到事物的本來(lái)面目,在這樣的狀態(tài)下難以創(chuàng)新。因此,在各種實(shí)踐探索過(guò)程中,要勇于拆掉習(xí)慣性思維的墻,打破所有束縛頭腦的條條框框,要允許自己異想天開(kāi),主動(dòng)丟棄從眾心理和從眾思維習(xí)慣,“不走尋常路”,不讓自己被表象迷惑,增強(qiáng)洞察事物本質(zhì)的能力,從根源上找到解決問(wèn)題的新構(gòu)思、新思想。實(shí)踐,是創(chuàng)新思維的源頭活水,實(shí)踐中發(fā)現(xiàn)和產(chǎn)生的需求,是創(chuàng)新活動(dòng)不竭的動(dòng)力。因此,要積極投身和參與實(shí)踐中,在實(shí)踐中收獲“觀念更新、思維新穎、方法先進(jìn)”的成果。

      四、要加強(qiáng)知識(shí)的積累

      要勤于學(xué)習(xí)各種知識(shí),不斷開(kāi)闊視野。知識(shí)和經(jīng)驗(yàn)是創(chuàng)新思維的基礎(chǔ)。有豐富的閱歷,廣博的知識(shí),就有足夠的閃光點(diǎn)用來(lái)進(jìn)行

      精品學(xué)習(xí)資料范文

      “想象”、“整合”和“類(lèi)比”。閱歷和知識(shí)越多樣化,頭腦中能夠產(chǎn)生的關(guān)聯(lián)就會(huì)越多。因此,要培養(yǎng)自己對(duì)各類(lèi)事物的觀察、學(xué)習(xí)興趣,主動(dòng)參與各種理論和實(shí)踐活動(dòng),力爭(zhēng)對(duì)各個(gè)行業(yè)、各種事物都有所了解。同時(shí),要養(yǎng)成善于學(xué)習(xí)和思考的習(xí)慣,能將各個(gè)不同領(lǐng)域內(nèi)看似毫無(wú)內(nèi)在關(guān)聯(lián)的問(wèn)題、想法、事物成功地聯(lián)系在一起,找出所有事物共同點(diǎn)、共通點(diǎn),為“整合”、“創(chuàng)造”打好扎實(shí)的基礎(chǔ)。最后,要錘煉堅(jiān)持不懈的品格。創(chuàng)新的道路上,沒(méi)有平坦的大道可走,挫折和失敗在所難免。不僅需要超常的智力,更需要非凡的勇氣和精神支撐。面對(duì)創(chuàng)新過(guò)程中可能遇到的各種困難,要努力克服畏難情緒和懶惰習(xí)氣,把追求創(chuàng)新、努力創(chuàng)新作為學(xué)習(xí)、工作的要求和標(biāo)準(zhǔn)。注重錘煉自信、堅(jiān)毅、獨(dú)創(chuàng)、不迷信權(quán)威等品格,用鍥而不舍、百折不撓的精神,不達(dá)目的不罷休的韌勁,義無(wú)反顧地去思、去闖。只有善于創(chuàng)新、勇于實(shí)踐,把創(chuàng)新看成自己生命中的一部分,努力讓世界變得更加美好,在創(chuàng)新的世界中收獲屬于自己的成功。

      五、要注重人才隊(duì)伍的創(chuàng)新要相信“時(shí)勢(shì)造英雄”,要充分認(rèn)識(shí)到國(guó)家的人口基數(shù)大,高效人才的流動(dòng)。要鼓勵(lì)科研人員創(chuàng)業(yè)創(chuàng)新。大力弘揚(yáng)創(chuàng)新文化,厚植創(chuàng)新沃土,營(yíng)造敢為人先、寬容失敗的良好氛圍,充分激發(fā)企業(yè)家精神,調(diào)動(dòng)全社會(huì)創(chuàng)業(yè)創(chuàng)新積極性,匯聚成推動(dòng)發(fā)展的磅礴力量。

      精品學(xué)習(xí)資料范文

      對(duì)于商貿(mào)工作而言,我認(rèn)為“創(chuàng)新”所帶來(lái)的影響將會(huì)更深遠(yuǎn),其作用不可替代。

      一、創(chuàng)新產(chǎn)業(yè)規(guī)?;徒M織化建設(shè),提升流通水平和層次。商貿(mào)流通企業(yè)規(guī)模小、流通水平低嚴(yán)重阻礙了商貿(mào)流通業(yè)的發(fā)展。一方面可以加大商貿(mào)流通企業(yè)的并購(gòu)力度,鼓勵(lì)企業(yè)以參股、控股、兼并、重組等方式實(shí)現(xiàn)更大范圍的整合,形成更大的連鎖型企業(yè),優(yōu)

      第四篇:S3C2410 LCD驅(qū)動(dòng)學(xué)習(xí)心得-4

      3.BMP和JPEG圖形顯示程序

      3.1 在LCD上顯示BMP或JPEG圖片的主流程圖

      首先,在程序開(kāi)始前。要在nfs/dev目錄下創(chuàng)建LCD的設(shè)備結(jié)點(diǎn),設(shè)備名fb0,設(shè)備類(lèi)型為字符設(shè)備,主設(shè)備號(hào)為29,次設(shè)備號(hào)為0。命令如下: mknod fb0 c 29 0 在LCD上顯示圖象的主流程圖如圖3.1所示。程序一開(kāi)始要調(diào)用open函數(shù)打開(kāi)設(shè)備,然后調(diào)用ioctl獲取設(shè)備相關(guān)信息,接下來(lái)就是讀取圖形文件數(shù)據(jù),把圖象的RGB值映射到顯存中,這部分是圖象顯示的核心。對(duì)于JPEG格式的圖片,要先經(jīng)過(guò)JPEG解碼才能得到RGB數(shù)據(jù),本項(xiàng)目中直接才用現(xiàn)成的JPEG庫(kù)進(jìn)行解碼。對(duì)于bmp格式的圖片,則可以直接從文件里面提取其RGB數(shù)據(jù)。要從一個(gè)bmp文件里面把圖片數(shù)據(jù)陣列提取出來(lái),首先必須知道bmp文件的格式。下面來(lái)詳細(xì)介紹bmp文件的格式。

      圖3.1

      3.2 bmp位圖格式分析

      位圖文件可看成由四個(gè)部分組成:位圖文件頭、位圖信息頭、彩色表和定義位圖的字節(jié)陣列。如圖3.2所示。

      圖3.2 文件頭中各個(gè)段的地址及其內(nèi)容如圖3.3。

      圖3.3 位圖文件頭數(shù)據(jù)結(jié)構(gòu)包含BMP圖象文件的類(lèi)型,顯示內(nèi)容等信息。它的數(shù)據(jù)結(jié)構(gòu)如下定義: Typedef struct {

      int bfType;//表明位圖文件的類(lèi)型,必須為BM long bfSize;//表明位圖文件的大小,以字節(jié)為單位 int bfReserved1;//屬于保留字,必須為本0 int bfReserved2;//也是保留字,必須為本0 long bfOffBits;//位圖陣列的起始位置,以字節(jié)為單位 } BITMAPFILEHEADER;

      圖3.4 位圖文件頭的數(shù)據(jù)結(jié)構(gòu)

      (2)信息頭中各個(gè)段的地址及其內(nèi)容如圖3.5所示。

      圖3.5 位圖信息頭的數(shù)據(jù)結(jié)構(gòu)包含了有關(guān)BMP圖象的寬,高,壓縮方法等信息,它的C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)如圖3.6所示。Typedef struct { long biSize; //指出本數(shù)據(jù)結(jié)構(gòu)所需要的字節(jié)數(shù)

      long biWidth;//以象素為單位,給出BMP圖象的寬度 long biHeight;//以象素為單位,給出BMP圖象的高度 int

      biPlanes;//輸出設(shè)備的位平面數(shù),必須置為1 int

      biBitCount;//給出每個(gè)象素的位數(shù) long biCompress;//給出位圖的壓縮類(lèi)型 long biSizeImage;//給出圖象字節(jié)數(shù)的多少 long biXPelsPerMeter;//圖像的水平分辨率 long biYPelsPerMeter;//圖象的垂直分辨率

      long biClrUsed;//調(diào)色板中圖象實(shí)際使用的顏色素?cái)?shù) long biClrImportant;//給出重要顏色的索引值 } BITMAPINFOHEADER;

      圖3.6 BITMAPINFOHEADER數(shù)據(jù)結(jié)構(gòu)

      (3)對(duì)于象素小于或等于16位的圖片,都有一個(gè)顏色表用來(lái)給圖象數(shù)據(jù)陣列提供顏色索引,其中的每塊數(shù)據(jù)都以B、G、R的順序排列,還有一個(gè)是reserved保留位。而在圖形數(shù)據(jù)區(qū)域存放的是各個(gè)象素點(diǎn)的索引值。它的C語(yǔ)言結(jié)構(gòu)如圖3.7所示。

      圖3.7 顏色表數(shù)據(jù)結(jié)構(gòu)(4)對(duì)于24位和32位的圖片,沒(méi)有彩色表,他在圖象數(shù)據(jù)區(qū)里直接存放圖片的RGB數(shù)據(jù),其中的每個(gè)象素點(diǎn)的數(shù)據(jù)都以B、G、R的順序排列。每個(gè)象素點(diǎn)的數(shù)據(jù)結(jié)構(gòu)如圖3.8所示。

      圖3.8 圖象數(shù)據(jù)陣列的數(shù)據(jù)結(jié)構(gòu)(5)由于圖象數(shù)據(jù)陣列中的數(shù)據(jù)是從圖片的最后一行開(kāi)始往上存放的,因此在顯示圖象時(shí),是從圖象的左下角開(kāi)始逐行掃描圖象,即從左到右,從下到上。

      (6)對(duì)S3C2410或PXA255開(kāi)發(fā)板上的LCD來(lái)說(shuō),他們每個(gè)象素點(diǎn)所占的位數(shù)為16位,這16位按B:G:R=5:6:5的方式分,其中B在最高位,R在最低位。而從bmp圖象得到的R、G、B數(shù)據(jù)則每個(gè)數(shù)據(jù)占8位,合起來(lái)一共24位,因此需要對(duì)該R、G、B數(shù)據(jù)進(jìn)行移位組合成一個(gè)16位的數(shù)據(jù)。移位方法如下: b >>= 3;g >>= 2;r >>= 3;RGBValue =(r<<11 | g << 5 | b);基于以上分析,提取各種類(lèi)型的bmp圖象的流程如圖3.9所示

      圖 3.9

      本篇文章來(lái)源于 Linux公社網(wǎng)站(本篇文章來(lái)源于 Linux公社網(wǎng)站(

      第五篇:S3C2410 LCD驅(qū)動(dòng)學(xué)習(xí)心得-6

      實(shí)驗(yàn)過(guò)程與結(jié)果 1.Linux 源代碼的修改

      首先修改arch/arm/mach-smdk2410.c文件,加入以下代碼。static struct s3c2410fb_mach_info smdk2440_lcd_cfg __initdata = {.regs = {

      .lcdcon1 = S3C2410_LCDCON1_TFT16BPP |

      S3C2410_LCDCON1_TFT |

      S3C2410_LCDCON1_CLKVAL(7),.lcdcon2 = S3C2410_LCDCON2_VBPD(4)|

      S3C2410_LCDCON2_LINEVAL(319)|

      S3C2410_LCDCON2_VFPD(1)|

      S3C2410_LCDCON2_VSPW(1),.lcdcon3 = S3C2410_LCDCON3_HBPD(26)|

      S3C2410_LCDCON3_HOZVAL(239)|

      S3C2410_LCDCON3_HFPD(30),.lcdcon4 = S3C2410_LCDCON4_HSPW(13)|

      S3C2410_LCDCON4_MVAL(13),.lcdcon5 = S3C2410_LCDCON5_FRM565 |

      S3C2410_LCDCON5_INVVLINE |

      S3C2410_LCDCON5_INVVFRAME |

      S3C2410_LCDCON5_PWREN |

      S3C2410_LCDCON5_HWSWP, },.lpcsel =((0xCE6)& ~7)| 1<<4,.width = 240,.height = 320,.xres = {

      .min = 240,.max = 240,.defval = 240,},.yres = {

      .min = 320,.max = 320,.defval = 320,},.bpp = {

      .min = 16,.max = 16,.defval = 16,}, };在函數(shù)smdk2410_machine_init()函數(shù)中加入LCD的初始化代碼,見(jiàn)下 static void __init smdk2410_machine_init(void){ s3c24xx_fb_set_platdata(&smdk2440_lcd_cfg);smdk_machine_init();} 2.編譯內(nèi)核,產(chǎn)生zImage文件,放入tftp目錄下。

      3.在nfs的dev目錄下建立FrameBuffer的設(shè)備節(jié)點(diǎn),使用命令:

      mknod fb0 c 29 0 4.啟動(dòng)開(kāi)發(fā)板,加載內(nèi)核和文件系統(tǒng)。5.編寫(xiě)LCD的應(yīng)用程序,程序見(jiàn)附錄。

      6.采用arm-linux-gcc 編譯應(yīng)用程序,產(chǎn)生可執(zhí)行文件,放入nfs目錄中。7.在開(kāi)發(fā)板上運(yùn)行編譯好的可執(zhí)行文件,便可。

      8.下圖是BMP位圖顯示程序,在S3C2410上的運(yùn)行結(jié)果。

      實(shí)驗(yàn)心得體會(huì)

      1. LCD驅(qū)動(dòng)的主要問(wèn)題是沒(méi)有LCD屏的文檔,我們找不到它的那些參數(shù)值,后來(lái)只能參照Linux源碼里面的其他LCD屏的參數(shù)進(jìn)行實(shí)驗(yàn)。

      2. 在驅(qū)動(dòng)差錯(cuò)的過(guò)程中,我們采用跟蹤打印的方法進(jìn)行調(diào)試。剛開(kāi)始的時(shí)候,內(nèi)核打印出一行找不到LCD設(shè)備。我們定位到輸出這行提示的代碼處,進(jìn)行反向跟蹤。發(fā)現(xiàn)傳給函數(shù)的設(shè)備指針為空,于是往上排查,終于發(fā)現(xiàn)源代碼中沒(méi)有定義LCD的設(shè)備信息。于是驅(qū)動(dòng)問(wèn)題也就順利解決了。

      3. 原來(lái)一直以為,只要LCD驅(qū)動(dòng)工作正常了,內(nèi)核起來(lái)的時(shí)候,液晶屏?xí)@示出Logo。當(dāng)時(shí)搞了很久一直沒(méi)有,還以為是驅(qū)動(dòng)的問(wèn)題。后來(lái)隨便寫(xiě)了一個(gè)LCD應(yīng)用程序,竟然能用。4. 在調(diào)試過(guò)程應(yīng)用程序中發(fā)現(xiàn),在讀取文件頭的時(shí)候,如果直接定義一個(gè)bitmapfileheader為它動(dòng)態(tài)分配內(nèi)存:

      *bmph=(bitmapfileheader*)malloc(sizeof(bitmapfileheader));然后用fread((char*)bmph,sizeof(bitmapfileheader),1,f)把文件頭一次性讀出來(lái),讀出來(lái)的文件頭是錯(cuò)誤的,經(jīng)過(guò)調(diào)試發(fā)現(xiàn)原因是bitmapfileheader這個(gè)結(jié)構(gòu)體中的type屬性原本應(yīng)該占2字節(jié),但是被編譯器在分配內(nèi)存的時(shí)候進(jìn)行了內(nèi)存對(duì)齊的優(yōu)化,給他分配了4個(gè)字節(jié)的空間,造成讀文件的錯(cuò)誤。因此在編程中要特別注意內(nèi)存對(duì)齊的影響。typedef struct { WORD

      type;(被優(yōu)化)DWORD bfsize;DWORD reserved;DWORD offbits;} bitmapfileheader;5. 在嵌入式應(yīng)用程序的移植過(guò)程中,我們?cè)瓉?lái)認(rèn)為ARM和PC機(jī)大小尾順序是不同的,因此在應(yīng)用程序中,也對(duì)這個(gè)差別進(jìn)行了處理。當(dāng)時(shí),在調(diào)試過(guò)程中發(fā)現(xiàn),PC機(jī)程序可以直接移植到ARM上,不需要任何改動(dòng)。但是我們的程序,的確存在會(huì)產(chǎn)生大小尾問(wèn)題代碼(在使用fread()讀入時(shí))。這究竟是為什么?有人說(shuō),ARM是可以設(shè)置大小尾順序的。后來(lái)這個(gè)問(wèn)題也沒(méi)有深究下去。

      參考文獻(xiàn)

      (1)嵌入式系統(tǒng)設(shè)計(jì)與應(yīng)用開(kāi)發(fā):鄭靈翔.北京:北京航天航空大學(xué)出版社 2006

      本篇文章來(lái)源于 Linux公社網(wǎng)站(

      下載S3c2410 LCD驅(qū)動(dòng)學(xué)習(xí)心得[五篇]word格式文檔
      下載S3c2410 LCD驅(qū)動(dòng)學(xué)習(xí)心得[五篇].doc
      將本文檔下載到自己電腦,方便修改和收藏,請(qǐng)勿使用迅雷等下載。
      點(diǎn)此處下載文檔

      文檔為doc格式


      聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻(xiàn)自行上傳,本網(wǎng)站不擁有所有權(quán),未作人工編輯處理,也不承擔(dān)相關(guān)法律責(zé)任。如果您發(fā)現(xiàn)有涉嫌版權(quán)的內(nèi)容,歡迎發(fā)送郵件至:645879355@qq.com 進(jìn)行舉報(bào),并提供相關(guān)證據(jù),工作人員會(huì)在5個(gè)工作日內(nèi)聯(lián)系你,一經(jīng)查實(shí),本站將立刻刪除涉嫌侵權(quán)內(nèi)容。

      相關(guān)范文推薦

        “解放思想、改革開(kāi)放、創(chuàng)新驅(qū)動(dòng)、科學(xué)發(fā)展”學(xué)習(xí)心得

        “解放思想、改革開(kāi)放、創(chuàng)新驅(qū)動(dòng)、科學(xué)發(fā)展” 大討論活動(dòng)心得體會(huì) 上尤各莊小學(xué)---張曉君 接縣教育局的“解放思想、改革開(kāi)放、創(chuàng)新驅(qū)動(dòng)、科學(xué)發(fā)展”大討論活動(dòng)的通知,我校全......

        《創(chuàng)新驅(qū)動(dòng)與供給側(cè)改革》學(xué)習(xí)心得[大全五篇]

        《創(chuàng)新驅(qū)動(dòng)與供給側(cè)改革》學(xué)習(xí)心得 3月30日下午,在縣委中心組(擴(kuò)大)理論學(xué)習(xí)會(huì)上,有幸聆聽(tīng)了中國(guó)人民大學(xué)世界經(jīng)濟(jì)研究中心主任黃衛(wèi)平教授所作題為《創(chuàng)新驅(qū)動(dòng)與供給側(cè)改革》的專(zhuān)......

        解放思想改革開(kāi)放創(chuàng)新驅(qū)動(dòng)科學(xué)發(fā)展大討論活動(dòng)學(xué)習(xí)心得[精選]

        解放思想改革開(kāi)放創(chuàng)新驅(qū)動(dòng)科學(xué)發(fā)展大討論活動(dòng)學(xué)習(xí)心得 開(kāi)展解放思想改革開(kāi)放創(chuàng)新驅(qū)動(dòng)科學(xué)發(fā)展大討論活動(dòng),就是要提高工作的服務(wù)質(zhì)量,為科學(xué)決策服務(wù)。要以開(kāi)展解放思想改革開(kāi)......

        創(chuàng)新驅(qū)動(dòng)

        創(chuàng)新驅(qū)動(dòng)為院校發(fā)展注入無(wú)限活力 ——理工大學(xué) 市東醫(yī)院“理工醫(yī)創(chuàng)新基地”建設(shè)一周年回顧 2010年早春,市東醫(yī)院 上海理工大學(xué)、市東醫(yī)院“理工醫(yī)創(chuàng)新基地” 簽約暨揭牌儀式......

        創(chuàng)新驅(qū)動(dòng)發(fā)展

        創(chuàng)新驅(qū)動(dòng)發(fā)展 黨的十八大明確提出“科技創(chuàng)新是提高社會(huì)生產(chǎn)力和綜合國(guó)力的戰(zhàn)略支撐,必須擺在國(guó)家發(fā)展全局的核心位置?!睆?qiáng)調(diào)要堅(jiān)持走中國(guó)特色自主創(chuàng)新道路、實(shí)施創(chuàng)新驅(qū)動(dòng)發(fā)......

        創(chuàng)新驅(qū)動(dòng)發(fā)展

        創(chuàng)新驅(qū)動(dòng)發(fā)展 十八大、“兩會(huì)”相關(guān)論述 材料一:科技創(chuàng)新驅(qū)動(dòng)發(fā)展戰(zhàn)略黨的十八報(bào)告強(qiáng)調(diào),實(shí)施創(chuàng)新驅(qū)動(dòng)發(fā)展戰(zhàn)略。科技創(chuàng)新是提高 社會(huì)生產(chǎn)力和綜合國(guó)力的戰(zhàn)略支撐,必須擺在國(guó)家......

        創(chuàng)新驅(qū)動(dòng)科學(xué)發(fā)展

        創(chuàng)新驅(qū)動(dòng)科學(xué)發(fā)展 破除事業(yè)發(fā)展瓶頸開(kāi)創(chuàng)廣電工作新局面 ——縣廣電臺(tái)2016年上半年工作總結(jié)及下半年工作謀劃 上半年,縣廣播電視臺(tái)在縣委、縣政府正確領(lǐng)導(dǎo)下,緊緊圍繞縣委、......

        任務(wù)驅(qū)動(dòng)教學(xué)法

        一、“任務(wù)驅(qū)動(dòng)”式教學(xué)的含義 “任務(wù)驅(qū)動(dòng)”式教學(xué)是將整個(gè)知識(shí)體系分解為一個(gè)一個(gè)相對(duì)獨(dú)立而相互關(guān)聯(lián)的“任務(wù)”,讓學(xué)生在一個(gè)個(gè)典型“任務(wù)”的驅(qū)動(dòng)下有序展開(kāi)學(xué)習(xí)活動(dòng),引導(dǎo)......