[nRF51822] 2、D-BUG之诗

摘要:
4线SPI彩色屏幕部分刷屏偏移的解决方案-我已经成功了很长一段时间。最近,我一直在研究如何用低速低RAM微控制器驱动小型LCD或TFT彩色屏幕。首先,我尝试用8位微控制器nRF51822驱动1.77英寸4线SPI屏幕(128X160),该微控制器具有16MHz晶体振荡器的m0内核。结果发现,刷屏大约需要0.8秒,具体包括在1.一个简单的nRF51822驱动天马4线SPI-1.77英寸LCD彩色屏幕

4线SPI彩屏局部刷屏偏移解决

            ——原来我早已经在成功的旁边了

 

最近在研究用低速、低RAM的单片机来驱动小LCD或TFT彩屏实现动画效果

首先我用一个16MHz晶振的m0内核的8位单片机nRF51822尝试驱动一个1.77寸的4线SPI屏(128X160),

发现,刷一屏大约要0.8s左右的时间,

具体收录在《1、一个简单的nRF51822驱动的天马4线SPI-1.77寸LCD彩屏DEMO》中

觉得,如果用72MHz的STM32也许效果会好很多

于是在stm32上做了个类似的版本,

具体收录在《一个简单的stm32vet6驱动的天马4线SPI-1.77寸LCD彩屏DEMO》中

发现刷一屏0.2s左右,

效果是有的,但是还不能达到支持播放流畅动画的效果!

后来,用stm32驱动一个2.4寸240X320的8位并口tft屏

具体收录在《一个简单的stm32vet6驱动2.4寸240X320的8位并口tft屏DEMO》中

这个尺寸比之前的1.77要大4倍,

所以即使采用8位并口速度还是没太大变化!

再后来,偶然发现采用单片机自带的硬件SPI速度回快很多(3-8倍)

这主要是因为硬件SPI把下面采用软件模拟的过程中不必要的移位、复制、电平翻转采用硬件给做了~(猜测)

 1 void SendDataSPI(unsigned char dat)
 2 {
 3     unsigned char i;
 4     for(i = 0; i < 8; i++)
 5     {
 6         if( (dat & 0x80) != 0 ) SDA_SET;
 7         else SDA_CLEAR;
 8 
 9         dat <<= 1;
10 
11         SCL_CLEAR;
12         SCL_SET;
13     }
14 }

尽管如此!还是不能实现大块大块图片的动画刷新效果~

于是灵机一动,也许采用16位并口+同时数据传输采用硬件刷屏速度会飞起来!

呵呵,其实是早就知道这个方法,也是最后的杀手锏了

如果是在不行DSP、FPGA得搬出来了~

其实上面这个想法有一个很霸气(拗口)的称呼——FSMC(Flexible Static Memory Controller,可变静态存储控制器)

也因此,我买了个土豪金屏幕——

[nRF51822] 2、D-BUG之诗第1张

只看该屏幕的介绍就知道人家不简单——(速度震四方!!!)

[nRF51822] 2、D-BUG之诗第2张


哈哈,扯远了!(开始说本节内容了哈~)

其实本节的重点不是展示这个速震四方的土豪屏,

而是一个突发bug的出现导致我不得不放下手中的土豪屏,专心搞BUG

BUG是这样的——

[nRF51822] 2、D-BUG之诗第3张

我拿到一个4线spi的220X176的屏幕,想写个驱动

本来应该是分分钟的事,可是遇到了一个坑了几天的问题:

拿到该屏幕及其资料如下:其中GC9201为其驱动IC,QTB2D0052和60是上面屏幕的规格书,只是外观大小稍有不同,压缩文件是一个包含简单demo的工程

http://pan.baidu.com/s/1eQRuP4u

[nRF51822] 2、D-BUG之诗第4张

① 在QT---52中找到对应引脚并设置好:

[nRF51822] 2、D-BUG之诗第5张

