Linux驱动之LCD驱动编写

发布时间:2024-08-19  

在Linux驱动之内核自带的S3C2440的LCD驱动分析这篇博客中已经分析了编写LCD驱动的步骤,接下来就按照这个步骤来字尝试字节编写LCD驱动。用的LCD屏幕为tft屏,每个像素点为16bit。对应与红绿蓝分别为565。


1、分配一个fb_info结构

2、设置fb_info结构

3、硬件相关的操作,配置LCD时钟、配置IO端口、配置LCD寄存器。

4、最终注册fbinfo结构到registered_fb数组

 

要理解LCD的工作原理,需要了解LCD的时钟,在TFT的LCD中有如下的时钟。这个几个时钟数据在配置LCD寄存器时都说需要设置的。

1、VCLK:两个像素之间的时钟,即两个像素隔多长时间才能显示下一个像素

2、HSYNC:水平同步时钟,即第一行像素点显示完成之后隔多长时间才能开始下一行的显示

3、VSYNC:垂直方向的同步时钟,也叫帧同步信号,即一帧数据显示完成之后(一帧数据表示一个屏幕显示完成,即一个显存的数据全部取完),过多长下一帧数据才开始显示

本节需要用到的函数:


void *dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp);  //分配DMA缓存区给显存

//返回值为:申请到的DMA缓冲区的虚拟地址,若为NULL,表示分配失败,则需要使用dma_free_writecombine()释放内存,避免内存泄漏

//参数如下: 


//*dev:指针,这里填0,表示这个申请的缓冲区里没有内容


//size:分配的地址大小(字节单位)


//*handle:申请到的物理起始地址


//gfp:分配出来的内存参数,标志定义在,常用标志如下:

    //GFP_ATOMIC    用来从中断处理和进程上下文之外的其他代码中分配内存. 从不睡眠.

    //GFP_KERNEL    内核内存的正常分配. 可能睡眠.

    //GFP_USER      用来为用户空间页来分配内存; 它可能睡眠.   


分配一段DMA缓存区,分配出来的内存会禁止cache缓存(因为DMA传输不需要CPU)


它和 dma_alloc_coherent ()函数相似,不过 dma_alloc_coherent ()函数是分配出来的内存会禁止cache缓存以及禁止写入缓冲区


dma_free_writecombine(dev,size,cpu_addr,handle);   //释放缓存

//cpu_addr:虚拟地址, 

//handle:物理地址

释放DMA缓冲区, dev和size参数和上面的一样


struct fb_info *framebuffer_alloc(size_t size, struct device *dev);      //申请一个fb_info结构体,

//size:额外的内存,

//*dev:指针, 这里填0,表示这个申请的结构体里没有内容

 

int register_framebuffer(struct fb_info *fb_info);  


                      //向内核中注册fb_info结构体,若内存不够,注册失败会返回负数


int unregister_framebuffer(struct fb_info *fb_info) ;


                      //注销内核中fb_info结构体


本节需要用到的结构体:


fb_info结构体如下:


struct fb_info {

        ... ...

       struct fb_var_screeninfo var;       //可变的参数

       struct fb_fix_screeninfo fix;        //固定的参数

       ... ...

       struct fb_ops *fbops;              //操作函数

       ... ...

       char __iomem *screen_base;        //显存虚拟起始地址

       unsigned long screen_size;          //显存虚拟地址长度

  

       void *pseudo_palette;                

//假的16色调色板,里面存放了16色的数据,可以通过8bpp数据来找到调色板里面的16色颜色索引值,模拟出16色颜色来,节省内存,不需要的话就指向一个不用的数组即可

       ... ...

};


其中操作函数fb_info-> fbops 结构体写法如下:


static struct fb_ops s3c_lcdfb_ops = {

         .owner                = THIS_MODULE,


         .fb_setcolreg    = my_lcdfb_setcolreg,//设置调色板fb_info-> pseudo_palette,自己构造该函数


         .fb_fillrect      = cfb_fillrect,     //填充矩形,用/drivers/video/ cfbfillrect.c里的函数即可


         .fb_copyarea    = cfb_copyarea,  //复制数据, 用/drivers/video/cfbcopyarea.c里的函数即可


         .fb_imageblit    = cfb_imageblit, //绘画图形, 用/drivers/video/imageblit.c里的函数即可

};


