久久99精品久久久久久琪琪,久久人人爽人人爽人人片亞洲,熟妇人妻无码中文字幕,亚洲精品无码久久久久久久

S3c2410 LCD驅動學習心得[五篇]

時間:2019-05-12 07:55:03下載本文作者:會員上傳
簡介:寫寫幫文庫小編為你整理了多篇相關的《S3c2410 LCD驅動學習心得》,但愿對你工作學習有幫助,當然你在寫寫幫文庫還可以找到更多《S3c2410 LCD驅動學習心得》。

第一篇:S3c2410 LCD驅動學習心得

S3c2410 LCD驅動學習心得

一 實驗內容簡要描述 1.實驗目的

學會驅動程序的編寫方法,配置S3C2410的LCD驅動,以及在LCD屏上顯示包括bmp和jpeg兩種格式的圖片 2.實驗內容

(1)分析S3c2410實驗箱LCD以及LCD控制器的硬件原理,據此找出相應的硬件設置參數,參考xcale實驗箱關于lcd的設置,完成s3c2410實驗箱LCD的設置

(2)在LCD上顯示一張BMP圖片或JPEG圖片 3.實驗條件(軟硬件環境)

PC機、S3C2410開發板、PXA255開發板 二 實驗原理

1.S3C2410內置LCD控制器分析 1.1 S3C2410 LCD控制器

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

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

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

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

支持單色、4級灰度、256色的調色板顯示模式 支持64K和16M色非調色板顯示模式

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

VSYNC(VFRAME):幀同步信號 HSYNC(VLINE):行同步信號 VCLK :像數時鐘信號

VDEN(VM):數據有效標志信號

由于本項目所用的S3C2410上的LCD是TFT屏,并且TFT屏將是今后應用的主流,因此接下來,重點圍繞TFT屏的控制來進行。

圖1.1是S3C2410內部的LCD控制器的邏輯示意圖:

圖1.1 REGBANK 是LCD控制器的寄存器組,用來對LCD控制器的各項參數進行設置。而 LCDCDMA 則是LCD控制器專用的DMA信道,負責將視頻資料從系統總線(System Bus)上取來,通過 VIDPRCS 從VD[23:0]發送給LCD屏。同時 TIMEGEN 和 LPC3600 負責產生 LCD屏所需要的控制時序,例如VSYNC、HSYNC、VCLK、VDEN,然后從 VIDEO MUX 送給LCD屏。

1.2 TFT屏時序分析

圖1.2是TFT屏的典型時序。其中VSYNC是幀同步信號,VSYNC每發出1個脈沖,都意味著新的1屏視頻資料開始發送。而HSYNC為行同步信號,每個HSYNC脈沖都表明新的1行視頻資料開始發送。而VDEN則用來標明視頻資料的有效,VCLK是用來鎖存視頻資料的像數時鐘。

并且在幀同步以及行同步的頭尾都必須留有回掃時間,例如對于VSYNC來說前回掃時間就是(VSPW+1)+(VBPD+1),后回掃時間就是(VFPD +1);HSYNC亦類同。這樣的時序要求是當初CRT顯示器由于電子槍偏轉需要時間,但后來成了實際上的工業標準,乃至于后來出現的TFT屏為了在時序上于CRT兼容,也采用了這樣的控制時序。

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

圖1.3 通過對比圖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 以上各參數,除了LINVAL和HOZVAL直接和屏的分辯率有關,其它的參數在實際操作過程中應以上面的為參考,不應偏差太多。

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

圖1.4 LINECNT :當前行掃描計數器值,標明當前掃描到了多少行。

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

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

圖1.5 VBPD,LINEVAL,VFPD,VSPW 的各項含義已經在前面的時序圖中得到體現。

圖1.6 HBPD,HOZVAL,HFPD 的各項含義已經在前面的時序圖中得到體現。

圖1.7 HSPW 的含義已經在前面的時序圖中得到體現。MVAL 只對 STN屏有效,對TFT屏無意義。

HSPW 的含義已經在前面的時序圖中得到體現,這里不再贅述。MVAL 只對 STN屏有效,對TFT屏無意義。

圖1.8 VSTATUS :當前VSYNC信號掃描狀態,指明當前VSYNC同步信號處于何種掃描階段。HSTATUS :當前HSYNC信號掃描狀態,指明當前HSYNC同步信號處于何種掃描階段。

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

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

PWREN 為LCD電源使能控制。在CPU LCD控制器的輸出信號中,有一個電源使能管腳LCD_PWREN,用來做為LCD屏電源的開關信號。

ENLEND 對普通的TFT屏無效,可以不考慮。

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

在Linux系統下,FrameBuffer的主要的結構如圖所示。Linux為了開發FrameBuffer程序的方便,使用了分層結構。fbmem.c處于Framebuffer設備驅動技術的中心位置。它為上層應用程序提供系統調用,也為下一層的特定硬件驅動提供接口;那些底層硬件驅動需要用到這兒的接口來向系統內核注冊它們自己。

fbmem.c 為所有支持FrameBuffer的設備驅動提供了通用的接口,避免重復工作。下將介紹fbmem.c主要的一些數據結構。

2.2 數據結構

2.2.1 Linux FrameBuffer的數據結構

在FrameBuffer中,fb_info可以說是最重要的一個結構體,它是Linux為幀緩沖設備定義的驅動層接口。它不僅包含了底層函數,而且還有記錄設備狀態的數據。每個幀緩沖設備都與一個fb_info結構相對應。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成員域標示了特定的FrameBuffer,實際上也就是一個FrameBuffer設備的次設備號。fb_var_screeninfo結構體成員記錄用戶可修改的顯示控制器參數,包括屏幕分辨率和每個像素點的比特數。fb_var_screeninfo中的xres定義屏幕一行有多少個點, yres定義屏幕一列有多少個點, bits_per_pixel定義每個點用多少個字節表示。其他域見以下代碼注釋。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結構體中,fb_fix_screeninfo中記錄用戶不能修改的顯示控制器的參數,如屏幕緩沖區的物理地址,長度。當對幀緩沖設備進行映射操作的時候,就是從fb_fix_screeninfo中取得緩沖區物理地址的。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還有一個很重要的域就是fb_ops。它是提供給底層設備驅動的一個接口。通常我們編寫字符驅動的時候,要填寫一個file_operations結構體,并使用register_chrdev()注冊之,以告訴Linux如何操控驅動。當我們編寫一個FrameBuffer的時候,就要依照Linux FrameBuffer編程的套路,填寫fb_ops結構體。這個fb_ops也就相當于通常的file_operations結構體。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);…………… } 上面的結構體,根據函數的名字就可以看出它的作用,這里不在一一說明。下圖給出了Linux FrameBuffer的總體結構,作為這一部分的總結。圖2.2

