最近在淘宝的店铺上淘到了一块ILI9341的彩色液晶屏,打算研究一下如何使用。

淘宝店铺购买屏幕之后有附源代码可供下载,代码质量惨不忍睹,各种缩进不规范就不说了,先拿来试一下吧。

这是淘宝店铺代码的核心部分:

void setup()
{
  Lcd_Init();
 //LCD_Clear(0xf800);
}

void loop()
{
   LCD_Clear(0xf800);
   LCD_Clear(0x07E0);
   LCD_Clear(0x001F);
  /*
  for(int i=0;i<1000;i++)
  {
    Rect(random(300),random(300),random(300),random(300),random(65535)); // rectangle at x, y, with, hight, color
  }*/

//  LCD_Clear(0xf800);
}

代码里面的setup()和loop()是arduino特有的主函数,和普通C程序的main()函数一样。

setup()函数在开机时只运行一次,运行完之后就开始循环运行loop()函数。

程序先在setup()函数里做了一下初始化操作Lcd_Init(),接着开始连续用不同颜色清屏。

这里的LCD_Clear()就是清屏函数了,原型如下:

void LCD_Clear(unsigned int j)
{
  unsigned int i,m;
 Address_set(,,,);
  //Lcd_Write_Com(0x02c); //write_memory_start
  //digitalWrite(LCD_RS,HIGH);
  digitalWrite(LCD_CS,LOW);

  ;i<;i++)
    ;m<;m++)
    {
      Lcd_Write_Data(j>>);
      Lcd_Write_Data(j);

    }
  digitalWrite(LCD_CS,HIGH);
}

缩进不规范就不吐槽了(;へ:),连变量名都起得乱七八糟,简直惨不忍睹。稍微重写了一下函数,长这样:

void LCD_Clear(unsigned int color){
  Address_set(,,,);
  digitalWrite(LCD_CS,LOW);
  ;i<;i++){
    ;m<;m++){
      Lcd_Write_Data(color>>);
      Lcd_Write_Data(color);
    }
  }
  digitalWrite(LCD_CS,HIGH);
}

这个函数先使用Address_set()设置了刷新区域,然后把LCD_CS针脚电压拉低,之后循环写入color。

color分两次写入,一次写入高八位(16位整形前面8个bit),一次写入低八位。

看上去好像没什么问题,但loop()函数中LCD_Clear()却是直接用十六进制写入的。

写一个RGB()函数把RGB颜色转换成十六进制,不是更人性化吗?

读了一遍源代码,结果真的找到了店家的RGB函数:

int RGB(int r,int g,int b)
{ | g <<  | b;
}

还是不规范的缩进(╯︵╰)。但有总比没有好,输出红色试一下:

void setup()
{
  Lcd_Init();
  LCD_Clear(RGB(,,));
}

void loop()
{
   //nothing
}

出故障了。

Arduino重启后,屏幕输出了黑色!再试着排除一下故障,把RGB(255,0,0)改成RGB(0,255,0),输出绿色试试:

结果输出了橙色!

之后我又反复尝试了,没有一次输出正确的颜色。莫非是这个RGB()函数有问题,淘宝店铺才用十六进制数字?

再仔细推导了一下:return r << 16 | g << 8 | b;把红色左移16位,绿色左移8位,蓝色不动,所以合成的二进制应该是这样的:

RRRRRRRRGGGGGGGGBBBBBBBB

R代表红色位,G代表绿色位,B代表蓝色位,每种颜色8位,总共24位。计算了一下可能性:

总共1677万种可能,也就是1677万种颜色,这就是普通电脑的真彩颜色。但LCD_Clear()函数是这么写的:

Lcd_Write_Data(color>>);
Lcd_Write_Data(color);

总的只能写入十六个bit,也就是16位,这和24位对不上号啊?

再回头看了一下,店铺代码的setup()函数中有这样一行白色清屏指令:

//LCD_Clear(0xf800);

0xf800换算成十进制,是63488,有没有感觉很接近一个数?

没错,就是65535,单个16位无符号整数的最大储存范围。

16位整型变量,顾名思义就是用16个0和1组成的变量。可以储存的整数范围是-32768 ~ 32767,32768 + 32767刚好等于65535,换算到二进制,就是1111111111111111,16个1。