② 参考压缩文件的驱动,在驱动文件中实现了刷屏、绘制条带、显示帧、绘制渐变条带、绘制黑白格子、在屏幕中间显示一个黑色、绘制一点、绘制一条线、绘制一个网等LCD屏幕驱动函数~

 1 int main(void)
 2 {
 3     int x,y;
 4     GPIO_Init();
 5     LCD_Init();
 6     
 7 //        DrawGird(RED);
 8     
 9     while(1<2)
10     {
11         DispColor(GREEN);//刷屏
12         DispBand();//显示条带
13         DispFrame();//显示窗口
14         DispScaleVer();//渐变颜色
15         DispScaleVer_Red();//红色渐变
16         DispSnow();//黑白格子
17         DispBlock();//在中间显示一个黑色块,但是是全屏刷新
18         
19         for(x=0,y=0;x<149;x++,y+=2)
20         {
21             PutPixel(x,y,BLUE);
22         }
23         
24         DrawLine(20,120,5,6,RED);
25         DrawGird(RED);
26     }
27 }

当时封装驱动在:http://pan.baidu.com/s/1bnX69Mf

③ 照理说参照厂家DEMO应该一气呵成的,可最坑爹的问题还就在不可能出现问题的地方【【【神坑】】】

当顺利测试完DispBlock()后,PutPixel(x,y,BLUE)函数总是不能把相应的点绘制对,然后我又试了DrawLine、DrawGrid,都出现了很大的问题

:::问题-就是整屏刷新可以成功,位置也对;局部刷新要么偏移,要么导致自身和之后的刷屏错误(具体表现为下一次接着上一次刷)

踩坑的-ALL PROCESS:其实首先发现这个原因之前做了很多工作——本来是直接分分钟写个驱动整合到总工程中进行从flash读图片并刷新在屏幕中央的,结果总是出现偏移!于是

1、仔细拿着厂家给的DEMO核对,发现并没有区别,DBUG失败

2、然后又逐条翻译LCD驱动中的writecom命令,并没有发现什么异常

3、重新看LCD驱动IC文档,千辛万苦发现命令20h和21h似乎对偏移能起作用

[nRF51822] 2、D-BUG之诗第6张

发现这两个命令和AC有关,屏幕之所以出现偏移可能是在writeblock中只指定了视窗,却没有修改AC值!

又发现上表中有G1~G220,由于对数据比较敏感,觉得这两个命令肯定是控制Y方向的AC的,

又参考38、39对Y方向视窗的设置方式,

于是顺手在blockwrite中加了两句:

 1 void BlockWrite(unsigned int Xstart,unsigned int Xend,unsigned int Ystart,unsigned int Yend)
 2 {
 3     //ILI9163C    
 4     WriteComm(0x0037);   
 5     WriteData(Xstart);
 6 
 7     WriteComm(0x0036);   
 8     WriteData(Xend);
 9 
10     WriteComm(0x0039);   
11     WriteData(Ystart);
12 
13     WriteComm(0x0038);   
14     WriteData(Yend);
15     
16     WriteComm(0x0021);   
17     WriteData(Ystart);
18 
19     WriteComm(0x0020);   
20     WriteData(Yend);
21 
22     WriteComm(0x0022);
23 }

还真有效果!!!

当时非常激动~~~~

但是我当时用的是drawrectange测试的,刷的是纯色

集成到总工程开始刷图片问题又来了~

——虽然Y方向的AC搞定了,但是X方向存在偏移,最终导致整个图片的平移

4、再次翻几遍IC的说明,将目标锁定在初始化部分可能存在问题!

直到把该注释的初始化全部注释掉(只剩两个了),虽然发现某些命令的功效但是还是没有解决根本问题

5、尝试采用计算偏移量,预填充GRAM来抵消偏移

发现偏移规律性不明显,总是补不完全~

6、今天下午实在不能忍(我断定是屏幕厂家给了我一次品!)

于是,一封休书找到了屏幕幕后黑手——屏幕驱动IC芯片厂技术人员:

[nRF51822] 2、D-BUG之诗第7张