2.2.2 S3C2410中LCD的數據結構

在S3C2410的LCD設備驅動中,定義了s3c2410fb_info來標識一個LCD設備,結構體如下: 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指向我們上面所說明的fb_info結構體,代表了一個FrameBuffer。dev則表示了這個LCD設備。map_dma,map_cpu,map_size這三個域向了開辟給LCD DMA使用的內存地址。screen_cpu,screen_dma指向了LCD控制器映射的內存地址。另外regs標識了LCD控制器的寄存器。struct s3c2410fb_hw { unsigned long lcdcon1;unsigned long lcdcon2;unsigned long lcdcon3;unsigned long lcdcon4;unsigned long lcdcon5;};這個寄存器和硬件的寄存器一一對應,主要作為實際寄存器的映像,以便程序使用。這個s3c2410fb_info中還有一個s3c2410fb_mach_info成員域。它存放了和體系結構相關的一些信息,如時鐘、LCD設備的GPIO口等等。這個結構體定義為 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驅動的整體結構,反映了結構體之間的相互關系 2.3 主要代碼結構以及關鍵代碼分析 2.3.1 FrameBuffer驅動的統一管理

fbmem.c實現了Linux FrameBuffer的中間層,任何一個FrameBuffer驅動,在系統初始化時,必須向fbmem.c注冊,即需要調用register_framebuffer()函數,在這個過程中,設備驅動的信息將會存放入名稱為registered_fb數組中,這個數組定義為 struct fb_info *registered_fb[FB_MAX];int num_registered_fb;它是類型為fb_info的數組,另外num_register_fb則存放了注冊過的設備數量。

我們分析一下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;/* 超過最大數量 */ num_registered_fb++;for(i = 0;i < FB_MAX;i++)if(!registered_fb[i])break;/* 找到空余的數組空間 */ fb_info->node = i;

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

2.3.2 實現消息的分派

fbmem.c實現了對系統全部FrameBuffer設備的統一管理。當用戶嘗試使用一個特定的FrameBuffer時,fbmem.c怎么知道該調用那個特定的設備驅動呢?

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

圖2.4

2.3.3 開發板S3C2410 LCD驅動的流程

(1)在mach-smdk2410.c中,定義了初始的LCD參數。注意這是個全局變量。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)內核初始化時候調用s3c2410fb_probe函數。下面分析這個函數的做的工作。首先先動態分配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;設置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;……

該函數調用s3c2410fb_map_video_memory()申請DMA內存,即顯存。

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;…….設置控制寄存器,設置硬件寄存器。

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

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

(3)當用戶調用mmap()映射內存的時候,Fbmem.c把剛才設置好的顯存區域映射給用戶。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);

……

這樣就完成了驅動初始化到用戶調用的整個過程。3.BMP和JPEG圖形顯示程序

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

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

圖3.1

3.2 bmp位圖格式分析

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

圖3.2 文件頭中各個段的地址及其內容如圖3.3。

圖3.3 位圖文件頭數據結構包含BMP圖象文件的類型,顯示內容等信息。它的數據結構如下定義: Typedef struct {

int bfType;//表明位圖文件的類型,必須為BM long bfSize;//表明位圖文件的大小,以字節為單位 int bfReserved1;//屬于保留字,必須為本0 int bfReserved2;//也是保留字,必須為本0 long bfOffBits;//位圖陣列的起始位置,以字節為單位 } BITMAPFILEHEADER; 圖3.4 位圖文件頭的數據結構

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

圖3.6 BITMAPINFOHEADER數據結構

(3)對于象素小于或等于16位的圖片,都有一個顏色表用來給圖象數據陣列提供顏色索引,其中的每塊數據都以B、G、R的順序排列,還有一個是reserved保留位。而在圖形數據區域存放的是各個象素點的索引值。它的C語言結構如圖3.7所示。

圖3.7 顏色表數據結構

(4)對于24位和32位的圖片,沒有彩色表,他在圖象數據區里直接存放圖片的RGB數據,其中的每個象素點的數據都以B、G、R的順序排列。每個象素點的數據結構如圖3.8所示。

圖3.8 圖象數據陣列的數據結構

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

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

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

圖 3.9

3.3 實現顯示任意大小的圖片

開發板上的LCD屏的大小是固定的,S3C2410上的LCD為:240*320,PXA255上的為:640*480。比屏幕小的圖片在屏上顯示當然沒問題,但是如果圖片比屏幕大呢?這就要求我們通過某種算法對圖片進行縮放。

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

(1)、計算圖片大小與LCD屏大小的比例,以及方塊的大小。為了適應各種屏幕大小,這里并不直接給lcd_width和lcd_height賦值為240和320。而是調用標準的接口來獲取有關屏幕的參數。具體如下:

// 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;

計算比例:

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

(2)、從圖片的左上角開始,以(i* widthScale,j* heightScale)位起始點,以寬paneWidth 高paneHeight為一個小方塊,對該方塊的R、G、B數值分別取平均,得到映射點的R、G、B值,把該點作為要在LCD上顯示的第(i , j)點存儲起來。這部分的程序如下: //-------------取平均--------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 圖片數據提取及顯示的總流程

通過以上的分析,整個圖片數據提取及顯示的總流程如圖3.10 所示。圖 3.10 三 實驗過程與結果 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, }, };在函數smdk2410_machine_init()函數中加入LCD的初始化代碼,見下 static void __init smdk2410_machine_init(void){ s3c24xx_fb_set_platdata(&smdk2440_lcd_cfg);smdk_machine_init();} 2.編譯內核,產生zImage文件,放入tftp目錄下。