固定的参数fb_info-> fix 结构体如下:


struct fb_fix_screeninfo {

       char id[16];                   //id名字

       unsigned long smem_start;  //framebuffer物理起始地址                          

       __u32 smem_len;           //framebuffer长度,字节为单位

       __u32 type;                 //lcd类型,默认值0即可

       __u32 type_aux;               //附加类型,为0

       __u32 visual;                     //画面设置,常用参数如下

// FB_VISUAL_MONO01             0   单色,0:白色,1:黑色

// FB_VISUAL_MONO10             1    单色,1:白色,0:黑色

// FB_VISUAL_TRUECOLOR          2     真彩(TFT:真彩)

// FB_VISUAL_PSEUDOCOLOR     3     伪彩

// FB_VISUAL_DIRECTCOLOR        4     直彩


    __u16 xpanstep;                /*如果没有硬件panning就赋值为0 */

    __u16 ypanstep;                /*如果没有硬件panning就赋值为0 */

    __u16 ywrapstep;                 /*如果没有硬件ywrap就赋值为0 */


    __u32 line_length;                 /*一行的字节数 ,例:(RGB565)240*320,那么这里就等于240*16/8 */


    /*以下成员都可以不需要*/

    unsigned long mmio_start;        /*内存映射IO的起始地址,用于应用层直接访问寄存器,可以不需要*/                                   

       __u32 mmio_len;                   /* 内存映射IO的长度,可以不需要*/

       __u32 accel;                 

       __u16 reserved[3];        


};


可变的参数fb_info-> var 结构体如下:


structfb_var_screeninfo{                                    

   __u32xres;                    /*可见屏幕一行有多少个像素点*/

    __u32 yres;                      /*可见屏幕一列有多少个像素点*/

    __u32 xres_virtual;         /*虚拟屏幕一行有多少个像素点 */       

    __u32  yres_virtual;       /*虚拟屏幕一列有多少个像素点*/

    __u32 xoffset;                 /*虚拟到可见屏幕之间的行偏移,若可见和虚拟的分辨率一样,就直接设为0*/

    __u32 yoffset;                 /*虚拟到可见屏幕之间的列偏移*/

    __u32  bits_per_pixel;    /*每个像素的位数即BPP,比如:RGB565则填入16*/

    __u32 grayscale;           /*非0时,指的是灰度,真彩直接填0即可*/


    struct fb_bitfield red;          //fb缓存的R位域, fb_bitfield结构体成员如下:

//__u32 offset;          区域偏移值,比如RGB565中的R,就在第11位

//__u32 length;                   区域长度,比如RGB565的R,共有5位

//__u32 msb_right;  msb_right ==0,表示数据左边最大, msb_right!=0,表示数据右边最大



    struct fb_bitfield green;    /*fb缓存的G位域*/

    struct fb_bitfield blue;       /*fb缓存的B位域*/


   /*以下参数都可以不填,默认为0*/

    struct fb_bitfield transp;   /*透明度,不需要填0即可*/    

 

    __u32nonstd;                    /* != 0表示非标准像素格式*/

    __u32 activate;                 /*设为0即可*/

    __u32height;                     /*外设高度(单位mm),一般不需要填*/

    __u32width;                      /*外设宽度(单位mm),一般不需要填*/

    __u32 accel_flags;        /*过时的参数,不需要填*/


    /* 除了pixclock本身外,其他的都以像素时钟为 单位*/ 

    __u32pixclock;                   /*像素时钟(皮秒)*/

    __u32 left_margin;         /*行切换,从同步到绘图之间的延迟*/

    __u32right_margin;        /*行切换,从绘图到同步之间的延迟*/

    __u32upper_margin;       /*帧切换,从同步到绘图之间的延迟*/

    __u32lower_margin;       /*帧切换,从绘图到同步之间的延迟*/

    __u32hsync_len;              /*水平同步的长度*/

    __u32 vsync_len;           /*垂直同步的长度*/

    __u32 sync;

    __u32 vmode;

    __u32 rotate;

    __u32reserved[5];        /*保留*/


}


1.写驱动程序:


(驱动设置:参考自带的LCD平台驱动drivers/video/s3c2410fb.c )


