zoukankan      html  css  js  c++  java
  • Arduino驱动ILI9341彩屏(一)——颜色问题

    最近在淘宝的店铺上淘到了一块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(0,0,240,320);
      //Lcd_Write_Com(0x02c); //write_memory_start
      //digitalWrite(LCD_RS,HIGH);
      digitalWrite(LCD_CS,LOW);
    
    
      for(i=0;i<240;i++)
        for(m=0;m<320;m++)
        {
          Lcd_Write_Data(j>>8);
          Lcd_Write_Data(j);
    
        }
      digitalWrite(LCD_CS,HIGH);   
    }

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

    void LCD_Clear(unsigned int color){
      Address_set(0,0,240,320);
      digitalWrite(LCD_CS,LOW);
      for(int i=0;i<240;i++){
        for(int m=0;m<320;m++){
          Lcd_Write_Data(color>>8);
          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)
    {return r << 16 | g << 8 | b;
    }

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

    void setup()
    {
      Lcd_Init();
      LCD_Clear(RGB(255,0,0));
    }
    
    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>>8);
    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份,来分别表示红、黄、蓝的数据。

    这就出现了一个问题:

    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)
    {
      return r << 11 | g << 5 | b;
    }

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

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

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

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

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

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

    “0xf600试一下?”

    “不行,太灰了!”

    “那0xf700呢?”

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

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

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

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

    “……”

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

  • 相关阅读:
    WINCE/WM5.0如何让安装完后自动运行程序
    Android 图片透明度处理代码
    windows mobile UI 自定义开始菜单图标
    Windows mobile 6捕获键盘操作
    HTTP的post和get总结
    提供一个Windows mobile Native UI 程序,循序渐进开发,并附有代码!
    Windows Mobile 中ComboBox【下拉列表】的使用
    注册表修改今日桌面左右软键的功能
    .net compact framework 注册表操作
    两种实现Toast 的例子(图片&文字)
  • 原文地址:https://www.cnblogs.com/SirJackie/p/11917788.html
Copyright © 2011-2022 走看看