3.在nfs的dev目錄下建立FrameBuffer的設備節點,使用命令: mknod fb0 c 29 0 4.啟動開發板,加載內核和文件系統。5.編寫LCD的應用程序,程序見附錄。

6.采用arm-linux-gcc 編譯應用程序,產生可執行文件,放入nfs目錄中。7.在開發板上運行編譯好的可執行文件,便可。

8.下圖是BMP位圖顯示程序,在S3C2410上的運行結果。

四 實驗心得體會

1. LCD驅動的主要問題是沒有LCD屏的文檔,我們找不到它的那些參數值,后來只能參照Linux源碼里面的其他LCD屏的參數進行實驗。

2. 在驅動差錯的過程中,我們采用跟蹤打印的方法進行調試。剛開始的時候,內核打印出一行找不到LCD設備。我們定位到輸出這行提示的代碼處,進行反向跟蹤。發現傳給函數的設備指針為空,于是往上排查,終于發現源代碼中沒有定義LCD的設備信息。于是驅動問題也就順利解決了。

3. 原來一直以為,只要LCD驅動工作正常了,內核起來的時候,液晶屏會顯示出Logo。當時搞了很久一直沒有,還以為是驅動的問題。后來隨便寫了一個LCD應用程序,竟然能用。

4. 在調試過程應用程序中發現,在讀取文件頭的時候,如果直接定義一個bitmapfileheader為它動態分配內存:

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

(1)嵌入式系統設計與應用開發:鄭靈翔.北京:北京航天航空大學出版社 2006

第二篇:linux驅動及g-sensor學習心得

目錄

1.MODULE_INIT和MODULE_EXIT..............................................................................................2 2.I2C_DRIVER......................................................................................................................................2 3.LINUX的INPUT子系統..................................................................................................................3 3.1 從驅動層到核心層.......................................................................................................................3 3.2 事件處理層的處理.......................................................................................................................3 3.3 設備結點的創建...........................................................................................................................4 3.4 設備的注銷和釋放.......................................................................................................................4 4.WORK QUEUE..................................................................................................................................4 5.HAL層開發........................................................................................................................................5 5.1 HAL_MODULE_INFO_SYM.....................................................................................................5 5.2 對設備文件的訪問.......................................................................................................................7 6.BMA250功能描述..............................................................................................................................7 6.1 電源管理.......................................................................................................................................7 6.2 操作模式.......................................................................................................................................7 6.3 電源模式.......................................................................................................................................8 6.4 SENSOR數據..................................................................................................................................8 6.4.1 加速度....................................................................................................................................8 6.4.2 溫度........................................................................................................................................8 6.5 偏移補償.......................................................................................................................................9 6.5.1 慢補償....................................................................................................................................9 6.5.2 快補償....................................................................................................................................9 6.5.3 手動補償..............................................................................................................................10 6.5.4 內嵌校準..............................................................................................................................10 6.6 非易失性存儲器.........................................................................................................................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驅動開發步驟...................................................................................................................15 附錄 BMA250寄存器表......................................................................................................................17 linux驅動及g-sensor學習心得

通過對g-sensor driver code的研究學習,我對linux設備驅動開發和g-sensor有了一定的了解,現將學習所得歸納如下。

1.module_init和module_exit

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

module_init的作用是聲明一個驅動程序的入口函數,在init.h中可以看到對這個宏的定義如下:

#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

如果驅動程序要以func函數作為驅動的入口,則可以這樣聲明:module_init(func)。經過上面的宏處理以后,變成__initcall_func6 __used加入到內核映射的“.initcall”區。內核加載的時候,會搜索“.initcall”區內的所有條目,并按優先級加載它們。通過module_init聲明的驅動程序優先級為6,優先級越小越先加載。

對于驅動入口函數func,一般要加上__init屬性,這個宏告訴編譯器如果這個模塊被編譯到內核,則把這個函數放到(.init.text)段。而module_exit用于聲明驅動程序的出口,對于驅動出口函數,一般要加上__exit屬性,這個宏與__init類似,如果驅動被編譯進內核,則__exit宏會忽略清理函數。

在內核初始化后期,所有帶__init屬性的函數會被放在同一個section里,在用完之后,一次性釋放掉整個section。當函數初始化完成后,這個區域可以被清除掉以節約系統內存。

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

struct i2c_driver bma250_driver = {.driver = {

.owner = THIS_MODULE,.name = SENSOR_NAME, },.id_table = bma250_id,.probe = bma250_probe,.remove };= bma250_remove, 在這個結構中,定義了驅動所屬module、驅動名、驅動的id表、驅動初始化以及移除接口。可以通過i2c_add_driver將sensor driver添加進module中,通過i2c_del_driver將driver移除。

3.linux的input子系統

Linux系統提供了input子系統,可以用以實現系統中大多數輸入設備的設備驅動,pd318中g-sensor的設備驅動就是通過它來實現的。

input子系統由核心層、驅動層和事件處理層三部分組成。當輸入設備產生了一個輸入事件時,由驅動層對事件加以識別,然后提交給核心層,核心層根據事件的類型將事件交給事件處理層處理,事件處理層將處理結果再反饋給用戶。其中核心層由/drivers/input/input.c及相關頭文件實現,對下提供了設備驅動的接口,對上提供了事件處理層的編程接口。這樣,一個輸入設備的輸入過程可以分離為獨立的兩部分:驅動層到核心層,核心層到事件處理層,整個鏈路的這兩部分的接口的創建是獨立的。

3.1 從驅動層到核心層

驅動層負責和底層的硬件設備打交道,將底層硬件對用戶輸入的響應轉換為標準的輸入事件以后再向上發送給核心層。

