够用的硬件
能用的代码
使用的教程
(拷贝过来的代码有点乱,请下载附件查看文档)
资料下载地址:https://pan.baidu.com/s/1bHUVe6X6tymktUHk_z91cA

网络上配套STM32开发板有很多LCD例程,主要是TFT LCD跟OLED的。从这些例程,大家都能学会如何点亮一个LCD。
但是不知道有多少人会直接使用这些代码,至少我不用,不是不用,而是用不了。这代码都有下面这些问题:
1 分层不清晰,通俗讲就是模块化太差。
2 接口乱。其实只要接口不乱,分层就会好很多了。
3 可移植性差。
4 通用性差。
为什么这样说呢?如果你已经了解了LCD的操作,请思考如下情景:
1 代码空间不够,只能保留9341的驱动,其他LCD驱动全部删除。能一键(一个宏定义)删除吗?删除后要改多少地方才能编译通过?
2 有一个新产品,收银设备。系统有两个LCD,一个叫做主显示,收银员用;一个叫顾显,顾客看金额。怎么办?这些例程代码要怎么改才能支持两个屏幕?复制一套然后改函数名称?这样确实能完成任务,只不过程序从此就进入恶性循环了。
3 一个OLED,原来接在这些IO,后来改到别的IO,容易改吗?
4 原来只是支持中文,现在要卖到南美,要支持多米尼加语言,好改吗?
大家慢慢想。
 

LCD种类概述

在讨论怎么写LCD驱动之前,我们先大概了解一下嵌入式常用LCD。只是概述一些跟驱动架构设计有关的概念。至于原理跟细节,在此不做深入讨论,会有专门文章介绍,或者参考网络文档。
 

TFT lcd

TFT LCD,也就是我们常说的彩屏。
通常像素较高,例如常见的2.8寸,320X240像素。4.0寸的,像素800X400。
这些屏通常使用并口,也就是8080或6800接口(STM32 的FSMC接口);
或者是RGB接口,STM32F429等部分较贵的芯片支持。
其他例如手机上使用的有MIPI接口。
也有一些支持SPI接口的,不过除非是比较小的屏幕,否则不建议使用SPI接口,速度慢,刷屏闪屏。
玩STM32常用的TFT lcd屏幕驱动IC通常有:ILI9341/ILI9325等。
下图是2.8寸 TFT LCD,表面带电阻触摸屏

下图为4.0寸 IPS LCD,表面带电容触摸屏
 

COG lcd

很多人可能不知道COG LCD是什么,我觉得跟现在开发板销售方向有关系,大家都出大屏,玩酷炫界面,对于更深的技术,例如软件架构设计,都不涉及。
使用单片机的产品,COG LCD其实占比非常大。
所谓的COG LCD,
COG是Chip On Glass的缩写,就是驱动芯片直接绑定在玻璃上,透明的。
实物像下图:

这种LCD通常像素不高,常用的有128X64,128X32。
一般只支持黑白显示,也有灰度屏,我没怎么用过。
接口通常是SPI,I2C。也有号称支持8位并口的,不过基本不会用,3根IO能解决的问题,没必要用8根吧?
常用的驱动IC:STR7565。
 

OLED lcd

买过开发板的应该基本用过。新技术,大家都感觉高档,在手环等产品常用。OLED目前屏幕较小,大一点的都很贵。
在控制上跟COG LCD类似,区别是两者的显示方式不一样。从我们程序角度来看,最大的差别就是,OLED LCD,不用控制背光。。。。。
实物如下图,

常见的是SPI跟I2C接口。
常见驱动IC:STR7565。
 

硬件场景

接下来的讨论,都基于以下硬件信息:
1 有一个TFT屏幕,接在硬件的FSMC接口,什么型号屏幕?不知道。
2 有一个COG lcd,接在几根IO口上,驱动IC是STR7565,128X32像素。
3 有一个COG LCD,接在硬件SPI3跟几根IO口上,驱动IC是STR7565,128x64像素。
4 有一个OLED LCD,接在SPI3上,使用CS2控制片选,驱动IC是SSD1315。
 

预备知识

