OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 21449|回复: 14

ILI9325横屏显示完美版,实现填充方式写数据,提高刷屏速度,同时可驱动HX8352

[复制链接]

63

主题

305

帖子

1

精华

高级会员

Rank: 4

积分
853
金钱
853
注册时间
2012-8-3
在线时间
79 小时
发表于 2012-8-12 12:58:35 | 显示全部楼层 |阅读模式
看了正点原子的液晶程序,虽然兼容多种液晶控制器,但是我本人也就只有两块液晶而已,根据DIY的原则,修改了部分代码,整理出HX8352&ILI9325兼容的二合一驱动,并且实现了ILI9325的横屏模式下的填充方式写字符,具体实现方法请访问:
ILI9325之Datasheet解析:
http://user.qzone.qq.com/362087583/blog/1344605757
ILI9325横屏显示:
http://user.qzone.qq.com/362087583/blog/1344866997
约定:竖屏时,Horizontal(Column):X=0~239;Vertical(Row):Y=0~319,原点位置(0,0)为左上角,如下图:





















 
一、扫描方式











































以上文字大意是9325由720个源极通道和320个栅极通道组成,为什么是720呢,因为每个像素点由三个部分组成:R G B ,分别对应红绿蓝三原色,液晶显示的原理就是控制三种光色的搭配形成各种颜色 ,720个Source(240*3=720 ,分布在X轴),320个Gate驱动分布在Y轴。G和S构成像素矩阵,通过扫面输出G和S信号就可以在屏幕上显示信息。





























 
G驱动的扫描方式看寄存器R01和R60H,需要GS与SM配合设置,SS控制S通道正序或倒序扫描,GS同理,SM控制G通道逐行或隔行扫面。






















SS:0为正序,1为倒序
GS:0为正序,1为倒序
实际测试,竖屏时,先设置SM=0,设置SS=0,GS=0和SS=1,GS=1效果刚好中心对称显示(旋转180);
Sm=0、SS=0不变时,GS由0改为1,则显示结果和原图一Y轴方向轴对称,因此看起来图像上下颠倒了,因为地址内存数据虽然没有改变,但是输出到屏幕的顺序改变了。
GS=0,SS=0时,SM=1时,由于此时G通道是隔行扫描的,先送G1,G3,……G317,319再从G2,G4扫到G320,就像食堂打饭,本来正常顺序是从第一人开始顺序打饭,但是如果队伍不变,但是隔一个人打饭,假设从奇数个开始打饭,那么先给所有奇数个打饭,之后才给排偶数的人打饭,这就造成偶数个打到的都是剩饭剩菜。但是液晶还有一个S通道,S通道是顺序扫描,两种效果叠加,所以最终显示结果是下半部图像和上半部调换并被拉长。故此得出结论,SM一定要设置为0!
 
二、显存GRAM地址设置
本节要用到的寄存器有R03H,R50 R51  R52 R53共5个寄存器。
首先要注意的是,ORG=0时,ILI9325的内存地址是不能修改的,也就是说,内存地址0000H始终对应屏幕左上角(0,0),当然这是正常情况下的情形,我们可以通过第一节介绍的的方法控制显示方式,但即便如此,也只是控制输出数据的顺序而已,地址与屏幕的默认对应关系是不可改变的。而HIMAX奇景光电的HX8352控制器是可以改变内存地址与屏幕的对应关系的,也就是说可以修改原点(0,0)在屏幕中的位置
R03:此寄存器用于设置写入ram时,内存地址增加/减少的方向


 
其中 TRI DFM均默认0,不解释,BGR置为1,BGR为1表示写入GRAM的数据格式是按B G R的顺序存放的,设置错误图像会按照逆序的RGB颜色显示,若发现显示颜色有误,改BGR为0就好了。
AM:水平/垂直扫描方向选择,0为水平,1为垂直;
ID:内存地址计数器(AC)增/减方向,不解释,看图;
实际上AM和ID只对开辟窗口写数据方式有用,需要结合R50~R53,一般初始化时会给R50~R53设置为239,319。
下一期将对横屏模式作分析,敬请关注。由于水平有限,有错漏的地方请见谅,敬请斧正。