驅動層先要調用input_allocate_device接口來分配一個設備,對設備進行一些屬性賦值,如設備名、總線類型、響應事件類型及事件參數、驅動數據等等,然后通過input_register_device函數向input子系統中注冊所要驅動的輸入設備。對于g-sensor來說,驅動需要響應EV_ABS事件,該事件需要向核心層提供一個絕對坐標,事件參數ABS_X、ABS_Y、ABS_Z分別對應g-sensor在x、y、z軸上的偏移量。當g-sensor發生坐標變化時,驅動程序需要從相應寄存器中讀出偏移量,然后通過input_report_abs接口上報給input子系統,由input子系統負責將事件及參數變化發送給事件處理層處理。

3.2 事件處理層的處理

驅動層只是把輸入設備注冊到input子系統中,在驅動中的code中并不創建設備結點。應用程序用來與設備打交道的設備結點的創建由事件處理層調用核心層的函數來實現。而對于常用輸入設備(如mouse、keyboard、joystick等),在創建具體的設備結點之前,事件處理層需要先通過input_register_handler注冊一類設備的輸入事件處理函數及相關接口。以鼠標事件處理為例,mouse input_handler定義如下:

static struct input_handler mousedev_handler = {.event = mousedev_event, //向系統報告input事件,系統通過read方法讀取

.connect = mousedev_connect, //和input_dev匹配后調用connect構建

.disconnect = mousedev_disconnect,.fops = &mousedev_fops, //event設備文件的操作方法.minor = MOUSEDEV_MINOR_BASE, //次設備號基準值

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

在linux中沒有對g-sensor事件處理register的通用標準定義,對于這類事件,事件處理層會統一地當作evdev事件處理,為設備創建一個對應的設備文件,在HAL層可以通過open該設備文件來實現與底層的通信。

3.3 設備結點的創建

向input子系統注冊一個硬件設備后,在input_register_handler中調用已經注冊的所有類型的input handler的connect函數,每一個connect函數會根據注冊設備所支持的事件類型判斷是否與自己有關,如果有關就調用input_register_minor創建一個具體的設備結點。

此外,如果已經注冊了一些硬件設備,此后再注冊一類新的input handler,則同樣會對所有已注冊的設備調用新的input handler的connect函數以確定是否需要創建新的設備結點。

3.4 設備的注銷和釋放

在remove driver同時注銷掉所注冊的input設備,通過input_unregister_device函數注銷設備,通過input_free_device接口釋放設備資源。

4.work queue 在pd318 bma250.c的bma25_probe函數中可以看到,對于g-sensor狀態的獲取和report是通過linux的work queue機制來實現的。這里可以看到一個宏:INIT_DELAYED_WORK。這個宏被定義在/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)

從這個定義中可以看到,INIT_DELAYED_WORK就是帶有timer的INIT_WORK,而INIT_WORK所做的事情就是初始化一個工作,但是并不馬上執行,需要將來某個時刻去觸發執行。INIT_DELAYED_WORK(INIT_WORK)需要兩個參數,一個是struct delayed_work(struct work_struct)結構體,一個是一個函數指針_func。這個初始化實際上就是為一個struct work_struct結構體綁定一個函數。在/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 };

在這個結構體中有一個成員函數func,初始化的目的就是使這個func指向INIT_WORK的第二個參數_func。以后調用schedule_delayed_work(schedule_work)時,只要傳遞struct delayed_work(struct work_struct)結構體參數即可,不需要再傳遞_func。這是因為,處理work的線程實際上跑的是一個死循環,有事情就處理,沒事情就睡眠,而schedule_delayed_work(schedule_work)的作用就是喚醒這個線程。

INIT_DELAYED_WORK與schedule_delayed_work,INIT_WORK與schedule_work是對應著使用的,兩者的區別就是schedule_work在喚醒線程的同時立刻執行_func,而schedule_delayed_work在喚醒線程后delay一段時間再執行。bma250.c通過使用INIT_DELAYED_WORK與schedule_delayed_work,實現g-sensor對不同取樣頻率的支持。

關于workqueue還有兩個函數,它們是cancel_delayed_work和flush_scheduled_work。cancel_delayed_work的作用是對于一個延遲執行的工作而言,在工作還未執行的時候就把它給取消掉。而flush_scheduled_work的作用是為了防止有競爭條件的出現。一般在cancel_delayed_work之后都得調用flush_scheduled_work,函數會一直等待,直到隊列中所有工作都被執行以后才返回。

5.HAL層開發

5.1 HAL_MODULE_INFO_SYM HAL層,即硬件抽象層,android層對于硬件的調用一般通過HAL的方式來完成。要想HAL的編寫方法,首先需要了解HAL的運行機制。看android源碼,可以發現android中實現調用HAL是通過hw_get_module來實現的。

int hw_get_module(const char *id, const struct hw_module_t **module);上面的是其函數原型,id會指定Hardware的id,這是一個字符串,比如sensor的id是#define SENSORS_HARDWARE_MODULE_ID “sensors”。如果找到了對應的hw_module_t結構體,會將其指針放入*module中。代碼實現如下:

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;

}

