LCD驱动程序分析
- 格式:doc
- 大小:181.50 KB
- 文档页数:34
基于STM32单片机FSMC接口驱动LCD的配置与分析概述:STM32单片机是一款高性能、低功耗的32位ARM Cortex-M系列微控制器。
它具有丰富的外设接口,其中包括FSMC(Flexible Static Memory Controller)接口,用于连接外部存储器,例如LCD显示器。
本文将详细介绍如何配置和驱动LCD显示器,以及分析FSMC接口的工作原理。
一、LCD驱动接口配置1. 在STM32的标准外设库中,FSMC的配置函数位于STM32F10x_stdperiph_driver库的stm32f10x_fsmc.c和stm32f10x_fsmc.h文件中。
通过这些函数,可以配置FSMC接口的参数,以使它能够连接和驱动LCD。
2.首先,需要配置FSMC的时钟预分频值。
根据LCD的要求以及系统时钟频率,选择适当的预分频值。
这可以通过设置FSMC_BCRx寄存器中的MBKEN和PS字段来实现。
3.然后,需要配置FSMC的存储芯片选择使能信号(CSEN)和片选信号(ALE)。
这可以通过设置FSMC_BCRx寄存器中的CSEN和ALEN字段来实现。
4.接下来,需要配置FSMC的读写延迟、数据宽度、存储器类型等参数。
这可以通过设置FSMC_BTRx和FSMC_BWTRx寄存器来实现。
5.最后,需要配置FSMC的地址线、数据线和控制线的映射关系。
这可以通过设置FSMC_BCRx寄存器中的MWID、MTYP、MUXEN、MWID和NWID 字段来实现。
二、FSMC接口工作原理1.FSMC接口是一种高速并行接口,它通过多路复用来连接不同的外部存储器。
它具有独立的读/写数据线和地址线,以及控制线,用于选择读/写操作和片选信号。
2. FSMC接口支持不同类型的存储器,例如SRAM、NOR Flash、NAND Flash和LCD。
每种存储器都有不同的时序和接口要求。
3.FSMC接口的时序参数主要包括时钟预分频值、读/写延迟、数据宽度和地址线宽度等。
linux的lcd驱动详细讲解嵌入式驱动程序Day12Top1.LCD驱动设计开发1 LCD驱动设计开发1.1 问题通过lcd驱动开发掌握linux内核framebuffer驱动开发通用方法。
1.2 方案一、帧缓冲(Framebuffer)。
帧缓冲(Framebuffer)是Linux为显示设备提供的一个接口,Linux抽象出FrameBuffer这个设备来供用户态进程实现直接写屏。
Framebuffer机制模仿显卡的功能,将显卡硬件结构抽象掉,可以通过 Framebuffer的读写直接对显存进行操作。
用户可以将Framebuffer看成是显示内存的一个映像,将其映射到进程地址空间之后,就可以直接进行读写操作,而写操作可以立即反应在屏幕上。
这种操作是抽象的,统一的。
用户不必关心物理显存的位置、换页机制等等具体细节。
这些都是由 Framebuffer设备驱动来完成的。
Framebuffer本身不具备任何运算数据的能力,就只好比是一个暂时存放水的水池。
CPU将运算后的结果放到这个水池,水池再将结果流到显示器,中间不会对数据做处理。
应用程序也可以直接读写这个水池的内容。
在应用程序中,一般通过将FrameBuffer 设备映射到进程地址空间的方式使用,比如下面的程序就打开/dev/fb0 设备,并通过mmap 系统调用进行地址映射。
FrameBuffer 设备还提供了若干 ioctl 命令,通过这些命令,可以获得显示设备的一些固定信息(比如显示内存大小)、与显示模式相关的可变信息(比如分辨率、象素结构、每扫描线的字节宽度),以及伪彩色模式下的调色板信息等等。
二、FrameBuffer在Linux中的实现和机制。
Framebuffer对应的源文件在linux/drivers/video/目录下。
总的抽象设备文件为fbcon.c,在这个目录下还有与各种显卡驱动相关的源文件。
1.分析Framebuffer设备驱动。
JZ2440 4.3寸屏LCD驱动和触摸屏驱动分析笔记 LCD驱动分析S3C2410/2440LCD控制结构图LCDCDMA从SBUS拉取图像数据,将FIFO数据送到VIDPRCS组合后发出,当FIFO减少到0或者阀值,LCDCDMA又自动从SBUS上拉取图像数据。
显示器沿着“Z”字形的路线进行扫描,使用HSYNC(表示“是跳到最左边的时候了”)、VSYNC(表示“是跳到最上边的时候了”)信号来控制扫描路线的跳转。
它只会依据这两个信号来取得、显示数据,并不理会该数据是否有效,何时发出有效数据由显卡决定。
显示器扫描一帧数据的过程S3C2410/2440 TFT LCD时序图每个VSYNC信号便是一帧数据的开始;每个HSYNC信号表示一行数据的开始,不管这些数据是否有效;每个VCLK信号表示正在传输一个像素的数据,无论它是否有效。
数据是否有效只是对CPU的LCD控制器来说的,LCD根据VSYNC、HSYNC、VCLK不停地读取总线数据、显示。
320*240 TFT屏显示器控制图struct fb_info{int node;int flags;struct fb_var_screeninfo var; /* Current var */ struct fb_fix_screeninfo fix; /* Current fix */struct fb_monspecs monspecs;/* Current Monitor specs */struct work_struct queue;/* Framebuffer event queue */struct fb_pixmap pixmap;/* Image hardware mapper */struct fb_pixmap sprite;/* Cursor hardware mapper */struct fb_cmap cmap;/* Current cmap */struct list_head modelist;/* mode list */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 */int class_flag;/* private sysfs flags */#ifdef CONFIG_FB_TILEBLITTINGstruct fb_tile_ops *tileops; /* Tile Blitting */ #endifchar __iomem *screen_base; /* Virtual address */unsigned long screen_size; /* Amount of ioremapped VRAM or 0 */void *pseudo_palette; /* Fake palette of 16 colors */#define FBINFO_STATE_RUNNING 0#define FBINFO_STATE_SUSPENDED 1u32 state;/* Hardware state i.e suspend */void *fbcon_par;/* fbcon use-only private area *//* From here on everything is device dependent */void *par;};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 */__u32 type;/* see FB_TYPE_* */__u32 type_aux;/* Interleave for interleaved Planes */__u32 visual;/* see FB_VISUAL_* */__u16 xpanstep;/* zero if no hardware panning */__u16 ypanstep;/* zero if no hardware panning */__u16 ywrapstep;/* zero if no hardware ywrap */__u32 line_length;/* length of a line in bytes */unsigned long mmio_start;/* Start of Memory Mapped I/O *//* (physical address) */__u32 mmio_len;/* Length of Memory Mapped I/O */__u32 accel;/* Indicate to driver which *//* specific chip/card we have */__u16 reserved[3];/* Reserved for future compatibility */};struct fb_var_screeninfo {__u32 xres;/* visible resolution */__u32 yres;__u32 xres_virtual;/* virtual resolution */__u32 yres_virtual;__u32 xoffset; /* offset from virtual to visible */__u32 yoffset; /* resolution */__u32 bits_per_pixel;/* guess what */__u32 grayscale;/* != 0 Graylevels instead of colors */ struct fb_bitfield red;/* bitfield in fb mem if true color, */ struct fb_bitfield green;/* else only length is significant */struct fb_bitfield blue;struct fb_bitfield transp;/* transparency */__u32 nonstd; /* != 0 Non standard pixel format */__u32 activate; /* see FB_ACTIVATE_* */__u32 height; /* height of picture in mm */__u32 width; /* width of picture in mm */__u32 accel_flags;/* (OBSOLETE) see fb_info.flags */__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 upper_margin;/* time from sync to picture */__u32 lower_margin;__u32 hsync_len;/* length of horizontal sync */__u32 vsync_len;/* length of vertical sync */__u32 sync;/* see FB_SYNC_* */__u32 vmode;/* see FB_VMODE_* */__u32 rotate; /* angle we rotate counter clockwise */ __u32 reserved[5];/* Reserved for future compatibility */ };4.3寸LCD芯片手册TFT屏垂直方向时间参数图解:S3C2440手册TFT屏垂直方向时间参数图解:4.3寸LCD芯片手册TFT屏水平方向时间参数图解:S3C2440手册LCDTFT屏水平方向时间参数图解:#include <linux/module.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/mm.h>#include <linux/slab.h>#include <linux/delay.h>#include <linux/fb.h>#include <linux/init.h>#include <linux/dma-mapping.h>#include <linux/interrupt.h>#include <linux/workqueue.h>#include <linux/wait.h>#include <linux/platform_device.h>#include <linux/clk.h>#include <asm/io.h>#include <asm/uaccess.h>#include <asm/div64.h>#include <asm/mach/map.h>#include <asm/arch/regs-lcd.h>#include <asm/arch/regs-gpio.h>#include <asm/arch/fb.h>/** 设置调色板* 调色板说白了,就是在内存中建一个表,而每个像素* 对应的8位数据是用来在表中查找相应的RGB的值,而* 这个表是有前面的24BPP或16BPP构成的**/static int s3c_lcdfb_setcolreg(unsigned int regno,unsigned int red,unsigned int green,unsigned int blue,unsigned int transp,struct fb_info *info); struct lcd_regs {unsigned long lcdcon1;unsigned long lcdcon2;unsigned long lcdcon3;unsigned long lcdcon4;unsigned long lcdcon5;unsigned long lcdsaddr1;unsigned long lcdsaddr2;unsigned long lcdsaddr3;unsigned long redlut;unsigned long greenlut;unsigned long bluelut;unsigned long reserved[9];unsigned long dithmode;unsigned long tpal;unsigned long lcdintpnd;unsigned long lcdsrcpnd;unsigned long lcdintmsk;unsigned long lpcsel;};/* 对显存的操作 */static struct fb_ops s3c_lcdfb_ops ={.owner = THIS_MODULE,.fb_setcolreg = s3c_lcdfb_setcolreg,.fb_fillrect = cfb_fillrect,/* 填充矩形 */.fb_copyarea = cfb_copyarea,/* 拷贝区域 */.fb_imageblit = cfb_imageblit,/* */};static struct fb_info *s3c_lcd;static volatile unsigned long*gpbcon;static volatile unsigned long*gpbdat;static volatile unsigned long*gpccon;static volatile unsigned long*gpdcon;static volatile unsigned long*gpgcon;static volatile struct lcd_regs* lcd_regs;static u32 pseudo_palette[16];/* from pxafb.c */static inline unsigned int chan_to_field(unsigned int chan, struct fb_bitfield *bf){chan &=0xffff;chan >>=16- bf->length;return chan << bf->offset;}static int s3c_lcdfb_setcolreg(unsigned int regno,unsigned int red,unsigned int green,unsigned int blue,unsigned int transp,struct fb_info *info) {unsigned int val;if(regno >16)return1;/* 用red,green,blue三原色构造出val */val = chan_to_field(red,&info->var.red);val |= chan_to_field(green,&info->var.green);val |= chan_to_field(blue,&info->var.blue);//((u32 *)(info->pseudo_palette))[regno] = val;pseudo_palette[regno]= val;return0;}static int lcd_init(void){/* 1. 分配一个fb_info *//* 原型: struct fb_info *framebuffer_alloc(size_t size, struct device *dev)* 其中的size表示大小,内核在分配结构体的同时会额外的分配一些内存空间原来* 分配的空间中有一个指针,指向这个额外的内存空间,里面存放私有数据。
MicrosoftWord-Linux的LCD驱动分析(四)Linux 的 LCD 驱动分析(四)四、s3c2410fb_ops 变量详解在上面的文字中,较为详细的解释了platform device 相关的代码,通过上面的代码的执行,一个 platform 设备(framebuffer 被当作了 platform 设备)就加载到内核中去了。
就像一个 PCI 的网卡被加入到内核一样,不同的是 PCI 的网卡占用的是 PCI 总线,内核会直接支同 PCI 而对于 platform 设备需要用上面软件的方法加载到内核,持它。
网卡一样,设备需要驱动程序,刚才只是将 platform 设备注册到内核中,现在它还需要驱动程序,本节中就来看看这些驱动。
4.1 static struct fb_ops s3c2410fb_ops对于 s3c2410 的 framebuffer 驱动支持的操作主要有s3c2410fb_ops 变量中定义,该变量类型为 struct fb_ops,该类型的定义在 include/linux/fb.h 文件中。
下面看看对于 s3c2410 的驱动为该 framebuffer 提供了哪些操作。
static struct fb_ops s3c2410fb_ops = {.owner = THIS_MODULE,.fb_check_var = s3c2410fb_check_var,.fb_set_par = s3c2410fb_set_par,.fb_blank = s3c2410fb_blank,.fb_setcolreg = s3c2410fb_setcolreg,.fb_fillrect = cfb_fillrect,.fb_copyarea = cfb_copyarea,.fb_imageblit = cfb_imageblit,};上面的代码描述了支持的相关操作,下面主要会解释s3c2410****的函数,从.fb_fillrect 开始的三个函数将不会被提及,当然也可以去看看它们的行为是什么。
嵌入式linux中的lcd驅動分析作者:傑洲村的木棉學校:廣東工業大學QQ:568109894在嵌入式linux中,lcd和觸控式螢幕驅動都是字元驅動,採用“檔層-驅動層”的介面方式,本文檔中分析的lcd驅動是針對linux2.6.13內核的,本人用的開發板是qq2440,lcd是三星的LTV3500V(帶觸控式螢幕的),具體分析的文件:是"include/linux/fb.h","drivers/video/s3c2410fb.h","drivers/video/s3c2410fb.c","drivers/video/fbmem.c","/include/asm/arch- s3c2410.fb.h(些標頭檔是針對s3c2440或s3c2410晶片的)",“/home/linux/5/kernel-2.6.13/arch/arm/mach-s3c2410/mach-smdk2410.c"(驅動移植主要就是要修改這個檔,配置一些參數)。
詳細看一下LCD的驅動,實際上,幾乎lcd設備驅動所要做的所有事情就是填充fb_info結構然後向系統註冊或登出它(1)fb.h包含了framebuffer所用到的結構(2)fbmem.c處於Framebuffer設備驅動技術的中心位置.它為上層應用程式提供系統調用也為下一層的特定硬體驅動提供介面;那些底層硬體驅動需要用到這兒的介面來向系統內核註冊它們自己. fbmem.c 為所有支援FrameBuffer的設備驅動提供了通用的介面,避免重復工作.(3)s3c2410fb.c就是特定硬體驅動(針對s3c2410晶片的),fbmem.c就是溝通應用層跟s3c2410fb.c的橋樑FrameBuffer設備驅動基於如下幾個檔:1)include/linux/fb.h2)drivers/video/fbmem.c3)drivers/video/s3c2410fb.c4)drivers/video/s3c2410fb.h5)include/asm/arch-s3c2410/fb.h現在先來分析這兩個檔:1.fb.h 包含了framebuffer 所用到的結構1)fb_fix_screeninfo 描述顯示卡的屬性,並且系統運行時不能被修改 structfb_fix_screeninfo {char id[16];unsigned long smem_start;/* identification string eg "TT Builtin" */ /* Start of frame buffer mem *//* (physical address) */__u32 smem_len;/* Length of frame buffer mem */__u32 type;__u32 type_aux;/* see FB_TYPE_* *//* Interleave for interleaved Planes */__u32 visual;/* see FB_VISUAL_* */ __u16 xpanstep;/* zero if no hardware panning */__u16 ypanstep;__u16 ywrapstep; __u32 line_length;/* zero if no hardware panning */ /* zero if no hardware ywrap */ /* length of a line in bytes */unsigned long mmio_start;/* Start of Memory Mapped I/O *//* (physical address) */__u32 mmio_len; __u32 accel;/* Length of Memory Mapped I/O *//* Indicate to driver which */ /* specific chip/card we have */};__u16 reserved[3];/* Reserved for future compatibility */2)fb_var_screeninfo 這個結構描述了顯示卡的特性struct fb_var_screeninfo {__u32 xres;__u32 yres;__u32 xres_virtual;/* visible resolution/* virtual resolution*/*/__u32 yres_virtual;__u32 xoffset; /* offset from virtual to visible */ __u32 yoffset;/* resolution*/__u32 bits_per_pixel; __u32 grayscale;/* guess what/* != 0 Graylevels instead of colors */*/struct fb_bitfield red; /* bitfield in fb mem if true color, */struct fb_bitfield green; /* else only length is significant */struct fb_bitfield blue;struct fb_bitfield transp; /* transparency */__u32 nonstd; /* != 0 Non standard pixel format */ __u32 activate;/* see FB_ACTIVATE_**/__u32 height; __u32 width;/* height of picture in mm/* width of picture in mm*/*/__u32 accel_flags; /* (OBSOLETE) see fb_info.flags *//* Timing: All values in pixclocks, except pixclock (of course) */__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 upper_margin; /* time from sync to picture */__u32 lower_margin;__u32 hsync_len; /* length of horizontal sync */__u32 vsync_len; /* length of vertical sync*/__u32 sync; /* see FB_SYNC_* */__u32 vmode; /* see FB_VMODE_* */__u32 rotate; /* angle we rotate counter clockwise */__u32 reserved[5]; /* Reserved for future compatibility */};3)fb_cmap描述設備無關的顏色映射資訊。
美的集团制冷事业本部企业标准QJ/MK03.056-2004 LCD液晶显示驱动程序设计指引1适用范围《LCD液晶显示驱动程序设计指引》主要对采用液晶驱动芯片HD1621(或此系列芯片)进行LCD 液晶的驱动方法进行了分析,说明了驱动芯片的功能、软件编制方法和注意事项,并提供了程序范例,为以后的程序设计者提供类似的开发参考。
2引用资料范例程序采用日本NEC公司的RA78K0S系列汇编语言编写,具体技术资料参照78K0S系列八位单片机UPD78F9177芯片的相关资料。
液晶驱动芯片参考资料:具体见HT1621DATASHEET。
3定义汇编语言:是用于编写微处理器软件的最基本编程语言。
汇编程序包:是一组程序的总称,用于把汇编语言的源程序文件转换成机器代码的程序,通常包括汇编程序﹑连接程序﹑目标码转换程序和其它库管理程序﹑表转换程序等。
LCD:液晶显示器简称。
4HT162X驱动芯片资料介绍4.1概述HT162X系列芯片是由HOTEK公司开发生产的多功能LCD 驱动器芯片,HT162X 的软件配置特性使其适合于各种LCD 的应用包括LCD 模块和显示子系统,主控器与HT162X通信只需要3 到4 条线。
由于采用了电容型偏置电压充电泵使得HT1620 的操作电流非常的小。
HT162X 系列包括多款产品适合不同的应用,目前广泛应用于各种液晶驱动控制上。
4.2芯片特性➢操作电压2.4V~3.3V➢LCD 电压3.6V~4.9V可调➢可选择1/2 或1/3 偏置1/2, 1/3 或1/4 占空比➢内部时基频率源➢片内电容型偏置充电泵➢读/写地址自动增加➢3线(或4线)串行接口➢软件配置特性➢两个可选的蜂鸣器频率2KHz 或4KHz4.3HT162X系列芯片选型表片内振荡器-√√-√√√晶体振荡器√√-√√√√5HT1621芯片说明HT1621为32*4位LCD驱动器,共有四种子型号,分别是HT1621-48SSO、HT1621B-48SSOP/DIP、HT1621D-28SKDIP,我们现在使用的为HT1621B-48SSOP,以下就以此芯片为例进行说明。
基于STM32单片机FSMC接口驱动LCD的配置与分析STM32单片机的FSMC(Flexible Static Memory Controller)接口是一种灵活的静态存储器控制器,可以用于连接外部存储器设备,如LCD显示屏。
本文将对基于STM32单片机FSMC接口驱动LCD的配置与分析进行详细介绍。
首先,我们需要了解FSMC接口的基本原理和功能。
FSMC接口是一种高性能、低功耗的外部总线接口,可以连接到SRAM、PSRAM、NOR Flash、NAND Flash、LCD显示屏等外部存储器设备。
FSMC接口提供了多种数据传输模式(如并行、串行)和多种数据总线宽度选择,以满足不同应用的需求。
要实现FSMC接口驱动LCD,首先需要配置FSMC接口的相关寄存器。
在STM32单片机中,FSMC的配置主要包括以下几个方面:1.时序配置:通过设置FSMC_RCC和FSMC_BTR寄存器来定义访问存储器的时序。
时序配置非常重要,需要根据外部存储器的时序规格进行调整,以确保数据的正确传输。
2.地址配置:通过设置FSMC_BANK1或FSMC_BANK2寄存器来定义存储器的基地址和各种地址范围。
3.数据总线配置:根据外部存储器的数据宽度,设置FSMC_BCR和FSMC_BWTR寄存器来选择数据总线宽度(比特数)。
4.控制信号配置:通过设置FSMC_BCR、FSMC_BTR和FSMC_BWTR寄存器来配置控制信号,如写使能信号、读使能信号、片选信号等。
配置完成后,就可以使用FSMC接口进行数据的读写操作。
读取操作可以通过读取FSMC_BANK1或FSMC_BANK2的数据寄存器来实现。
写入操作可以通过写入FSMC_BANK1或FSMC_BANK2的数据寄存器来实现。
对于LCD显示屏的驱动,可以通过FSMC接口的并行模式来实现。
在并行模式下,数据总线的宽度由FSMC_BCR和FSMC_BWTR寄存器的设置决定,可以通过并行总线同时传输多个像素数据和控制信号,从而提高数据传输速度。
Linux-2.6.20的LCD驱动分析(二).1 驱动的入口点摆在面前的第一个问题相信应该是,这个函数是从那里开始运行的。
这里就应该从long long ago 开始了,打开drivers/video/s3c2410fb.c文件,然后找到s3c2410fb_init函数,先不管它里面是怎么回事,再把目光下移就会看到这样一串字符串module_init(s3c2410fb_init),郁闷,这和S3C2410fb_probe有啥关系嘛?这个问题问的好!不要着急慢慢往下面走。
先摸摸module_init是何方神圣再说,于是乎我就登陆了http://lxr.linux.no/linux+v2.6.20/网站,在上面一搜,原来module_init老家在include/linux/init.h,原来它居然还有两重身份,其原型如下:#ifndef MODULE……#define module_init(x) __initcall(x); ①……#else……#define module_init(initfn) \ ②static inline initcall_t __inittest(void) \{ return initfn; } \int init_module(void) __attribute__((alias(#c)));……#endif从上面可以看出,module_init到底用哪个,就取决于MODULE了,那么MODULE的作用是什么呢?我们知道Linux可以将设备当作模块动态加进内核,也可以直接编译进内核,说到这里大概有点明白MODULE的作用了,不错!它就是要控制一个驱动加入内核的方式。
定义了MODULE就表示将设备当作模块动态加入。
所以上面的①表示将设备加进内核。
在②中的__attribute__((alias(#initfn)))很有意思,这代表什么呢?主要alias就是属性的意思,它的英文意思是别名,可以在/infocenter/lnxpcomp/v8v101/index.jsp?topic=/com.ibm.xlcpp8l.doc/language/ ref/fn_attrib_alias.htm找到它的详细说明,这里简单的说int init_module(void)__attribute__((alias(#initfn)));的意思为init_module是initfn的别名,或者init_module是initfn的一个连接,再简单一点说这个时候module_init宏基因突变成了init_module()了。
linux中LCD设备驱动(1)——framebuffer(帧缓冲)1、framebuffer 帧缓冲帧缓冲(framebuffer)是Linux 系统为显示设备提供的一个接口,它将显示缓冲区抽象,屏蔽图像硬件的底层差异,允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作。
用户不必关心物理显示缓冲区的具体位置及存放方式,这些都由帧缓冲设备驱动本身来完成。
framebuffer机制模仿显卡的功能,将显卡硬件结构抽象为一系列的数据结构,可以通过framebuffer的读写直接对显存进行操作。
用户可以将framebuffer 看成是显存的一个映像,将其映射到进程空间后,就可以直接进行读写操作,写操作会直接反映在屏幕上。
framebuffer是个字符设备,主设备号为29,对应于/dev/fb%d 设备文件。
通常,使用如下方式(前面的数字表示次设备号)0 = /dev/fb0 第一个fb 设备1 = /dev/fb1 第二个fb 设备fb 也是一种普通的内存设备,可以读写其内容。
例如,屏幕抓屏:cp/dev/fb0 myfilefb 虽然可以像内存设备(/dev/mem)一样,对其read,write,seek 以及mmap。
但区别在于fb 使用的不是整个内存区,而是显存部分。
2、fb与应用程序的交互对于用户程序而言,它和其他的设备并没有什么区别,用户可以把fb看成是一块内存,既可以向内存中写数据,也可以读数据。
fb的显示缓冲区位于内核空间,应用程序可以把此空间映射到自己的用户空间,在进行操作。
在应用程序中,操作/dev/fbn的一般步骤如下:(1)打开/dev/fbn设备文件。
(2)用ioctl()操作取得当前显示屏幕的参数,如屏幕分辨率、每个像素点的比特数。
根据屏幕参数可计算屏幕缓冲区的大小。
(3)用mmap()函数,将屏幕缓冲区映射到用户空间。
(4)映射后就可以直接读/写屏幕缓冲区,进行绘图和图片显示了。
LCD驱动调试中部分常见问题的分析及解决办法LCD点不亮——无法正确完成初始化:LCD点不亮问题的原因有很多,但出现这个问题后,首先应该判断LCD是否正确完成初始化。
最简单的判断方法就是测量LCM的FPC 上的电容两端电压。
(具体的值可以和模组供应商沟通)如果经过上一步,检测出没有正确完成初始化,接下来首先和模组、IC一起确认初始化代码是否有问题。
确认好代码以后还是点不亮,说明是模组无法进行初始化,而不是初始化出错。
重新理一遍流程:上电->初始化。
上电这个步骤一般不会有问题,如果没有遵循正确的上电时序和RESET的流程的话也比较好排查。
那么还能存在哪些问题呢?在上电成功以后,BB会通过LCD串行总线发送LCD的初始化数据,如果这个环节出现问题,那肯定初始化不能成功。
在这个过程中能出现问题的就只有SPI 的通讯控制这一块了,(通常LCD的通讯接口有CPU和串行总线接口等,手机中较常用的就是串行总线接口,串行总线接口又以SPI接口居多),其实造成SPI通讯不符合LCD模组驱动芯片的要求的原因也是多种多样的:1、虽然都是SPI接口,但是,不同的LCD模组,在控制信号的要求上往往都会有细小的不同,有时候,CPU的SPI接口甚至都无法产生LCD模组所要求的特定波形时序。
有些LCD模组可能还会有特定的势能信号来控制SPI接口工作与否。
2、多数LCD驱动芯片其实都是具有读取寄存器和ID号的功能的,但是很多模组在封装的时候往往没有吧芯片的SPI接口的SDO信号线引出来。
导致无法通过读取寄存器和ID的方式来判断SPI总线上的通信协议是否正确。
那么,如果确定了是SPI通讯控制不满足要求的话,就可以通过修改SPI的读写控制来适配LCD模组IC的要求。
如果CPU所提供SPI接口实在没有办法配置到完全和LCD模组要求的时序波形相同,可以采用CPIO口模拟SPI信号的方式来初始化LCD。
最后,如果模组能够将SDO引出就尽量引出,不仅方便调试,而且可以很方便的做不同IC的LCD自适应的兼容。
LCD驱动程序开发指南LCD(液晶显示器)是一种常见的显示设备,广泛应用于电子产品中。
开发LCD驱动程序是实现LCD显示的重要环节。
本文将对LCD驱动程序的开发进行指南。
首先,开发LCD驱动程序前需要了解LCD的基本原理和特性。
LCD主要由像素阵列、控制芯片和背光源组成。
像素阵列是由许多小点组成的,每个小点称为像素。
控制芯片负责控制像素点的显示和刷新。
背光源提供背光亮度和显示效果。
在开发LCD驱动程序时,需要先选择适合的开发板和LCD控制芯片。
开发板上的LCD接口和控制芯片的接口需要匹配。
然后需要了解LCD控制芯片的规格和技术手册,包括寄存器的功能和操作方式等。
接下来,需初始化LCD控制芯片。
初始化的目的是设置LCD控制芯片的工作模式和参数。
通常包括设置像素点的个数和位深度、设置显示模式和刷新率等。
初始化还需要设置LCD的工作电压和背光源的亮度。
初始化的具体步骤可以参考LCD控制芯片的技术手册。
然后,需编写LCD控制代码。
这部分工作需要根据LCD控制芯片的通讯协议和接口规范进行。
常见的通讯协议有RGB接口、I2C总线和SPI总线等。
根据协议进行通讯后,可以发送命令和数据到LCD控制芯片,以实现显示和刷新。
具体的代码编写要根据具体的开发板和控制芯片进行,可以参考控制芯片的技术手册和示例代码。
另外,需编写LCD驱动程序的测试代码。
测试代码可以验证LCD驱动程序的功能和正确性。
可以通过显示图像、文本和图形等方式进行测试。
测试代码应涵盖各种显示模式和刷新率,以保证LCD驱动程序的稳定性和可靠性。
最后,需进行调试和优化。
调试主要是针对LCD显示不正常或显示效果不理想的问题。
可以通过查看LCD控制芯片的寄存器状态和输出信号等,确定问题的原因和解决方案。
优化可以提高LCD驱动程序的性能和效率,例如采用硬件加速或优化算法等。
综上所述,开发LCD驱动程序需要了解LCD的基本原理和特性,选择适合的开发板和LCD控制芯片,进行初始化和编写控制代码,编写测试代码,进行调试和优化。
液晶显示器LCD12864驱动程序#include<msp430g2553.h>#include "lcd12864.h"#include "typedef.h"#define cyCS BIT0 //P2.0,片选信号#define cySID BIT1 //P2.1,串行数据#define cyCLK BIT2 //P2.2,同步时钟#define cyPORT P2OUT#define cyDDR P2DIRvoid Write_8bits(u8 W_bits){u8 i;cyDDR |= cyCLK + cySID; //设置输出方向for(i = 0; i < 8; i++){if(( W_bits << i )&0x80){cyPORT |= cySID;}else{cyPORT &= ~cySID;}delay_ms(1);cyPORT |= cyCLK;delay_ms(1);delay_ms(1);cyPORT &= ~cyCLK;}}void w_1byte(u8 RS, u8 w_data){u8 H_Data,L_Data;u8 tmp_Data = 0xf8;cyDDR |= cyCS; //设置CS口为输出if(RS == 0) tmp_Data &= ~0x02;else tmp_Data |= 0x02;H_Data = w_data; //高位数据H_Data &= 0xf0;L_Data = w_data; //低位数据L_Data &= 0x0f;L_Data <<= 4;cyPORT |= cyCS;Write_8bits(tmp_Data);Write_8bits(H_Data);Write_8bits(L_Data);cyPORT &= ~cyCS;}void init_Lcd(void){cyDDR |= cyCLK + cySID + cyCS; //相应的位端口设置为输出delay_ms(10); //延时等待液晶完成复位w_1byte(0,0x30);delay_ms(1);w_1byte(0,0x02);delay_ms(5);w_1byte(0,0x0c);delay_ms(1);w_1byte(0,0x01);delay_ms(5);w_1byte(0,0x06);delay_ms(1);}//清屏void clear_lcd(void){delay_ms(1);w_1byte(0,0x01);delay_ms(5);}void lcd_pos(u8 x,u8 y)//定位{u8 pos;switch(x){case 1:pos=0x80;break;case 2:pos=0x90;break;case 3:pos=0x88;break;case 4:pos=0x98;break;default:pos=0x80;}pos += y;w_1byte(0,pos);}//显示汉字void Disp_HZ(const u8 * pt,u8 num){u8 i;for(i = 0;i < num*2;i++){w_1byte(1,*(pt++));}}//显示字符void Disp_Ch(const u8 ch){w_1byte(1, ch);}//汉字和字符混合显示void disp_lcd_str(u8 x, u8 y, const u8 *str, u8 len) {u8 i;lcd_pos(x, y);for(i = 0;i < len && *str; ){if(*(str) >= 0x80){w_1byte(1,*(str++));w_1byte(1,*(str++));i++;i++;}else{w_1byte(1,*(str++));i++;}}}。
LCD 驱动开发指引 1、 LCD 驱动概述LCD 驱动程序调试,是整个手机研发过程中非常重要的一个环节,在每个新的机型开发的初期,最先都要调试 LCD 驱动程序,我们俗称“点屏” 。
“点屏”的调试包括两个部分, 一是点亮 LCD 的背光, 二是调试 LCD 显示。
背光驱动调试的方法与技巧, 会在背光文档中叙述,暂不在这篇文档里讨论,本文将重点讨论 LCD 的电路原理、驱动程序分析、 LCD 驱动调试经验总结和具体驱动调试案例的分析。
2、 LCD 原理及电路分析相关概念:LCD :全称是 Liquid Crystal Display 液晶显示屏LCM :全称是 Liquid Crystal Module指的是液晶显术模块,包括液晶屏及液晶的外围 FPC 电路和结构件。
LCD 的 FPC 电路:指 LCM 模块中的液晶外围电路,这部分电路由 LCD 模组厂家按照我们对 LCD 的接口要求进行设计的。
在 LCD 驱动调试中,看 FPC 电路图也是很重要的一个环节。
LCD 外围电路:我们通常也简称为 LCD 电路,指的是 baseband 端的 LCD 接口电路部分,这部分电路由我们自行设计。
LCD 模组厂家:指信利,天马,京东方这些厂家。
他们将 LCD 制作成可以供我们生产使用的 LCM 模组。
2.1LCD 芯片介绍目前手机使用的大部分显示器件都是 LCD (Liguid Crystal Display器件,目前康佳使用的 LCM 模块由信利、京东方、天马、凌达这几家厂商供货。
但是 LCM 生产厂家对我们调试驱动并没有任何关系,我们需要了解的是 LCM 所使用的 IC 型号。
因为,我们实际上是对 LCD 的 IC 进行编程, 间接控制 LCD 面板, 常用的 IC 有HD66773、 S6B33B2/ S6B33B6、 HD66777等。
LCD驱动的编程,除了要关注 IC 的型号,还要关注 LCD FPC的电路设计, LCD 外围电路设计, 基带芯片的 LCD 接口单元, 背光 IC 的控制等几个方面, 当然也包括软件的上层程序。
/*LCD.C128×64 LCD驱动程序*/#include <INTRINS.H>#include <ABSACC.H>#include "LCD.H"//定义屏幕光标(取值0~63,光标本身不可见)unsigned char LcdCursor;/*函数:LcdLightOn()功能:点亮背光灯*/void LcdLightOn(){LCD_BL = 1;}/*函数:LcdLightOff()功能:熄灭背光灯*/void LcdLightOff(){LCD_BL = 0;}/*函数:LcdGetBF()功能:读出状态位BF返回:BF=1,表示忙,不可进行任何操作BF=0,表示不忙,可以进行正常操作*/bit LcdGetBF(){unsigned char dat;dat = XBYTE[0xD002]; //XBYTE的定义见<ABSACC.H>return (bit)(dat & 0x80);}/*函数:LcdWriteCmd()功能:向LCD发送命令参数:cmd:命令字,详见器件的数据手册*/void LcdWriteCmd(unsigned char cmd){while ( LcdGetBF() );XBYTE[0xD000] = cmd;}/*函数:LcdWriteDat()功能:向LCD写入数据参数:dat,要写入的数据说明:目标地址由地址计数器AC隐含指定,写完后AC自动加1*/void LcdWriteDat(unsigned char dat){while ( LcdGetBF() );XBYTE[0xD001] = dat;}/*函数:LcdReadDat()功能:从LCD读出数据返回:读出的数据*//*unsigned char LcdReadDat(){volatile unsigned char dat;while ( LcdGetBF() );dat = XBYTE[0xD003];dat = XBYTE[0xD003]; //需要连续执行两次才能够读出真正的数据return dat;}*//*函数:LcdSetAC()功能:设置DDRAM(显示数据RAM)的AC(地址计数器)值参数:ac:地址计数器值,范围0~63*/void LcdSetAC(unsigned char ac){ac &= 0x3F;ac |= 0x80;LcdWriteCmd(ac);}/*函数:LcdClear()功能:LCD清屏,并使光标回到0*/void LcdClear(){LcdWriteCmd(0x01); //清屏命令LcdCursor = 0;}/*函数:LcdDelay()功能:延时(t*100)个机器周期*/void LcdDelay(unsigned char t){unsigned char n;do{n = 49;while ( --n != 0 );} while ( --t != 0 );}/*函数:LcdInit()功能:LCD初始化*/void LcdInit(){LcdWriteCmd(0x30); //设置基本指令集LcdDelay(3);LcdWriteCmd(0x30); //设置基本指令集(需要再执行一次)LcdDelay(1);LcdWriteCmd(0x0C); //开启显示LcdDelay(3);LcdClear(); //清屏LcdDelay(250);LcdWriteCmd(0x06); //设置进入点LcdDelay(10);}/*函数:LcdCheckAC()功能:根据光标位置调整AC*/void LcdCheckAC(){switch ( LcdCursor ){case 16:LcdSetAC(16);break;case 32:LcdSetAC(8);break;case 48:LcdSetAC(24);break;case 64:LcdCursor = 0;LcdSetAC(0);break;default:break;}/*函数:LcdPutChar()功能:显示ASCII码参数:c为可显示的ASCII码(0x20~0x7F)*/void LcdPutChar(unsigned char c){LcdWriteDat(c);LcdCursor++;LcdCheckAC();}/*函数:LcdPutHZ()功能:显示汉字参数:ch,cl:汉字编码*/void LcdPutHZ(unsigned char ch, unsigned char cl){if ( LcdCursor & 0x01 ){//显示汉字时,必须偶地址对准,即光标位置不能是奇数LcdPutChar(' '); //额外输出一个空格}LcdWriteDat(ch);LcdWriteDat(cl);LcdCursor += 2;LcdCheckAC();}/*函数:LcdPuts()功能:显示字符串参数:*s:要显示的字符串(可同时包含ASCII码和汉字)*/void LcdPuts(unsigned char *s){unsigned char ch, cl;for (;;){ch = *s++;if ( ch == '\0' ) break;if ( ch < 0x80 ){LcdPutChar(ch);}else{cl = *s++;LcdPutHZ(ch,cl);}}}。
//****************************************************** *//* 2007.6.18//****************************************************** *在/kernel/include/asm-arm/arch-s3c2410/bitfield.h 文件中:#ifndef __ASSEMBLY__#define UData(Data) ((unsigned long) (Data))#else#define UData(Data) (Data)#endif例:UData(5); = 5/** MACRO: Fld** Purpose* The macro "Fld" encodes a bit field, given its size and its shift value* with respect to bit 0.** Note* A more intuitive way to encode bit fields would have been to use their* mask. However, extracting size and shift value information from a bit* field''''s mask is cumbersome and might break the assembler (255-character* line-size limit).** Input* Size Size of the bit field, in number of bits.* Shft Shift value of the bit field with respect to bit 0.** Output* Fld Encoded bit field.*/#define Fld(Size, Shft) (((Size) << 16) + (Shft))例:Fld(2,5); = 0x20005/** MACROS: FSize, FShft, FMsk, FAlnMsk, F1stBit** Purpose* The macros "FSize", "FShft", "FMsk", "FAlnMsk", and "F1stBit" return* the size, shift value, mask, aligned mask, and first bit of a* bit field.** Input* Field Encoded bit field (using the macro "Fld").** Output* FSize Size of the bit field, in number of bits.* FShft Shift value of the bit field with respectto bit 0.* FMsk Mask for the bit field.* FAlnMsk Mask for the bit field, aligned on bit 0.* F1stBit First bit of the bit field.*/#define FSize(Field) ((Field) >> 16)例:FSize(0x20005); = 2#define FShft(Field) ((Field) & 0x0000FFFF)例:FShft(0x20005); = 5/** MACRO: FInsrt** Purpose* The macro "FInsrt" inserts a value into a bit field by shifting the* former appropriately.** Input* Value Bit-field value.* Field Encoded bit field (using the macro "Fld").** Output* FInsrt Bit-field value positioned appropriately.*/#define FInsrt(Value, Field) \(UData (Value) << FShft (Field))例:FInsrt(0x3, 0x20005); = 0x3 << 0x0005 = 0x60------------------------------------------------------------------------在/kernel/include/asm-arm/arch-s3c2410/hardware.h 文件中:/** S3C2410 internal I/O mappings** We have the following mapping:* phys virt* 48000000 e8000000*/#define VIO_BASE 0xe8000000 /* virtual start of IO space */#define PIO_START 0x48000000 /* physical start of IO space */#define io_p2v(x) ((x) | 0xa0000000)#define io_v2p(x) ((x) & ~0xa0000000)# define __REG(x) io_p2v(x)# define __PREG(x) io_v2p(x)这里,在实际的寄存器操作中,都用__REG(x) 宏将物理地址转换为了虚拟地址,然后再对这些虚拟地址进行读写操作。
------------------------------------------------------------------------当应用程序对设备文件进行ioctl操作时候会调用它们。
对于fb_get_fix(),应用程序传入的是fb_fix_screeninfo结构,在函数中对其成员变量赋值,主要是smem_start(缓冲区起始地址)和smem_len(缓冲区长度),最终返回给应用程序。
在/kernel/drivers/video/s3c2410fb.c 文件中的s3c2410fb_map_video_memory 函数中:fbi->fb.fix.smem_len = fbi->max_xres * fbi->max_yres * fbi->max_bpp / 8;fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + PAGE_SIZE);fbi->map_cpu = consistent_alloc(GFP_KERNEL,fbi->map_size,&fbi->map_dma);if (fbi->map_cpu){fbi->screen_cpu = fbi->map_cpu + PAGE_SIZE;fbi->screen_dma = fbi->map_dma + PAGE_SIZE;fbi->fb.fix.smem_start = fbi->screen_dma;}在/kernel/include/asm-arm/proc-armo/page.h 文件中:/* PAGE_SHIFT determines the page size. This is configurable. */#if defined(CONFIG_PAGESIZE_16)#define PAGE_SHIFT 14 /* 16K */#else /* default */#define PAGE_SHIFT 15 /* 32K */#endif在/kernel/include/asm-arm/page.h 文件中:#define PAGE_SIZE (1UL << PAGE_SHIFT)#define PAGE_MASK (~(PAGE_SIZE-1))/* to align the pointer to the (next) page boundary */#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)在/kernel/arch/arm/mm/consistent.c 文件中:/** This allocates one page of cache-coherent memory space and returns* both the virtual and a "dma" address to that space. It is not clear* whether this could be called from an interrupt context or not. For* now, we expressly forbid it, especially as some of the stuff we do* here is not interrupt context safe.** Note that this does *not* zero the allocated area!*/void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle)这里首先计算出需要视频缓冲区的大小(LCD屏的宽度 * LCD 屏的高度 * 每像素的位数 / 每字节的位数)fbi->fb.fix.smem_len = 240*320*16/8 = 0x25800 =150K(9.375个PAGE)PAGE_SHIFT = 14PAGE_SIZE = 1<<14 = 0x4000 = 16K (1个PAGE)PAGE_MASK = 0xFFFFC000fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len +PAGE_SIZE) = PAGE_ALIGN(150K + 16K) = PAGE_ALIGN(166K) = (166K + 16K - 1) & 0xFFFFC000 = 0x2D7FF & 0xFFFFC000 = 0x2C000 =176Kconsistent_alloc(GFP_KERNEL, 176K, &fbi->map_dma);最后得到:framebuffer(物理地址)|---------------|| ... |-------|---------------| <-- fbi->map_dma| 16K |分配了 |---------------| <-- fbi->screen_dma =fbi->fb.fix.smem_start176K | |共11个 | | 160K = 10个PAGEPAGE | 160K | 可以容下所需的150K 视频缓冲区大小 (16K) | || |-------|---------------|-------| ... ||---------------|//****************************************************** *//* 2007.6.19//****************************************************** *在/kernel/drivers/video/s3c2410fb.c 文件中的s3c2410fb_activate_var 函数中:unsigned long VideoPhysicalTemp = fbi->screen_dma;这里已经得到了framebuffer 在内存中的起始地址为VideoPhysicalTemp,地址数据位为A[30:0]。