源程序请到以下地址下载查看:
一、竖屏显示
        要想实现横屏显示,首先要了解竖屏显示的操作方法,前面说过原点位置(0,0)位于屏幕左上角,对于ILI9325(0,0)位置也是显存地址00000H对应的地方,为什么用00000H而不用0H表示呢,因为Gram低八位用于表示X轴坐标,范围从0~EFH(0~239),高12位用于Y轴地址坐标,范围从0~13FH(0~319),所以右下角终点地址是13FEFH。但坐标地址并不是连续的,因为13FEFH = 81903,这与屏幕像素点总数与240*320=76800并不相等,因为低八位最大值是EFH,但不要紧,这个问题并不影响操作。默认情况下,每次向gram中写像素数据,iLI9325的gram地址自动先从左到右,再从上到下增加。ILI9325用R20H和R21H两个寄存器来确定GRAM地址
        所以我们在某个点写数据的过程是:
1.向寄存器R20H,R21H写像素地址
2.写一次R22H命令,通知ILI9325准备接受RGB数据
3.写RGB数据
二、划定窗口连续写数据
        按照第一节介绍的方法我们发现如果要在某个矩形区域连续写同种颜色数据,每次都需要重新定义GRAM地址,效率很低,实际上可以通过划定区域来向指定窗口区域中连续输入数据,因为GRAM地址会按照寄存器R03H中的ORG AM ID确定的方向自动增/减,而且竖屏的时候。ORG = 1时,当通过50H~53H划定区域时,芯片将GRAM地址00000H映射到窗口区域的某个顶点(根据AM、ID的设置,见下图中各种模式中字母B的位置就是00000H的位置(Begin)),这样就可以再横屏显示时也可以划定区域连续填数据。
        一般情况下,竖屏显示时让ORG = 0,因为很多人都会选择ID = 11,AM=0的模式(下图中右上角的模式,看字字母"F"的正常情况下的朝向),这样区域填充数据时就符合使用者常规视觉上的理解,不用做坐标转换,。此时,因为ORG = 0,即使通过R50~53H划定窗口,但是00000H依然是在屏幕的左上角,而不是窗口区域的左上角!且此时向R20H R21H写的地址必须是窗口内的地址,否则无效。
        横屏显示时,令ORG = 1,这样我们划区域时GRAM起始地址00000H就始终映射到窗口中起点B的位置,此时地址自增的方向才符合人体视觉上的从左到右,从上到下。我选择ID = 10 ,AM=1 ,对应下图中的第二排第二种模式。记得此时要么SS=1 GS=1,要么SS=0,GS = 0,不懂什么意思请看上一篇。




程序代码如下:
 
//设置光标位置
//Xpos:横坐标
//Ypos:纵坐标
__inline void LCD_SetCursor(u16 Xpos, u16 Ypos)
{
 if(DeviceCode==0X52)
 {
  LCD_WriteReg(0x02, Xpos>>8);//起点x高八位
  LCD_WriteReg(0x03, Xpos); //起点x低八位
  LCD_WriteReg(0x06, Ypos>>8);//起点y高八位
  LCD_WriteReg(0x07, Ypos);   //起点y低八位                
 }else
 if(DeviceCode==0X9325)
 {
 #if USE_HORIZONTAL == 0
  LCD_WriteReg(0x50, Xpos);
  LCD_WriteReg(0x51, LCD_W);  //把终点定在屏幕右下角,确保Xpos有效,因为0x50的值必须<0x51的值
  LCD_WriteReg(0x52, Ypos);
  LCD_WriteReg(0x53, LCD_H);
 #else
  LCD_WriteReg(0x50, Ypos);
  LCD_WriteReg(0x51, 239);  //把终点定在屏幕右下角,确保Xpos有效,因为0x50的值必须<0x51的值
  LCD_WriteReg(0x52, 0);        //把终点定在屏幕右下角,确保Xpos有效,因为0x52的值必须<0x53的值
  LCD_WriteReg(0x53, 319-Xpos);
 #endif
  LCD_WriteReg(0x20, 0x0000);
  LCD_WriteReg(0x21, 0x0000);
 }
 LCD_WR_REG(WriteGram);   //准备写入ram
}
 