/* 獲取并訪問HAL動態鏈接庫 */

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){

/* 調用load函數打開動態鏈接庫*/

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

這個函數的作用,就是獲取動態鏈接庫并調用load函數打開它。再看load函數,可以發現該函數中出現了一個宏HAL_MODULE_INFO_SYM_AS_STR。HAL_MODULE_INFO_SYM_AS_STR是硬件模塊在動態鏈接庫中的標志,定義在hardware.h中如下:

#define HAL_MODULE_INFO_SYM HMI #define HAL_MODULE_INFO_SYM_AS_STR “HMI”

再去對照一個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結構體的定義為: struct sensors_module_t {

struct hw_module_t common;

int(*get_sensors_list)(struct sensors_module_t* module,struct sensor_t const** list);};它定義了一個hw_module_t類型的common成員,和獲取sensors list的接口函數sensors__get_sensors_list。注意,這里的HAL_MODULE_INFO_SYM必須為這個名字,這樣編譯器才會將這個結構體的導出符號變為“HMI”。

從以上分析可以知道,HAL層開發就是要定義一個hw_module_t結構體,結構體名稱命名為HAL_MODULE_INFO_SYM,然后實現結構體的相關內容即可。也就是說,HAL模塊的入口地址就是HAL_MODULE_INFO_SYM變量,通過它,我們可以訪問到HAL模塊中所有想要外部訪問到的方法。

5.2 對設備文件的訪問

在HAL層可以通過訪問3.2節中evdev.c生成的設備文件來實現對硬件設備的訪問。對于g-sensor來說,要實現對于sensor的poll、setDelay、activate、close等函數接口。在poll接口中,程序通過一個循環去獲取設備文件中顯示出的sensor的坐標變化,在收到EV_SYN事件時,將sensor的坐標變化反饋給android系統,android對獲取到的狀態變化作出相應的處理。

6.bma250功能描述

6.1 電源管理

VDD :主電源,為所有內部模擬/數字功能塊供電。VDDIO:專為數字I/O供電的單獨電源引腳。

6.2 操作模式

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

Dedicated mode :sensor作為一個獨立設備,沒有外部中斷功能,使用內部中斷機制,一次只能夠被指派處理orientation recognition、tap sensing、slope detection三種中斷中的一種。

PS引腳的連接狀態決定了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 :電路全開,整個g-sensor處于正常工作狀態。

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

suspend mode :包括振蕩器在內的整個board處于power down狀態,僅可以讀取寄存器、寫suspend位和softreset寄存器。

三種模式之間可能的狀態切換如圖1所示。

圖1 電源模式切換圖

6.4 sensor數據

6.4.1 加速度

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

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

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

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

6.5 偏移補償

偏移補償就是根據ADC值對加速度數據作出一個補償。不過用于補償的公共寄存器(public register)0x38 ~ 0x3D對每個軸用于讀寫補償的只有8 bit,而內部寄存器(internal register)對于每個加速度值都是用10 bit(MSB + LSB)來存儲的。在這之間需要一個轉換,補償轉換原則如圖2所示。

圖2 8-bit/10-bit補償轉換原則圖

從上圖可以看出,根據設定的range,公共寄存器的補償值將要對輸出的加速度數據作出補償。例如,公共寄存器值為00000001b,從圖2中得到加速度數據補償為±7.8mg,對應內部寄存器為±2 LSB。

bma250支持四種偏移補償方式:慢補償、快補償、手動補償和內嵌校準。對于慢補償和快補償來說,0x37寄存器的offset_target_x、offset_target_y、offset_target_z決定了sensor在x、y、z軸上的目標值。而0x36的offset_reset位如果被置為1,則所有的偏移補償寄存器都reset為0。

6.5.1 慢補償

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

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

6.5.2 快補償

連續取16個加速度值,計算出平均值,將這個平均值與0x37寄存器所設置的目標值的差值寫入0x37寄存器中。0x36寄存器的cal_trigger決定了對哪個軸實行快補償。cal_trigger = 00b none cal_trigger = 01b x軸 cal_trigger = 10b y軸 cal_trigger = 11b z軸

當正在進行快補償時,慢補償被阻斷。

6.5.3 手動補償

通過數字接口去手動設置補償值。在手動補償時要注意不要影響正在進行的偏移補償,所以一般在獲得new data中斷后立刻執行。在慢補償有效或快補償正在運行時,不允許對偏移補償寄存器作出寫操作。

6.5.4 內嵌校準

通過前面所提到的偏移補償方法計算出合適的補償值,然后將這些補償值存放在EEPROM中。在每一次設備重置時,補償值被load進image寄存器作為偏移補償,直到它被用其他的補償方式重寫。

6.6 非易失性存儲器

bma250具有三種存儲器:hard-wired、valatile和non-valatile。non-valatile存儲器通過EEPROM來實現,可以通過訪問image寄存器來訪問它。在bma250中共有八個image寄存器(0x38 ~ 0x3F),0x38 ~ 0x3D被用作存儲偏移補償值,0x3E和0x3F保留備用。

在兩種情況下EEPROM內容會被load到image寄存器中去,一種情況是設備重置時,另一種情況是將0x33寄存器中的nvm_load值置為1。只要image寄存器還沒有load完成,nv_ram位就為1,在完成后被置成0。image寄存器可以像其他寄存器一樣執行讀寫操作。

寫EEPROM要經過三步:

1)將新內容寫入image寄存器;

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

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

每次寫EEPROM總是要更新整個EEPROM內容,可以通過讀取0x33寄存器的nvm_rdy位來檢測寫狀態。nvm_rdy等于1,表示寫操作正在進行中;nvm_rdy等于0,表示寫操作已完成。在寫EEPROM時,電源模式必須處于normal mode,而且不能對image寄存器作出更新。

6.7 中斷控制器

中斷的清除取決于所選擇的中斷模式,bma250支持三種模式:non-latched、latched和temporary。中斷模式可以通過0x21寄存器的低四位latch_int來設置,具體對應關系如表1所示。

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

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

表1 中斷模式選擇對應表

在temporary模式下,中斷狀態和pin腳在一段時間后被清除,這段時間由latch_int的具體值來決定。

bma250支持七種中斷機制,分別為: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作為輸入。

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

6.7.1 new data中斷

new data中斷提供了一個同步讀取加速度數據的服務。它在將一個z軸的新值寫入數據寄存器時產生,在下一次數據獲取循環開始的時候自動清除。通過將0x17寄存器的data_en位置為1來使能new data中斷,中斷狀態存儲在0x0A的data_int位中。

6.7.2 slope中斷

在sensor移動中產生連續的加速度信號,當一定數量的連續兩個加速度信號的值差大于一個預設的臨界值時,會產生一個slope中斷。而在一定數量的連續兩個加速度信號的值差小于這個預設值時,中斷被清除。可以通過0x28寄存器的slope_th位來設置這個臨界值,1 LSB slope_th對應1 LSB的加速度數據。

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

通過設置0x16寄存器的slope_en_x、slope_en_y和slope_en_z為1來使能在x、y、z軸上的slope中斷。在dedicated mode喚醒狀態時,三個軸的slope中斷都被使能,0x16寄存器上的這三個值無效。

中斷狀態存儲在0x09的slope_int位。檢測到的slope中斷狀態信息存放在0x0B寄存器中,slope_first_x、slope_first_y、slope_first_z分別標識了觸發中斷的軸狀態,slope_sign位標識了正負(0為正,1為負)。