在进入讨论之前,我们先大概说一下下面几个概念,对于这些概念,如果你想深入了解,请GOOGLE。
 

面向对象

面向对象,是编程界的一个概念,常在C++中出现。
什么叫面向对象呢?
编程有两种要素:程序(方法),数据(属性)。
例如:一个LED,我们可以点亮或者熄灭它,这叫方法。
LED什么状态?亮还是灭?这就是属性。
我们通常这样编程:
 

u8 ledsta = 0;void ledset(u8 sta)
{

}

这样的编程有一个问题,假如我们有10个这样的LED,怎么写?
这时我们可以引入面向对象编程,将每一个LED封装为一个对象。可以这样做:
 

/*定义一个结构体,将LED这个对象的属性跟方法封装。这个结构体就是一个对象。
但是这个不是一个真实的存在,而是一个对象的抽象。*/
typedef struct{   
     u8 sta;    
     void (*setsta)(u8 sta);
}LedObj;

/*    
声明一个LED对象,名称叫做LED1,    
并且实现它的方法drv_led1_setsta
*/
void drv_led1_setsta(u8 sta)
{
}

LedObj LED1={        
    .sta = 0,        
    .setsta = drv_led1_setsta,    
    };

/*    
声明一个LED对象,名称叫做LED2,    
并且实现它的方法drv_led2_setsta*/
void drv_led2_setsta(u8 sta)
{
}
LedObj LED2={       
     .sta = 0,        
    .setsta = drv_led2_setsta,    
    };
/*    
操作LED的函数,参数指定哪个led*/
void ledset(LedObj *led, u8 sta)
{    
     led->setsta(sta);
}

抛砖引玉,很多地方不正确,但是不想展开,大家自己搜索资料学习。
 
是的,在C语言中,实现面向对象的手段就是结构体的使用。
上面的代码,对于API来说,就很友好了。
操作所有LED,使用同一个接口,只需告诉接口哪个LED。
大家想想,前面说的LCD硬件场景。
4个LCD,如果不面向对象,显示汉字的接口是不是要实现4个?每个屏幕一个?
 

驱动与设备分离

如果要深入了解驱动与设备分离,请看LINUX驱动的书籍。
什么是设备?
我认为的设备就是属性,就是参数,就是驱动程序要用到的数据和接口。
那么驱动就是控制这些数据和接口的代码过程。通常来说,如果LCD的驱动IC相同,就用相同的驱动。有些不同的IC也可以用相同的,例如SSD1315跟STR7565,除了初始化,其他都可以用相同的驱动。
例如一个COG lcd:
驱动IC是STR7565
128*64像素
用SPI3
背光用PF5
命令线用PF4
复位脚用PF3
上面所有的信息综合,就是一个设备。
驱动就是STR7565的驱动。
为什么要驱动跟设备分离,因为要解决下面问题:
2 有一个新产品,收银设备,系统有两个LCD,一个叫做主显示,收银员用,一个叫顾显,顾客看金额使用。怎么办?这些例程代码要怎么改才能支持两个屏幕?复制一套然后改函数名称?这样确实能完成任务,只不过程序从此就进入恶性循环了。
这个问题,两个设备用同一套程序控制才是最好的解决办法。
驱动与设备分离的手段:
在驱动程序接口中增加设备参数,驱动用到的所有资源从设备参数传入。
驱动如何跟设备绑定呢?通过设备的驱动IC型号。
 

模块化

我认为模块化就是将一段程序封装,提供接口,给不同的驱动使用。
不模块化就是,在不同的驱动中都实现这段程序。
例如字库处理,在显示汉字的时候,我们要找点阵,在打印机打印汉字的时候,我们也要找点阵,你觉得程序要怎么写?
把点阵处理做成一个模块,就是模块化。
非模块化的典型特征就是一根线串到底,没有任何层次感。
 

LCD到底是什么