[nRF51822] 2、D-BUG之诗第8张

[nRF51822] 2、D-BUG之诗第9张

后来,这位技术把我拉到一个讨论组里面,转述内容省略....然后出来个大牛~

[nRF51822] 2、D-BUG之诗第10张

看到最后一句20 stax时瞬间豁然开朗~心中有无数草泥马在奔腾~

      

    《D-BUG诗》

曾经我离成功只差一步之遥,

绕了一大圈,

回到原点~

原来20、21命令一条是指明X方向的AC的值,一条指明Y方向AC的值!

当时钻进死胡同了~

硬把20、21和Y方向的start和end绑定,

却苦苦寻找X方向的start和end该怎么放!

于是乎,

明白了为什么规律老是不明显的X方向偏移,

其实就是command-20将Yend当做了Xstart,

导致了未解的偏移~

有时候,

你与你想要的只差一毫,

一时大意、一时疏忽、一时自得,

让你用千百倍懂得!

世界上本来没有坑,想的多了,也就有了坑!

BUG废除,世界又恢复了平静~

测试工程源码(一个移植demo,一个居中绘图):http://pan.baidu.com/s/1c1vlgPy

注:非常感谢该IC技术团队的热情帮忙~

@beautifulzzzz 

  2015-12-7 持续更新中~

免责声明:文章转载自《[nRF51822] 2、D-BUG之诗》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇自动化-Yaml文件读取函数封装Eclipse安装SVN插件下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Linux12-内存管理

Linux内核第12章 内核不能像用户空间那样奢侈地使用内存,内核与用户空间不同,它不具备这种能力,它不支持简单便捷的内存分配方式。比如,内核一般不能睡眠,此外处理内存分配错误对内核来说也很困难。正是因为这些限制和内存分配机制不能太复杂,所以在内核中获取内存要比在用户空间复杂得多。 12.1 页 内核把物理页作为内存管理的基本单位。尽管处理器的最小可寻址单...

mmap操作荔枝派gpio v3s Linux

1.预备知识 https://baike.baidu.com/item/mmap/1322217?fr=aladdin 大家直接看百度百科,比较清楚了。 2.代码 gpio.c #include "gpio.h" unsigned int fd; PIO_Map *PIO = NULL; unsigned int *gpio_map; unsigned...

c语言实现灰度图转换为二值图

将上篇得到的灰度图转换为二值图,读取像素数据,低于某一值置0,否则设置为255,为得到更好的效果不同图片应采用不同的值 1 /* 2 2015年6月2日11:16:22 3 灰度图转换为二值图 4 blog:http://www.cnblogs.com/wd1001/ 5 */ 6 #include<stdio.h>...

一种高效快速的内存池实现(附源码)

此算法灵感来自于apache内存池实现原理,不过读者如果没有看过apache内存池实现也无关系,因为本算法相对apache内存池算法更为简单而且易懂,个人认为某些场合也更为高效,或许真正到了apache服务器上性能不如,但是这套设计思想应该还是可以借鉴到更多场合的。 我们在调用malloc函数时,操作系统内部会查找一个所谓的空闲链表,当找到足够大的空闲空间...

利用ENGINE替换OPENSSL中的加解密算法

利用ENGINE 替换OPENSSL中的 文件: pkcs11_engine.zip 大小: 332KB 下载: 下载 一:ENGINE的目的: ENGINE是OPENSSL预留的加载第三方加密库,主要包括了动态库加载的代码和加密函数指针管理的一系列接口。如果要使用Engine(假设你已经加载上该Engine了),那么首先要Load...

SSL连接建立过程分析(6)

SSL连接建立过程分析(6)   本文档的Copyleft归yfydz所有,使用GPL发布,可以自由拷贝,转载,转载时请保持文档的完整性,严禁用于任何商业用途。msn: yfydz_no1@hotmail.com来源:http://yfydz.cublog.cn/ 2.15 SSL_write SSL结构(struct ssl_st)中的s2,s3指...