6.7.3 tap中斷

tap中斷類似于鼠標按鍵的click,當至少在一個軸上的加速度slope大于一個預定義的值時,該中斷產生。

有兩種tap事件:single tap和double tap。single tap是在一次tap事件后,緊跟著是一段安靜時間,類似于鼠標的單擊;而double tap是在一段定義好的時間內,連續發生兩次tap事件,類似于鼠標的雙擊。

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

single tap的中斷狀態存儲在0x09寄存器的s_tap_int位,double tap的中斷狀態存儲在0x09寄存器的d_tap_int位。

通過設置0x2B寄存器的tap_th值來設置tap中斷的slope預設臨界值,在不同的range下,slope_th表示不同的數值。1 LSB的tap_th對應于2g-range下的62.5mg slope,4g-range下的125mg slope,8g-range下的250mg slope,16g-range下的500mg slope。

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

表2 tap_dur對應持續時間值表

tap中斷產生后12.5 ms后會被自動清除。

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

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

6.7.4 orientation中斷

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

圖3 sensor角度矢量圖

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

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

3、表

4、表5所示。

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

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

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

在以上三張表中,‘hyst’ 表示一個延遲,這個值通過0x0C寄存器的orient_hyst設置。1 LSB的orient_hyst對應于62.5 mg。

通過將0x16寄存器的orient_en位置為1來使能orientation中斷。當0x0C寄存器的orient發生變化時,中斷產生,一段之間后自動清除。中斷狀態存儲在0x09寄存器的orient_int位。

0x0C寄存器的orient位發生變化后,中斷的產生可能會被阻斷,這可以通過0x2C寄存器的orient_blocking進行設置。

orient_blocking = 00b表示沒有阻斷; orient_blocking = 01b表示θ阻斷;

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

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

θ阻斷通過下面的不等式定義:

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

6.7.5 flat中斷

flat中斷,顧名思義,用于檢測sensor是否位于水平狀態,判斷設備位于水平狀態的條件時:

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

通過將0x16寄存器的flat_en置為1使能flat中斷。當0x0C寄存器的flat值發生變化,并且這個值保持穩定一段時間后,flat中斷產生。保持穩定的時間的最小值由0x2F寄存器的flat_hold_time決定。flat_hold_time等于00b、01b、10b、11b分別表示0、512 ms、1024 ms、2048 ms。這個中斷在一段之間后自動清除。flat中斷狀態存儲在0x09寄存器的flat_int位。

6.7.6 low-g中斷

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

low-g臨界值通過0x23寄存器的low_th設置,1 LSB low_th對應于7.81 mg的加速度。可以通過設置0x24寄存器的low_hy來設置滯后值,1 LSB low_hy對應于125 mg的加速度值。

當某一軸上的加速度絕對值(single mode)或三軸加速度絕對值的總和(sum mode)小于臨界值超過一段時間(這個時間由0x22寄存器的low_dur決定)后,中斷產生;當某一軸上的加速度絕對值(single mode)或三軸加速度絕對值的總和(sum mode)大于臨界值減去滯后值至少超過一個數據的獲取時間后,中斷被重置。

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

6.7.7 high-g中斷

這個中斷是基于比較加速度數據和high-g臨界值而產生的,主要用于對震動或其他的一些高加速度事件的偵測。

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

high-g臨界值通過0x26寄存器的high_th設置,1 LSB high_th對應于2g-range下的7.81mg,4g-range下的15.63mg,8g-range下的31.25mg,16g-range下的62.5mg。可以通過設置0x24寄存器的high_hy來設置滯后值,1 LSB high_hy對應于2g-range下的125mg,4g-range下的250mg,8g-range下的500mg,16g-range下的1000mg。

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

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

7.sensor驅動開發步驟 綜上所述,sensor驅動開發可以歸納為以下步驟來完成: 1.read && verify spec,確認chip功能以及register配置;

2.按照spec所述,在code中加入主要的配置數據,如電源模式、主要寄存器的配置、range支持、bandwidth支持、中斷配置等; 3.設計主要的數據結構;

4.實現sensor數據的設置和獲取接口;

5.通過module_init和module_exit接口加入driver層入口和出口函數函數;

6.定義i2c_driver,設置driver的probe和remove函數入口,通過i2c_add_driver和i2c_del_driver接口添加/移除driver; 7.實現driver的probe函數功能,函數中實現sensor的硬件配置,并通過linux的input子系統實現sensor數據的上報;

8.實現driver的remove函數功能,函數中實現設備的移除、資源的釋放等。

9.HAL層中注冊hw_module_t結構體,將結構體名稱命名為HAL_MODULE_INFO_SYM;

10.判斷sensor設備文件是否存在,通過open_input_device訪問設備文件,并注冊設備文件的poll、activate、close等函數; 11.實現sensor list的獲取函數;

12.實現對設備文件的主要操作接口,完成上層與硬件設備的通信; 13.調試sensor功能。附錄 bma250寄存器表

第三篇:創新驅動發展戰略學習心得范文

精品學習資料范文

創新驅動發展戰略學習心得

創新驅動發展戰略學習心得

通過將近一個月的課程學習,我獲益匪淺,對“創新”有了新的理解和認識。創新是一種探索未知事物、尋找科學真理的活動,意味著新的嘗試,走新的道路。創新是引領發展的第一動力,必須擺在國家發展全局的核心位置,深入實施創新驅動發展戰略。作為黨員領導干部,更應該樹立創新意識,自覺運用創新思維方式和方法謀劃自身工作。

一、要樹立創新的勇氣

中國的改革航船已經駛入攻堅克難的深水區。只有創新思維,沖破思想觀念的束縛,突破利益固化的藩籬,攻克體制機制上的頑癥痼疾,才能進一步發展社會生產力和增強社會活力。創新,需要敢于冒險的勇氣和魄力。中國改革創新,束縛怎么沖破? 藩籬如何突破? 頑癥痼疾又怎樣攻克? 倘若沒有一往無前的勇氣,沒有壯士斷腕的決心,沒有背水一戰的氣概,沒有迎難而上的擔當,這艘改革航船將注定無法抵達勝利的彼岸。我們要拿出逢山開路的闖勁兒,拿出甩開膀子的干勁兒,拿出抓鐵有痕的韌勁兒,拿出眾人拾柴的心勁兒,拿出