前面我们说了面向对象,想要对LCD进行抽象,得出一个对象,就需要知道LCD到底是什么。
我们问自己下面几个问题:
1 LCD能做什么?
2 要LCD做什么?
3 谁想要LCD做什么?
刚刚接触嵌入式的朋友可能不是很了解,可能会想不通。我们模拟一下LCD的功能操作数据流。
APP想要像是一个汉字。
1 首先,需要一个像是汉字的接口,APP调用这个接口就可以显示汉字了。假设接口叫做lcd_display_hz。
2 汉字从哪来?从点阵字库来,所以在lcd_display_hz函数内就要调用一个叫做find_font的函数获取点阵。
3 获取点阵后要将点阵显示到LCD上,那么我们调用一个ILL9341_dis的接口,将点阵刷新到驱动IC型号为ILI9341的LCD上。
4 ILI9341_dis怎么将点阵显示上去?调用一个8080_WRITE的接口。
好的,这个就是大概过程,我们从这个过程去抽象LCD功能接口。
汉字跟LCD对象有关吗?无关。在LCD眼里,无论汉字还是图片,都是一个个点。
那么前面问题的答案就是:
1 LCD可以一个点一个点显示内容。
2 要LCD显示汉字或图片-----转化后就是显示一堆点
3 APP想要LCD显示图片或问题。
结论就是:
所有LCD对象的功能就是显示点。
那么驱动只要提供显示点的接口就可以了,显示一个点,显示一片点。
抽象接口如下:
 

/*    LCD驱动定义*/
typedef struct  
{    
u16 id;   
s32 (*init)(DevLcd *lcd);    
s32 (*draw_point)(DevLcd *lcd, u16 x, u16 y, u16 color);    
s32 (*color_fill)(DevLcd *lcd, u16 sx,u16 ex,u16 sy,u16 ey, u16 color);    
s32 (*fill)(DevLcd *lcd, u16 sx,u16 ex,u16 sy,u16 ey,u16 *color);    
s32 (*onoff)(DevLcd *lcd, u8 sta);    
s32 (*prepare_display)(DevLcd *lcd, u16 sx, u16 ex, u16 sy, u16 ey);    
void (*set_dir)(DevLcd *lcd, u8 scan_dir);    
void (*backlight)(DevLcd *lcd, u8 sta);
}_lcd_drv;

上面的接口,也就是对应的驱动,包含了一个驱动id号。
1 id,驱动型号
2 初始化
3 画点
4 将一片区域的点显示某种颜色
5 将一片区域的点显示某些颜色
6 显示开关
7 准备刷新区域(主要彩屏直接DMA刷屏使用)
8 设置扫描方向
9 背光控制
 

LCD驱动框架

我们设计了如下的驱动框架

设计思想
1 中间显示驱动IC驱动程序提供统一接口,接口形式如前面说的_lcd_drv结构体。
2 各显示IC驱动根据设备参数,调用不同的接口驱动。例如TFT就用8080驱动,其他的都用SPI驱动。
SPI驱动只有一份,用IO口控制的我们也做成模拟SPI。
3 LCD驱动层做LCD管理,例如完成TFT LCD的识别。并且将所有LCD接口封装为一套接口。
4 简易GUI层封装了一些显示函数,例如划线、字符显示。
5 字体点阵模块提供点阵获取与处理接口。
由于嵌入式实际没那么复杂,在例程中我们将GUI跟LCD驱动层放到一起。
TFT LCD的两个驱动也放到一个文件,但是逻辑是分开的。
OLED除初始化,其他接口跟COG LCD基本一样,因此这两个驱动也放在一个文件。
 

代码分析

代码分三层:
1. GUI和LCD驱动成
dev_lcd.c
dev_lcd.h
2. 显示驱动IC层
dev_str7565.c & dev_str7565.h
dev_ILI9341.c & dev_ILI9341.h
3. 接口层
mcu_spi.c & mcu_spi.h
stm324xg_eval_fsmc_sram.c & stm324xg_eval_fsmc_sram.h
 

GUI和LCD层

这层主要有3个功能
1 设备管理
首先定义了一堆LCD参数结构体,结构体包含ID,像素。
并且把这些结构体组合到一个list数组内。