这时,真相出现了——这台机器所采用的,是16位颜色,也被成为RGB565颜色模式。

早期的16位计算机由于架构的设计,一次只能处理一个16位二进制数。而图形显示对速度要求特别高,所以一个像素必须要用一个16进制数来表示,也就是16位颜色。

如果用采用24位颜色,就需要两个16进制数,也就是2Bytes,速度就慢了一半。

而每个像素都是使用红黄蓝三基色来显示的,所以一个16进制数必须分3份,来分别表示红、黄、蓝的数据。

这就出现了一个问题:

 /  = 5.33333

红黄蓝三种颜色平均占用5.33333个bit。

可bit是计算机存储的基本单位,要么是1,要么是0,不能再分割。必须要有一种颜色多用一个位,才能充分单个利用16进制整数。

人体的绿色视锥细胞比较敏感,正好,那绿色就用6位,红色蓝色就用5位吧。

这就是著名的RGB565模式,总共能存储65535种颜色。

早期的游戏都采用这种模式,所以颜色不够丰富,很有特色:

这块ILI9341显示屏模块(注意不是ILI9341芯片本身)也刚好只有16根数据引脚,所以就采用了这种RGB565的颜色模式。

找到了问题,那就改一下程序吧:

int RGB(int r,int g,int b)
{
   | g <<  | b;
}

光改RGB()函数还不够,现在使用了RGB565模式,所以绿色范围是从0-63,红色、蓝色的范围是0-31。

所以还得改setup里面的清屏函数:

void setup()
{
  Lcd_Init();
  LCD_Clear(RGB(,,));
}

重新下载了程序,屏幕成功显示,输出了正确的绿色!⁄(⁄⁄•⁄ω⁄•⁄⁄)⁄

那么问题来了,开头店家给的LCD_Clear(0xf800)这条清屏指令,是怎么来的?毕竟他连RGB565都不知道呢!

这是我提供的一种可能性:

“0xf600试一下?”

“不行,太灰了!”

“那0xf700呢?”

“还是不行!老板,我们都试了一下午了,肯定是屏幕坏了!”

“加油,还差一点点了,肯定可以的!”

“0xf800好像还行,但是还是有点灰!”

“没关系,反正买家能点亮屏幕就行,其他的我们不管!”

“……”

所以这家淘宝店铺根本不知道自己在买什么。ヽ( ̄▽ ̄)ノ