精品學習資料范文

勇毅篤行的穩勁兒,用今天的改革為明天的遠行鋪路搭橋。

二、要講究創新的方法

實現創新,需要具備追求卓越的意識、開拓創先的精神和獨具卓識的方法。要學會掌握和運用逆向思維、發散思維和聯想思維等方法,克服思維的單一性、孤立性,善于多角度、多層次、全方位地解決、學習實踐中的各種問題,力爭達到獨創性、系統性。“創新是民族進步的靈魂,創新是國家興旺發達不竭的動力”創新就在于創造,創造就在于人腦的訓練。創新思維是發散思維和集中思維的結合,發散思維是構成創造性思維的主導成分。發散思維是在思維過程中通過重組所給的和記憶中的信息,得到眾多可能的答案、設想或解決方案。它的特點為是以一個問題為中心,充分發揮人的聯想力和想象力,突破原有的知識圈,從一點向四面八方想開去,從各個不同的角度或側面進行思考,讓思維多向流動,以便獲得解決問題的全部可能。這種思考無一定方向、無一定范圍、不墨守成規、不拘于傳統方法,可以標新立異、異想天開,從已知的領域去探求未知的境界。所以,發散思維是一種創新思維方法,集中體現了創造性思維的本質牲特征。我們要有意識的訓練運用這些思維方式和方法,創造性的開展自身的工作。

精品學習資料范文

三、要在實踐中創新

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

四、要加強知識的積累

要勤于學習各種知識,不斷開闊視野。知識和經驗是創新思維的基礎。有豐富的閱歷,廣博的知識,就有足夠的閃光點用來進行

精品學習資料范文

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

五、要注重人才隊伍的創新要相信“時勢造英雄”,要充分認識到國家的人口基數大,高效人才的流動。要鼓勵科研人員創業創新。大力弘揚創新文化,厚植創新沃土,營造敢為人先、寬容失敗的良好氛圍,充分激發企業家精神,調動全社會創業創新積極性,匯聚成推動發展的磅礴力量。

精品學習資料范文

對于商貿工作而言,我認為“創新”所帶來的影響將會更深遠,其作用不可替代。

一、創新產業規模化和組織化建設,提升流通水平和層次。商貿流通企業規模小、流通水平低嚴重阻礙了商貿流通業的發展。一方面可以加大商貿流通企業的并購力度,鼓勵企業以參股、控股、兼并、重組等方式實現更大范圍的整合,形成更大的連鎖型企業,優

第四篇:S3C2410 LCD驅動學習心得-4

3.BMP和JPEG圖形顯示程序

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

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

圖3.1

3.2 bmp位圖格式分析

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

圖3.2 文件頭中各個段的地址及其內容如圖3.3。