(LCD控制寄存器设置:参考之前的LCD裸机驱动:http://www.cnblogs.com/lifexy/p/7144890.html)


1.1 步骤如下:


在驱动init入口函数中:


1)分配一个fb_info结构体


2)设置fb_info


  2.1)设置固定的参数fb_info-> fix


  2.2) 设置可变的参数fb_info-> var


  2.3) 设置操作函数fb_info-> fbops


  2.4) 设置fb_info 其它的成员


3)设置硬件相关的操作    


  3.1)配置LCD引脚


  3.2)根据LCD手册设置LCD控制器


  3.3)分配显存(framebuffer),把地址告诉LCD控制器和fb_info


4)开启LCD,并注册fb_info: register_framebuffer()


  4.1) 直接在init函数中开启LCD(后面讲到电源管理,再来优化)


    控制LCDCON5允许PWREN信号,


    然后控制LCDCON1输出PWREN信号,


    输出GPB0高电平来开背光,


  4.2) 注册fb_info


在驱动exit出口函数中:


1)卸载内核中的fb_info


2) 控制LCDCON1关闭PWREN信号,关背光,iounmap注销地址


3)释放DMA缓存地址dma_free_writecombine()


4)释放注册的fb_info


1.2 具体代码如下:


#include

#include

#include

#include

#include         //含有iomap函数iounmap函数

#include //含有copy_from_user函数

#include //含有类相关的处理函数

#include       //含有fb_info结构体定义

//#include //含有dma_free_writecombine宏定义

#include   //含有dma_free_writecombine宏定义

#include //含有平台设备总线模型相关变量

#include

#include


//#include

//#include

//#include

//#include

//#include

//#include

//#include

//#include

//#include

//#include

//#include

//#include

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

相关文章

    前面的实验解析我们可以得知,该设计可以拆分成两个功能模块实现, LCDRGB:1.8寸串行液晶屏驱动模块。 * LCDRAM:用于存储单色图片数据。   实验原理 液晶屏介绍 查看底板上集成的1.8寸串行彩色液晶屏......
    江苏润石推出高驱动能力运算放大器RS8471; 【导读】Vcom是TFT-LCD液晶屏驱动用的信号,在屏内连接至每一个显示单位,屏的尺寸越大,Vcom的走线越长,而驱动......
    s3c2440液晶屏驱动 (内核自带) linux-4.1.24;自带有一部分驱动的配置信息,只要修改这部分就能支援 不同的液晶屏 - /arch/arm/mach-s3c24xx/mach......
    据线无法显示完全部的颜色组成,只能当做一个索引作用,指向调色板上正真的地址颜色空间   LCD液晶屏显示原理:      可以想象一下LCD后面有一个电子枪,电子枪的作用就是将从FramBuffer内存里获取到的颜色,一个......
    用范围越来越广。本文提出了一种能直接驱动数字液晶屏的设计方案,方案先介绍了TFT数字彩屏的工作原理,利用STM32处理器的FSMC接口设计的硬件电路和软件程序均能对显示控制芯片进行有效的控制。在实......
    用范围越来越广。本文提出了一种能直接驱动数字液晶屏的设计方案,方案先介绍了TFT数字彩屏的工作原理,利用STM32处理器的FSMC接口设计的硬件电路和软件程序均能对显示控制芯片进行有效的控制。在实......
    基带芯片部分电路如图5所示。         底板硬件电路   彩色液晶屏接口及触摸屏驱动电路   S3C2440A内置有液晶控制器,可以支持最大256 k色TFT彩色液晶屏、最大4 k色STN彩色液晶屏......
    为低电平后,液晶屏开始读取总线上面的数据 在RD跳变为低电平后,液晶屏开始放置数据到总线上面 本例程使用3.0寸的TFT-LCD模块,驱动芯片为R61509VN,分辨率240*400,接口为16位的80并口......
    显示的后台缓存。 2.2 μC/OS-II上的μC/GUI移植 μC/GUI的移植内容主要分成4部分:μC/GUI配置文件的参数修改,LCD驱动程序的编写,LCD触摸屏驱动程序编写,以及与μC/OS-II操作......
    ,那可以选择discovery板卡,它可以支持液晶显示,当然了,Nucleo板卡扩展一下也可以支持液晶显示,甚至用一些I/O模拟的方式也能把液晶屏驱动起来,但是......

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>