//LCD_SetDomain:设定窗口区域写数据
//Xsta , Ysta:起点横坐标和纵坐标
//Xend , Yend:终点横坐标和纵坐标
void LCD_SetDomain(u16 Xsta, u16 Ysta,u16 Xend, u16 Yend)
{
 if(DeviceCode==0X52)//HX8352
 {
  LCD_WriteReg(0x02, Xsta>>8);//起点x高八位但由于最大值为239,故高八位始终为0,可不写
  LCD_WriteReg(0x03, Xsta); //起点x低八位
  LCD_WriteReg(0x04, Xend>>8);//终点x高八位
  LCD_WriteReg(0x05, Xend); //终点x低八位
  LCD_WriteReg(0x06, Ysta>>8);//起点y高八位
  LCD_WriteReg(0x07, Ysta);   //起点y低八位
  LCD_WriteReg(0x08, Yend>>8);//终点y高八位
  LCD_WriteReg(0x09, Yend); //终点y低八位                
 }
 else    
 if(DeviceCode==0X9325) //ILI9325
 {
 #if USE_HORIZONTAL == 0
  LCD_WriteReg(0x50, Xsta); //水平GRAM起始位置
  LCD_WriteReg(0x51, Xend); //水平GRAM终点位置
  LCD_WriteReg(0x52, Ysta); //水平GRAM起始位置
  LCD_WriteReg(0x53, Yend); //垂直GRAM终点位置
//50h和52h是起点,51h和53h是终点
 #else
  LCD_WriteReg(0x50, Ysta);  //水平GRAM起始位置
  LCD_WriteReg(0x51, Yend);  //水平GRAM终点位置
  LCD_WriteReg(0x52, 319-Xend); //垂直GRAM起始位置
  LCD_WriteReg(0x53, 319-Xsta); //垂直GRAM终点位置
 #endif
  LCD_WriteReg(0x20, 0x0000);
  LCD_WriteReg(0x21, 0x0000);
 }
 LCD_WR_REG(WriteGram);   //准备写入ram
 
在上面代码中,为什么写50H~53H写数据时坐标特别呢,因为上一篇说过,ILI9325的GRAM地址与屏幕的对应关系是不会改变的,不管怎么设置50H和51H始终是竖屏时的横坐标,52H和53H始终和竖屏时的纵坐标一样,这样一来,只能坐标转换了,横屏时看上去的坐标转换到竖屏的坐标图上去,使(0,0)位置通过程序映射到横屏时的左上角,好了,ILI9325的笔记到此为止,摸清了ILI9325,相信其他液晶控制IC也就能举一反三了。
 

STM32_240320_TFTLCD_ILI9325_HX8352_Final.rar

66.27 KB, 下载次数: 2796

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2012-8-12 13:33:56 | 显示全部楼层
回复 支持 反对

使用道具 举报

36

主题

1105

帖子

5

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
2201
金钱
2201
注册时间
2012-2-8
在线时间
35 小时
发表于 2012-8-12 13:42:09 | 显示全部楼层
 又一把内容放QQ空间里不愿贴这的
https://github.com/roxma
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手上路

积分
46
金钱
46
注册时间
2012-9-28
在线时间
5 小时
发表于 2012-10-20 23:32:33 | 显示全部楼层
谢谢分享!!!
回复 支持 反对

使用道具 举报

12

主题

216

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
313
金钱
313
注册时间
2011-4-7
在线时间
3 小时
发表于 2012-10-22 11:43:46 | 显示全部楼层
mark
回复 支持 反对

使用道具 举报

2

主题

8

帖子

0

精华

初级会员

Rank: 2

积分
74
金钱
74
注册时间
2012-11-9
在线时间
13 小时
发表于 2012-11-9 23:45:52 | 显示全部楼层
ili9325的LCD
在移植GUI的时候发现怎么样都画不了点。

弄了半天。用窗口可以画。
但20,21寄存器却死活不起做用。
是我哪里弄错了吗。

求救 


LCD_WriteReg(0x0050,50);//窗口X0
LCD_WriteReg(0x0051,50);//窗口y0 
LCD_WriteReg(0x0052,50);//窗口x1
LCD_WriteReg(0x0053,50);//窗口y1
LCD_WriteRAM_Prepare();//写gram
LCD_WriteRAM(0xf800);//写数据

//上面能正常画一个点

LCD_WriteReg(0x0020,100);//设置X坐标位置
LCD_WriteReg(0x0021,100);//设置Y坐标位置
LCD_WriteRAM_Prepare();//写gram
LCD_WriteRAM(0xf800);//写数据
//这个不能正常画一个点
回复 支持 反对

使用道具 举报

13

主题

91

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
235
金钱
235
注册时间
2012-11-17
在线时间
18 小时
发表于 2012-12-12 04:32:58 | 显示全部楼层
B505型号的LCD,通过个人实践,发觉如果要横屏显示,需要设置SM=0,SS=1,GS=0(跟楼主说的GS=1不一样,应该是型号不同的缘故),ID[1:0]=01,AM=1,当然因为是通过开窗口区域来指定坐标,所以ORG=1。

其实还有另一个倒方向横屏的,这个时候应该需要设置SS=0,但因通常竖屏的时候设置SS=1,通常就不弄这个方向的横屏。
回复 支持 反对

使用道具 举报

0

主题

16

帖子

0

精华

初级会员

Rank: 2

积分
68
金钱
68
注册时间
2013-3-16
在线时间
7 小时
发表于 2013-5-8 21:57:27 | 显示全部楼层
学习下
回复 支持 反对

使用道具 举报

46

主题

333

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
357
金钱
357
注册时间
2013-12-12
在线时间
63 小时
发表于 2014-2-18 17:36:35 | 显示全部楼层
回复【3楼】Pony279:
---------------------------------
突然看到,原来大师你是老马旗下的~膜拜下~
回复 支持 反对

使用道具 举报

63

主题

305

帖子

1

精华

高级会员

Rank: 4

积分
853
金钱
853
注册时间
2012-8-3
在线时间
79 小时
 楼主| 发表于 2014-3-21 19:27:48 | 显示全部楼层
回复【6楼】gongcsf:
---------------------------------
20h和21h的地址必须要在窗口区域内才有效。
LCD_WriteReg(0x0050,0);//窗口X0 
LCD_WriteReg(0x0051,0);//窗口y0 
LCD_WriteReg(0x0052,LCD_W);//窗口x1 
LCD_WriteReg(0x0053,LCD_H);//窗口y1 
LCD_WriteReg(0x0020,100);//设置X坐标位置 
LCD_WriteReg(0x0021,100);//设置Y坐标位置 
LCD_WriteRAM_Prepare();//写gram 
LCD_WriteRAM(0xf800);//写数据 

这样肯定行。
一般只有初始化时将窗口划为全屏,之后写数据才只需写20H和21H,这就是为什么原子的例程中,定坐标不写50H~53H,因为LCD初始化函数中窗口区域(50H~53H)已经划为全屏了,仔细看芯片手册。
回复 支持 反对

使用道具 举报

39

主题

160

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
298
金钱
298
注册时间
2014-1-9
在线时间
8 小时
发表于 2014-3-25 09:34:31 | 显示全部楼层
谢谢,看了这里完美解决了我的问题
回复 支持 反对

使用道具 举报

2

主题

40

帖子

0

精华

初级会员

Rank: 2

积分
68
金钱
68
注册时间
2014-7-11
在线时间
0 小时
发表于 2014-7-30 23:06:18 | 显示全部楼层
很好,很强大
回复 支持 反对

使用道具 举报

2

主题

19

帖子

0

精华

新手上路

积分
48
金钱
48
注册时间
2014-4-23
在线时间
0 小时
发表于 2014-8-2 20:57:59 | 显示全部楼层
谢谢分享,真心有用!
都只为不负青春
回复 支持 反对

使用道具 举报

0

主题

1

帖子

0

精华

新手入门

积分
21
金钱
21
注册时间
2014-9-1
在线时间
0 小时
发表于 2014-9-18 16:44:28 | 显示全部楼层
很好很强大!学习了!
回复 支持 反对

使用道具 举报

0

主题

10

帖子

0

精华

新手上路

积分
45
金钱
45
注册时间
2014-11-15
在线时间
5 小时
发表于 2014-12-22 20:58:17 | 显示全部楼层
谢谢分享,我搞了一个40X24点阵的字库,显示三组仪表参数,每组显示5位数字,结果刷新速度每秒只有8次左右,准备用楼主的方法再试,看能提高多少
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-27 15:51

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表