圖3.3 位圖文件頭數據結構包含BMP圖象文件的類型,顯示內容等信息。它的數據結構如下定義: Typedef struct {

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

圖3.4 位圖文件頭的數據結構

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

圖3.5 位圖信息頭的數據結構包含了有關BMP圖象的寬,高,壓縮方法等信息,它的C語言數據結構如圖3.6所示。Typedef struct { long biSize; //指出本數據結構所需要的字節數

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

biPlanes;//輸出設備的位平面數,必須置為1 int

biBitCount;//給出每個象素的位數 long biCompress;//給出位圖的壓縮類型 long biSizeImage;//給出圖象字節數的多少 long biXPelsPerMeter;//圖像的水平分辨率 long biYPelsPerMeter;//圖象的垂直分辨率

long biClrUsed;//調色板中圖象實際使用的顏色素數 long biClrImportant;//給出重要顏色的索引值 } BITMAPINFOHEADER;

圖3.6 BITMAPINFOHEADER數據結構

(3)對于象素小于或等于16位的圖片,都有一個顏色表用來給圖象數據陣列提供顏色索引,其中的每塊數據都以B、G、R的順序排列,還有一個是reserved保留位。而在圖形數據區域存放的是各個象素點的索引值。它的C語言結構如圖3.7所示。

圖3.7 顏色表數據結構(4)對于24位和32位的圖片,沒有彩色表,他在圖象數據區里直接存放圖片的RGB數據,其中的每個象素點的數據都以B、G、R的順序排列。每個象素點的數據結構如圖3.8所示。

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

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

圖 3.9

本篇文章來源于 Linux公社網站(本篇文章來源于 Linux公社網站(

第五篇:S3C2410 LCD驅動學習心得-6

實驗過程與結果 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,}, };在函數smdk2410_machine_init()函數中加入LCD的初始化代碼,見下 static void __init smdk2410_machine_init(void){ s3c24xx_fb_set_platdata(&smdk2440_lcd_cfg);smdk_machine_init();} 2.編譯內核,產生zImage文件,放入tftp目錄下。

3.在nfs的dev目錄下建立FrameBuffer的設備節點,使用命令:

mknod fb0 c 29 0 4.啟動開發板,加載內核和文件系統。5.編寫LCD的應用程序,程序見附錄。

6.采用arm-linux-gcc 編譯應用程序,產生可執行文件,放入nfs目錄中。7.在開發板上運行編譯好的可執行文件,便可。

8.下圖是BMP位圖顯示程序,在S3C2410上的運行結果。

實驗心得體會

1. LCD驅動的主要問題是沒有LCD屏的文檔,我們找不到它的那些參數值,后來只能參照Linux源碼里面的其他LCD屏的參數進行實驗。

2. 在驅動差錯的過程中,我們采用跟蹤打印的方法進行調試。剛開始的時候,內核打印出一行找不到LCD設備。我們定位到輸出這行提示的代碼處,進行反向跟蹤。發現傳給函數的設備指針為空,于是往上排查,終于發現源代碼中沒有定義LCD的設備信息。于是驅動問題也就順利解決了。

3. 原來一直以為,只要LCD驅動工作正常了,內核起來的時候,液晶屏會顯示出Logo。當時搞了很久一直沒有,還以為是驅動的問題。后來隨便寫了一個LCD應用程序,竟然能用。4. 在調試過程應用程序中發現,在讀取文件頭的時候,如果直接定義一個bitmapfileheader為它動態分配內存:

*bmph=(bitmapfileheader*)malloc(sizeof(bitmapfileheader));然后用fread((char*)bmph,sizeof(bitmapfileheader),1,f)把文件頭一次性讀出來,讀出來的文件頭是錯誤的,經過調試發現原因是bitmapfileheader這個結構體中的type屬性原本應該占2字節,但是被編譯器在分配內存的時候進行了內存對齊的優化,給他分配了4個字節的空間,造成讀文件的錯誤。因此在編程中要特別注意內存對齊的影響。typedef struct { WORD

type;(被優化)DWORD bfsize;DWORD reserved;DWORD offbits;} bitmapfileheader;5. 在嵌入式應用程序的移植過程中,我們原來認為ARM和PC機大小尾順序是不同的,因此在應用程序中,也對這個差別進行了處理。當時,在調試過程中發現,PC機程序可以直接移植到ARM上,不需要任何改動。但是我們的程序,的確存在會產生大小尾問題代碼(在使用fread()讀入時)。這究竟是為什么?有人說,ARM是可以設置大小尾順序的。后來這個問題也沒有深究下去。

參考文獻

(1)嵌入式系統設計與應用開發:鄭靈翔.北京:北京航天航空大學出版社 2006

本篇文章來源于 Linux公社網站(

下載S3c2410 LCD驅動學習心得[五篇]word格式文檔
下載S3c2410 LCD驅動學習心得[五篇].doc
將本文檔下載到自己電腦,方便修改和收藏,請勿使用迅雷等下載。
點此處下載文檔

文檔為doc格式


聲明:本文內容由互聯網用戶自發貢獻自行上傳,本網站不擁有所有權,未作人工編輯處理,也不承擔相關法律責任。如果您發現有涉嫌版權的內容,歡迎發送郵件至:645879355@qq.com 進行舉報,并提供相關證據,工作人員會在5個工作日內聯系你,一經查實,本站將立刻刪除涉嫌侵權內容。

相關范文推薦

    “解放思想、改革開放、創新驅動、科學發展”學習心得

    “解放思想、改革開放、創新驅動、科學發展” 大討論活動心得體會 上尤各莊小學---張曉君 接縣教育局的“解放思想、改革開放、創新驅動、科學發展”大討論活動的通知,我校全......

    《創新驅動與供給側改革》學習心得[大全五篇]

    《創新驅動與供給側改革》學習心得 3月30日下午,在縣委中心組(擴大)理論學習會上,有幸聆聽了中國人民大學世界經濟研究中心主任黃衛平教授所作題為《創新驅動與供給側改革》的專......

    解放思想改革開放創新驅動科學發展大討論活動學習心得[精選]

    解放思想改革開放創新驅動科學發展大討論活動學習心得 開展解放思想改革開放創新驅動科學發展大討論活動,就是要提高工作的服務質量,為科學決策服務。要以開展解放思想改革開......

    創新驅動

    創新驅動為院校發展注入無限活力 ——理工大學 市東醫院“理工醫創新基地”建設一周年回顧 2010年早春,市東醫院 上海理工大學、市東醫院“理工醫創新基地” 簽約暨揭牌儀式......

    創新驅動發展

    創新驅動發展 黨的十八大明確提出“科技創新是提高社會生產力和綜合國力的戰略支撐,必須擺在國家發展全局的核心位置。”強調要堅持走中國特色自主創新道路、實施創新驅動發......

    創新驅動發展

    創新驅動發展 十八大、“兩會”相關論述 材料一:科技創新驅動發展戰略黨的十八報告強調,實施創新驅動發展戰略。科技創新是提高 社會生產力和綜合國力的戰略支撐,必須擺在國家......

    創新驅動科學發展

    創新驅動科學發展 破除事業發展瓶頸開創廣電工作新局面 ——縣廣電臺2016年上半年工作總結及下半年工作謀劃 上半年,縣廣播電視臺在縣委、縣政府正確領導下,緊緊圍繞縣委、......

    任務驅動教學法

    一、“任務驅動”式教學的含義 “任務驅動”式教學是將整個知識體系分解為一個一個相對獨立而相互關聯的“任務”,讓學生在一個個典型“任務”的驅動下有序展開學習活動,引導......

主站蜘蛛池模板: 亚洲日本在线电影| 少妇装睡让我滑了进去| 色一情一乱一伦一区二区三区日本| 五月综合网亚洲乱妇久久| 女人把脚张来开让男人桶| 性做无码视频在线观看| 一本色道久久综合亚洲精品不卡| 欧美人与动牲交精品| 国产人妻人伦精品欧美| 亚洲国产精品va在线播放| 久久综合亚洲色一区二区三区| 欧美嫩交一区二区三区| 国产精品爽爽久久久久久无码| 亚洲高清aⅴ日本欧美视频| 欧美拍拍视频免费大全| 性色av无码久久一区二区三区| 久久久久久久综合狠狠综合| 亚洲欧美国产精品专区久久| 中文字幕天天躁日日躁狠狠躁免费| 久久国产亚洲精品赲碰热| 国产精品丝袜肉丝出水| 福利姬国产精品一区在线| 免费a级毛片无码a∨男男| 久久永久免费专区人妻精品| 亚洲午夜性猛春交xxxx| 久久久久九九精品影院| 国产精品亚洲成在人线| 动漫成人无码精品一区二区三区| 久久久久久久性潮| 入侵人妻反抗中文字幕| 日本无卡无吗二区三区入口| 国产熟睡乱子伦午夜视频在线| 亚洲全国最大的人成网站| 无码制服丝袜人妻在线视频精品| 在线观看av永久免费| 午夜片少妇无码区在线观看| 国产成人aaa在线视频免费观看| 亚洲一线产区二线产区分布| 亚洲国产成av人天堂无码| 麻豆文化传媒精品一区二区| 国产在线国偷精品产拍|