/*    各种LCD的规格参数*/
_lcd_pra LCD_IIL9341 =
{        
.id   = 0x9341,        
.width = 240,   //LCD 宽度        
.height = 320,  //LCD 高度
};
...
/*各种LCD列表*/
_lcd_pra *LcdPraList[5=            
{                
&LCD_IIL9341,                       
&LCD_IIL9325,                
&LCD_R61408,               
&LCD_Cog12864,                
&LCD_Oled12864,            
};

然后定义了所有驱动list数组,数组内容就是驱动,在对应的驱动文件内实现。

/*    所有驱动列表    驱动列表*/
_lcd_drv *LcdDrvList[ = {                    
&TftLcdILI9341Drv,                    
&TftLcdILI9325Drv,                   
&CogLcdST7565Drv,                    
&OledLcdSSD1615rv,

定义了设备树,即是定义了系统有多少个LCD,接在哪个接口,什么驱动IC。
如果是一个完整系统,可以做成一个类似LINUX的设备树。

/*设备树定义*/
#define DEV_LCD_C 3//系统存在3个LCD设备
LcdObj LcdObjList[DEV_LCD_C={    
{"oledlcd", LCD_BUS_VSPI, 0X1315},    
{"coglcd", LCD_BUS_SPI,  0X7565},    
{"tftlcd", LCD_BUS_8080, NULL},
};

2 接口封装

void dev_lcd_setdir(DevLcd *obj, u8 dir, u8 scan_dir)
s32 dev_lcd_init(void)
DevLcd *dev_lcd_open(char *name)
s32 dev_lcd_close(DevLcd *dev)
s32 dev_lcd_drawpoint(DevLcd *lcd, u16 x, u16 y, u16 color)
s32 dev_lcd_prepare_display(DevLcd *lcd, u16 sx, u16 ex, u16 sy, u16 ey)
s32 dev_lcd_display_onoff(DevLcd *lcd, u8 sta)
s32 dev_lcd_fill(DevLcd *lcd, u16 sx,u16 ex,u16 sy,u16 ey,u16 *color)
s32 dev_lcd_color_fill(DevLcd *lcd, u16 sx,u16 ex,u16 sy,u16 ey,u16 color)
s32 dev_lcd_backlight(DevLcd *lcd, u8 sta)

大部分接口都是对驱动IC接口的二次封装。有区别的是初始化和打开接口。
初始化,就是根据前面定义的设备树,寻找对应驱动,找到对应设备参数,并完成设备初始化。
打开函数,根据传入的设备名称,查找设备,找到后返回设备句柄,后续的操作全部需要这个设备句柄。
3 简易GUI层
目前最重要就是显示字符函数。

s32 dev_lcd_put_string(DevLcd *lcd, FontType font, int x, int y, char *s, unsigned colidx)

其他划线画圆的函数目前只是测试,后续会完善。

驱动IC层

驱动IC层分两部分
1 封装LCD接口
LCD有使用8080总线的,有使用SPI总线的,有使用VSPI总线的。这些总线的函数由单独文件实现。
但是,除了这些通信信号外,LCD还会有复位信号,命令数据线信号,背光信号等。
我们通过函数封装,将这些信号跟通信接口一起封装为LCD通信总线。
BUS_8080在dev_ILI9341.c文件中封装。
BUS_LCD1和BUS_lcd2在dev_str7565.c 中封装。
2 驱动实现
实现_lcd_drv驱动结构体。每个驱动都实现一个,某些驱动可以共用函数。

_lcd_drv CogLcdST7565Drv = { 
                           .id = 0X7565, 
                           .init = drv_ST7565_init, 
                           .draw_point = drv_ST7565_drawpoint,
                            .color_fill = drv_ST7565_color_fill, 
                           .fill = drv_ST7565_fill, 
                           .onoff = drv_ST7565_display_onoff,
                            .prepare_display = drv_ST7565_prepare_display, 
                           .set_dir = drv_ST7565_scan_dir,
                            .backlight = drv_ST7565_lcd_bl                            
};

接口层

8080层比较简单,用的是官方接口。
SPI接口提供下面操作函数,可以操作SPI,也可以操作VSPI。

extern s32 mcu_spi_init(void);
extern s32 mcu_spi_open(SPI_DEV dev, SPI_MODE mode, u16 pre);
extern s32 mcu_spi_close(SPI_DEV dev);
extern s32 mcu_spi_transfer(SPI_DEV dev, u8 *snd, u8 *rsv, s32 len);
extern s32 mcu_spi_cs(SPI_DEV dev, u8 sta);

至于SPI为什么这样写,会有一个单独文件说明。

总体流程

前面说的几个模块时如何联系在一起的呢?
请看下面结构体:

/*    初始化的时候会根据设备数定义,    
并且匹配驱动跟参数,并初始化变量。    
打开的时候只是获取了一个指针*/
struct _strDevLcd{
    s32 gd;//句柄,控制是否可以打开    
    LcdObj   *dev;    
/* LCD参数,固定,不可变*/
    _lcd_pra *pra;    
/* LCD驱动 */ 
   _lcd_drv *drv;    
/*驱动需要的变量*/
    u8  dir;    //横屏还是竖屏控制:0,竖屏;1,横屏。
    u8  scandir;//扫描方向
    u16 width;  //LCD 宽度 
   u16 height; //LCD 高度
    void *pri;//私有数据,黑白屏跟OLED屏在初始化的时候会开辟显存
};

每一个设备都会有一个这样的机构体,这个结构体在初始化LCD时初始化。
- 成员dev指向设备树,从这个成员可以知道设备名称,挂在哪个LCD总线,设备ID。

typedef struct{
    char *name;//设备名字
    LcdBusType bus;//挂在那条LCD总线上
    u16 id;
}LcdObj;

-成员pra指向LCD参数,可以知道LCD的规格。

typedef struct{ 
   u16 id;    
   u16 width;  //LCD 宽度  竖屏   
   u16 height; //LCD 高度    竖屏
}_lcd_pra;

-成员drv指向驱动,所有操作通过drv实现。

typedef struct  {
    u16 id;
    s32 (*init)(DevLcd *lcd);
    s32 (*draw_point)(DevLcd *lcd, u16 x, u16 y, u16 color);
    s32 (*color_fill)(DevLcd *lcd, u16 sx,u16 ex,u16 sy,u16 ey, u16 color);
    s32 (*fill)(DevLcd *lcd, u16 sx,u16 ex,u16 sy,u16 ey,u16 *color); 
   s32 (*prepare_display)(DevLcd *lcd, u16 sx, u16 ex, u16 sy, u16 ey);
    s32 (*onoff)(DevLcd *lcd, u8 sta); 
   void (*set_dir)(DevLcd *lcd, u8 scan_dir); 
   void (*backlight)(DevLcd *lcd, u8 sta);
}_lcd_drv;

  • 成员dir、scandir、 width、 height是驱动要使用的通用变量。因为每个LCD都有一个结构体,一套驱动程序就能控制多个设备而互不干扰。
  • 成员pri是一个私有指针,某些驱动可能需要有些比较特殊的变量,就全部用这个指针记录,通常这个指针指向一个结构体,结构体由驱动定义,并且在设备初始化时申请变量空间。
    目前主要用于COG LCD跟OLED LCD显示缓存。
整个LCD驱动,就通过这个结构体组合在一起。
1 初始化,根据设备树,找到驱动跟参数,然后初始化上面说的结构体。
2 要使用LCD前,调用dev_lcd_open函数。打开成功就返回一个上面的结构体指针。
3 显示字符,接口找到点阵后,通过上面结构体的drv,调用对应的驱动程序。
4 驱动程序根据这个结构体,决定操作哪个LCD总线,并且使用这个结构体的变量。

用法和好处

  • 好处1
请看测试程序

void dev_lcd_test(void)
{
    DevLcd *LcdCog; 
   DevLcd *LcdOled;
    DevLcd *LcdTft;
    /*  打开三个设备 */ 
   LcdCog = dev_lcd_open("coglcd"); 
   if(LcdCog==NULL) 
       uart_printf("open cog lcd err\r\n");
    LcdOled = dev_lcd_open("oledlcd");
    if(LcdOled==NULL) 
       uart_printf("open oled lcd err\r\n");
    LcdTft = dev_lcd_open("tftlcd");
    if(LcdTft==NULL)
        uart_printf("open tft lcd err\r\n");
    /*打开背光*/ 
   dev_lcd_backlight(LcdCog, 1); 
   dev_lcd_backlight(LcdOled, 1);
    dev_lcd_backlight(LcdTft, 1);

dev_lcd_put_string(LcdOled, FONT_SONGTI_1212, 10,1, "ABC-abc,", BLACK); 
   dev_lcd_put_string(LcdOled, FONT_SIYUAN_1616, 1, 13, "这是oled lcd", BLACK); 
   dev_lcd_put_string(LcdOled, FONT_SONGTI_1212, 10,30, "www.wujique.com", BLACK); 
   dev_lcd_put_string(LcdOled, FONT_SIYUAN_1616, 1, 47, "屋脊雀工作室", BLACK); 
   dev_lcd_put_string(LcdCog, FONT_SONGTI_1212, 10,1, "ABC-abc,", BLACK); 
   dev_lcd_put_string(LcdCog, FONT_SIYUAN_1616, 1, 13, "这是cog lcd", BLACK);
    dev_lcd_put_string(LcdCog, FONT_SONGTI_1212, 10,30, "www.wujique.com", BLACK); 
   dev_lcd_put_string(LcdCog, FONT_SIYUAN_1616, 1, 47, "屋脊雀工作室", BLACK); 
   dev_lcd_put_string(LcdTft, FONT_SONGTI_1212, 20,30, "ABC-abc,", RED); 
   dev_lcd_put_string(LcdTft, FONT_SIYUAN_1616, 20,60, "这是tft lcd", RED); 
   dev_lcd_put_string(LcdTft, FONT_SONGTI_1212, 20,100, "www.wujique.com", RED);
    dev_lcd_put_string(LcdTft, FONT_SIYUAN_1616, 20,150, "屋脊雀工作室", RED);    while(1);}

使用一个函数dev_lcd_open,可以打开3个LCD,获取LCD设备。
然后调用dev_lcd_put_string就可以在不同的LCD上显示。
其他所有的gui操作接口都只有一个。
这样的设计对于APP层来说,就很友好。

- 好处2
现在的设备树是这样定义的

LcdObj LcdObjList[DEV_LCD_C={ 
   {"oledlcd", LCD_BUS_VSPI, 0X1315}, 
   {"coglcd", LCD_BUS_SPI,  0X7565},
    {"tftlcd", LCD_BUS_8080, NULL},
};

某天,oled lcd要接到SPI上,只需要将设备树数组里面的参数改一下,就可以了,当然,在一个接口上不能接两个设备。

LcdObj LcdObjList[DEV_LCD_C={
    {"oledlcd", LCD_BUS_SPI, 0X1315}, 
   {"tftlcd", LCD_BUS_8080, NULL},
};

字库

暂时不做细说,例程的字库放在SD卡中,各位移植的时候根据需要修改。
具体参考font.c

声明

1 代码请按照版权协议使用。
2 当前源码只是一个能用的设计,完整性与健壮性尚未测试。
3 后续会放到github,并且持续更新优化。
4 最新消息请关注www.wujique.com.

LCD驱动应该怎么写?–基于stm32F407 [复制链接]的更多相关文章

  1. Smart210学习-----lcd驱动

    帧缓冲设备 1.1帧缓冲设备:帧缓冲(framebuffer)是 Linux 系统为显示设备提供的一个接口,它将显示缓冲区抽象,屏蔽图像硬件的底层差异,允许上层应用程序在图形模式下直接对显示缓冲区进行 ...

  2. 【GMT43智能液晶模块】基于HAL库的SDRAM和LCD驱动例程(MDK工程&CubeMX工程)

    说明: 1.该工程基于HAL库实现动态存储器SDRAM驱动以及液晶控制器LCD驱动. 2.工程通过STM32CubeMX(Version 4.22.0)配置生成,可直接打开进行配置. 3.KEIL M ...

  3. LCD驱动(FrameBuffer)实例开发讲解

    一.开发环境 主  机:VMWare--Fedora 9 开发板:Mini2440--64MB Nand, Kernel:2.6.30.4 编译器:arm-linux-gcc-4.3.2 二.背景知识 ...

  4. LCD驱动分析【转】

    转自:http://blog.csdn.net/hanmengaidudu/article/details/21559153 1.S3C2440上LCD驱动 (FrameBuffer)实例开发讲解 其 ...

  5. S3C2440上LCD驱动(FrameBuffer)实例开发讲解

    一.开发环境 主  机:VMWare--Fedora 9 开发板:Mini2440--64MB Nand, Kernel:2.6.30.4 编译器:arm-linux-gcc-4.3.2 二.背景知识 ...

  6. S3C2440 LCD驱动(FrameBuffer)实例开发<一>(转)

    1. 背景知识 在多媒体的推动下,彩色LCD越来越多地应用到嵌入式系统中,PDA和手机等大多都采用LCD作为显示器材,因此学习LCD的应用很有实际意义! LCD工作的硬件需求:要使一块LCD正常的显示 ...

  7. sc7731 Android 5.1 LCD驱动简明笔记之三

    此篇笔记基于sc7731 - android 5.1,对lcd的gralloc库做一个简明笔记. 第一部分 调用gralloc.sc8830.so所谓的Gralloc模块,它就是一个模块,一个操作ke ...

  8. sc7731 Android 5.1 LCD驱动简明笔记之一

    基于展讯sc7731 - Android 5.1 代码分析浏览.将屏蔽细节,把握整体,并且不涉及其他设备和LCD的交互. 以下对sc7731 lcd大体流程进行简要说明. 第一,lcd 的两个阶段 1 ...

  9. android系统平台显示驱动开发简要:LCD驱动调试篇『四』

    平台信息: 内核:linux3.4.39系统:android4.4 平台:S5P4418(cortex a9) 作者:瘋耔(欢迎转载,请注明作者) 欢迎指正错误,共同学习.共同进步!! 关注博主新浪博 ...

随机推荐

  1. 【代码笔记】iOS-4个可以单独点击的button

    一,效果图. 二,工程图. 三,代码. ViewController.m #import "ViewController.h" @interface ViewController ...

  2. 【读书笔记】iOS-网络-HTTP-URL结构

    http://user:password@hostname:port/absolute-path?query. http:  协议 user:password@   认证 hostname:  主机名 ...

  3. eclipse以O开头的版本安装tomcat插件

    最近闲着无聊想着捣鼓下java web ,轻车熟路的在eclipse下载好IDE,有强迫症的我下载了最新版本的(2017-10),然而下载过来的IDE真的是纯净版的,连java web 的new pr ...

  4. JavaScript写计算器

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. VC中添加头文件以及库

    原文:http://blog.csdn.net/lwb102063/article/details/52068389   附加头文件包含 VC6.0中: VC6.0默认include包含路径:Tool ...

  6. springboot 1.3.5升级1.5.9后 默认使用tomcat 8.5版本 get请求报400 异常信息为 The valid characters are defined in RFC 7230 and RFC 3986

    1.springboot 1.3.5升级1.5.9后 默认使用tomcat 8.5版本而之前用的是tomcat7    get请求报400 异常信息为 The valid characters are ...

  7. 构建第一个SpringBoot工程

    学习和使用 SpringBoot 有一段时间了,现在开始陆陆续续会总结归纳 SpringBoot 学习中遇到的相关知识点. SpringBoot 设计目的是用来简化新Spring应用的初始搭建以及开发 ...

  8. 2016年度最受欢迎的100个 Java 库

    [编者按]本文作者为 Henn Idan,主要介绍基于 GitHub 中的数据分析,得出的2016年度最受欢迎的100个 Java 库.本文系国内 ITOM 管理平台 OneAPM 编译呈现. 谁拔得 ...

  9. 字节顺序标记BOM

    最近,从numbers导出的csv文件,导入excel后,出现中文乱码问题.网上查询后,发现是numbers导出的csv默认是utf-8无BOM的,使用sublimText3打开,另存为utf-8wi ...

  10. LeetCode题解之 Increasing Order Search Tree

    1.题目描述 2/问题分析 利用中序遍历,然后重新构造树. 3.代码 TreeNode* increasingBST(TreeNode* root) { if (root == NULL) retur ...