Arduino驱动ILI9341彩屏(一)——颜色问题的更多相关文章

  1. STM32驱动ILI9341控制器控制TFTLCD显示

    STM32驱动ILI9341控制器控制TFTLCD显示 一.用STM32控制TFTLCD显示的编程方法,在编程驱动TFTLCD液晶显示器之前,我们先熟悉以下概念: 1.色彩深度,这是一个与TFTLCD ...

  2. STM32的FSMC总线驱动ili9341,掉电重启无法正常显示的问题

    问题描述 通过STM32的FSMC总线驱动ili9341,程序调试和刚下载的时候,显示完全正常.可是就在我掉电关机,重新启动的时候就完全跑飞了.这令我非常疑惑.以下是我的FSMC总线配置程序, sta ...

  3. arduino驱动安装

    方法一:使用官方提供的一键安装程序安装 打开Arduino在你电脑上的位置如果你的电脑是32位系统,就运行dpinst-x86.exe如果是64位系统,就运行dpinst-amd64.exe然后在弹出 ...

  4. 使用Arduino驱动基于ST7533芯片的TFT屏

    在合宙通信买了一个1.8寸的TFT屏,驱动芯片是ST7533,本来打算使用Air800直接驱动,但由于其他原因,放弃了.于是尝试使用arduino驱动,为了屏幕刷新速度更快,采用硬件SPI. 硬件连接 ...

  5. win8.1环境下安装arduino驱动问题解决方案

    1. Windows 键+ R, 输入 shutdown.exe /r /o /f /t 00 2.此时电脑会自动重启,进入一下画面,选择Troubleshoot (转载请注明原处:http://ww ...

  6. 最新 Arduino 驱动 12接口/户外 LED显示屏/LED点阵屏/LED单元板

    起因 现有的驱动LED显示屏的资料,比较好的只有这个.但是它驱动的是08接口的室内显示屏,而我要驱动的是12接口的户外显示屏.两种屏幕的区别在于户外屏幕点阵比较稀疏,而且二者的扫描方式,驱动方式都不太 ...

  7. 精简版、GHOST版win7,arduino驱动安装失败的解决方法分享

    arduino组件安装驱动不成功,总是提示系统找不到指定文件. 原因是因为精简版缺少了两个关键的系统文件,导致无法安装.mdmcpq.inf  和 usbser.sys 解决方案详见帖子http:// ...

  8. Arduino入门教程--课前准备--Arduino驱动安装及1.0 IDE菜单介绍

    编译器版本:Arduino 1.0实验器件:ocrobot mango控制板(Arduino兼容)一块 Arduino控制板到手后,首先需要在电脑上把驱动装上,这样才可以进行各种实验. 第一步需要把A ...

  9. Win10 上 安装Arduino 驱动 和 Arduino IDE 1.6.9

    Win10 安装Arduino IDE软件 和 驱动 在Win10 上安装最新的Arduino IDE (1.6.9安装包)很简单,并且不行要手动安装Arduino板子的驱动,整个安装过程都当前的简单 ...

随机推荐

  1. Halcon一日一练:获取孔位

    本例程是用于获取安装螺丝孔在图像中对应的坐标位置,并显示该坐标位,如上图所示. read_image(Image,'rim.png')//读取图像 dev_close_window()//关闭窗口 g ...

  2. opencv::轮廓发现(find contour in your image)

    轮廓发现(find contour) 轮廓发现是基于图像边缘提取的基础寻找对象轮廓的方法. 所以边缘提取的阈值选定会影响最终轮廓发现结果 //发现轮廓 cv::findContours( InputO ...

  3. opencv::直方图均衡化

    直方图均衡化 图像直方图: 是指对整个图像像在灰度范围内的像素值是指对整个图像像在灰度范围内的像素值(~)统计出现频率次数,据此生成的直方图,称为图像直方图-直方图. 直方图反映了图像灰度的分布情况. ...

  4. 【Leetcode 做题学算法周刊】第一期

    首发于微信公众号<前端成长记>,写于 2019.10.28 背景 本文记录刷题过程中的整个思考过程,以供参考.主要内容涵盖: 题目分析设想 编写代码验证 查阅他人解法 思考总结 目录 1. ...

  5. Mysql数据库(八)存储过程与存储函数

    一.创建存储过程与存储函数 1.创建存储过程(实现统计tb_borrow1数据表中指定图书编号的图书的借阅次数) mysql> delimiter // mysql> CREATE PRO ...

  6. Redis(一)Redis基础

    一.Redis是什么 Redis是一种基于键值对(key-value)的NoSQL数据库,与很多键值对数据库不同的是,Redis中的值可以是由string(字符串).hash(哈希).list(列表) ...

  7. Blazor之ABC

    .net core正式推出了Blazor, 正好在一个小项目里试用一下. 建立项目 因为基于WebAssemble的客户端Blazor还不是正式版, 为了避免不必要的麻烦,我试用服务端的Blazor. ...

  8. Centos6.5 忘记密码解决方法

    问题 原因  : 太久没用centos了  忘记密码了 很尴尬 快照也没说明密码.... 1.重启 centos 在开机启动的时候快速按键盘上的“E”键 或者“ESC”键(如果做不到精准快速可以在启动 ...

  9. 「2019.7.22 考试」AC和WA0一步之遥

    这卷子还是答的挺惨的. 第一题5min写完了,自认为AC(其实WA了80),第二题推了半天CRT的公式老出错结果发现是程序打错了.第三题打模拟150行结果数组没开够,开大就是0->60的转变.状 ...

  10. 详解SpringBoot应用跨域访问解决方案

    一.什么是跨域访问 说到跨域访问,必须先解释一个名词:同源策略.所谓同源策略就是在浏览器端出于安全考量,向服务端发起请求必须满足:协议相同.Host(ip)相同.端口相同的条件,否则访问将被禁止,该访 ...