zoukankan      html  css  js  c++  java
  • [原创][连载].基于SOPC的简易数码相框 Nios II SBTE部分(软件部分) TFTLCD(控制器为ILI9325)驱动

    准备资料

    [整理].ILI9325 TFT驱动中文资料

    编写驱动程序

    步骤1 将ili9325的文件夹加入APP路径

    image image

    步骤2 编写驱动文件

    时间比较紧张,我就贴出来代码,挑重点的讲几句。

    代码2.1 ili932x.h

    #ifndef ILI932X_H_
    #define ILI932X_H_
    //
    #include "my_types.h"
    #include "my_regs.h"
    //
    #define White          0xFFFF
    #define Black          0x0000
    #define Blue           0x001F
    #define Blue2          0x051F
    #define Red            0xF800
    #define Magenta        0xF81F
    #define Green          0x07E0
    #define Cyan           0x7FFF
    #define Yellow         0xFFE0
    //
    #define ID_AM    110
    //
    #define DB_o_EN  ili_DB->DIRECTION=0xFF
    #define DB_i_EN  ili_DB->DIRECTION=0x00
    //
    void ili_WrDB_2x8b(u8 DH, u8 DL);
    void ili_WrCmd(u8 DH, u8 DL);
    void ili_WrData(u8 DH, u8 DL);
    void ili_WrReg(u8 cmd, u16 data);
    void ili_WrDB_16b(u16 data);
    //
    void ili_DelayMs(u32 n);
    void ili_Initial(void);
    void ili_SetCursor(u8 x, u16 y);
    void ili_SetDispArea(u16 x0, u16 y0, u8 xLength, u16 yLength, u16 xOffset, u16 yOffset);
    void ili_ClearScreen(u32 bColor);
    //
    void ili_PlotPoint(u8 x, u16 y, u16 color);
    void ili_PlotPixel(u8 x, u16 y, u16 color);
    void ili_PlotBigPoint(u8 x, u16 y, u16 color);
    //
    void ili_PutAscii_8x16(u16 x, u16 y, uc8 c, u32 fColor, u32 bColor);
    void ili_PutGb_16x16(u16 x, u16 y, uc8 c[2], u32 fColor, u32 bColor);
    void ili_PutString(u16 x, u16 y, uc8 *s, u32 fColor, u32 bColor);
    //
    void ili_DispColorBar(void);
    //
    #endif /* ILI932X_H_ */

    注意第19~20行,定义两个宏来操纵8位DB双向总线的方向。

    代码2.2 ili_932x.c

    #include "ili932x.h"
    #include "unistd.h"       // usleep()
    #include "ascii_8x16.h"   // ascii码字库
    #include "GB16.h"         // 汉字字库
    
    
    // 8位总线模式,通过两次写操作写入高8位和低8位
    void ili_WrDB_2x8b(u8 DH, u8 DL)
    {    
      ili_DB->DATA=DH;    
      ili_nWR=0;
        ili_nWR=1;
        ili_DB->DATA=DL;    
      ili_nWR=0;
        ili_nWR=1;
    }
    
    
    // 写命令
    void ili_WrCmd(u8 DH, u8 DL)
    {
      ili_RS=0;  
      ili_WrDB_2x8b(DH, DL);
    }
    
    
    // 写数据
    void ili_WrData(u8 DH, u8 DL)
    {
      ili_RS=1;
      ili_WrDB_2x8b(DH, DL);
    }
    
    
    // 向DB总线写数据
    void ili_WrDB_16b(u16 data)
    {
      ili_WrData(data>>8, data);
    }
    
    
    // 写寄存器
    void ili_WrReg(u8 cmd, u16 data)
    {
      ili_WrCmd(0x00, cmd);
      ili_WrDB_16b(data);
    }
    
    
    // 延时ms
    void ili_DelayMs(u32 n)
    {
      usleep(n*1000);
    }
    
    
    // ILI93525初始化
    void ili_Initial(void)
    { 
      // 硬件复位
      ili_nRST=0;
      ili_DelayMs(1);
      ili_nRST=1;
      // 打开片选,输出使能
      ili_nCS=0;
      DB_o_EN;
      //
      ili_WrReg(0xE3, 0x3008);
      ili_WrReg(0xE7, 0x0012);
      ili_WrReg(0xEF, 0x1231); // Set the internal timing
      ili_WrReg(0x01, 0x0000); // Set SS and SM bit
      ili_WrReg(0x02, 0x0700); // Set 1 line inversion
      // 屏幕旋转控制
    #if   ID_AM==000
      ili_WrReg(0x03, 0x1000); // TRI=0, DFM=x, BGR=0, HWM=0, ORG=0, I/D[1:0]=00, AM=0
    #elif ID_AM==001
      ili_WrReg(0x03, 0x1008); // TRI=0, DFM=x, BGR=0, HWM=0, ORG=0, I/D[1:0]=00, AM=0
    #elif ID_AM==010
      ili_WrReg(0x03, 0x1010); // TRI=0, DFM=x, BGR=0, HWM=0, ORG=0, I/D[1:0]=01, AM=0
    #elif ID_AM==011
      ili_WrReg(0x03, 0x1018); // TRI=0, DFM=x, BGR=0, HWM=0, ORG=0, I/D[1:0]=01, AM=1
    #elif ID_AM==100
      ili_WrReg(0x03, 0x1020); // TRI=0, DFM=x, BGR=0, HWM=0, ORG=0, I/D[1:0]=10, AM=0
    #elif ID_AM==101
      ili_WrReg(0x03, 0x1028); // TRI=0, DFM=x, BGR=0, HWM=0, ORG=0, I/D[1:0]=10, AM=1
    #elif ID_AM==110
      ili_WrReg(0x03, 0x1030); // TRI=0, DFM=x, BGR=0, HWM=0, ORG=0, I/D[1:0]=11, AM=0
    #elif ID_AM==111
      ili_WrReg(0x03, 0x1038); // TRI=0, DFM=x, BGR=0, HWM=0, ORG=0, I/D[1:0]=11, AM=1
    #endif
      ili_WrReg(0x04, 0x0000); // Resize register
      ili_WrReg(0x08, 0x0404); // Set the back porch and front porch
      ili_WrReg(0x09, 0x0000); // Set non-display area refresh cycle ISC[3:0]
      ili_WrReg(0x0A, 0x0000); // FMARK function
      ili_WrReg(0x0C, 0x0000); // RGB interface setting
      ili_WrReg(0x0D, 0x0000); // Frame marker Position
      ili_WrReg(0x0F, 0x0000); // RGB interface polarity
      // Power on sequence VGHVGL
      ili_WrReg(0x10, 0x0000); // SAP, BT[3:0], AP, DSTB, SLP, STB
      ili_WrReg(0x11, 0x0007); // DC1[2:0], DC0[2:0], VC[2:0]
      ili_WrReg(0x12, 0x0000); // VREG1OUT voltage
      ili_WrReg(0x13, 0x1300); // VDV[4:0] for VCOM amplitude
      ili_WrReg(0x07, 0x0001);
      ili_DelayMs(50);         // Dis-charge capacitor power voltage
      ili_WrReg(0x10, 0x1590); // SAP, BT[3:0], AP, DSTB, SLP, STB
      ili_WrReg(0x11, 0x0227); // DC1[2:0], DC0[2:0], VC[2:0]
      ili_DelayMs(50);
      ili_WrReg(0x12, 0x001E); // Internal reference voltage= Vci;
      ili_DelayMs(50);
      ili_WrReg(0x13, 0x1500); // Set VDV[4:0] for VCOM amplitude
      ili_WrReg(0x29, 0x0026); // Set VCM[5:0] for VCOMH
      ili_WrReg(0x2B, 0x000F); // Set Frame Rate
      ili_DelayMs(50);
      ili_WrReg(0x20, 0x0000);
      ili_WrReg(0x21, 0x013f);
      // GRAM起始位置
    #if   ID_AM==000
      ili_WrReg(0x20, 0x00EF);
      ili_WrReg(0x21, 0x013F);
    #elif ID_AM==001
      ili_WrReg(0x20, 0x00EF);
      ili_WrReg(0x21, 0x013F);
    #elif ID_AM==010
      ili_WrReg(0x20, 0x0000);
      ili_WrReg(0x21, 0x013F);
    #elif ID_AM==011
      ili_WrReg(0x20, 0x0000);
      ili_WrReg(0x21, 0x013F);
    #elif ID_AM==100
      ili_WrReg(0x20, 0x00EF);
      ili_WrReg(0x21, 0x0000);
    #elif ID_AM==101
      ili_WrReg(0x20, 0x00EF);
      ili_WrReg(0x21, 0x0000);
    #elif ID_AM==110
      ili_WrReg(0x20, 0x0000);
      ili_WrReg(0x21, 0x0000);
    #elif ID_AM==111
      ili_WrReg(0x20, 0x0000);
      ili_WrReg(0x21, 0x0000);
    #endif
      // Adjust the Gamma Curve
      ili_WrReg(0x30, 0x0007);
      ili_WrReg(0x31, 0x0007);
      ili_WrReg(0x32, 0x0107);
      ili_WrReg(0x35, 0x0206);
      ili_WrReg(0x36, 0x0406);
      ili_WrReg(0x37, 0x0101);
      ili_WrReg(0x38, 0x0101);
      ili_WrReg(0x39, 0x0207);
      ili_WrReg(0x3C, 0x0504);
      ili_WrReg(0x3D, 0x0806);
      // Set GRAM area
      ili_WrReg(0x50, 0x0000); // Horizontal GRAM Start Address
      ili_WrReg(0x51, 0x00EF); // Horizontal GRAM End Address
      ili_WrReg(0x52, 0x0000); // Vertical GRAM Start Address
      ili_WrReg(0x53, 0x013F); // Vertical GRAM Start Address
      ili_WrReg(0x60, 0x2700); // Gate Scan Line
      ili_WrReg(0x61, 0x0001); // NDL,VLE, REV
      ili_WrReg(0x6A, 0x0000); // Set scrolling line
      // Partial Display Control
      ili_WrReg(0x80, 0x0000);
      ili_WrReg(0x81, 0x0000);
      ili_WrReg(0x82, 0x0000);
      ili_WrReg(0x83, 0x0000);
      ili_WrReg(0x84, 0x0000);
      ili_WrReg(0x85, 0x0000);
      // Panel Control
      ili_WrReg(0x90, 0x0010);
      ili_WrReg(0x92, 0x0600);
      ili_WrReg(0x93, 0x0003);
      ili_WrReg(0x95, 0x0110);
      ili_WrReg(0x97, 0x0000);
      ili_WrReg(0x98, 0x0000);
      ili_WrReg(0x07, 0x0173); // 262K color and display ON
      // 关闭片选
      ili_nCS=1;
    }
    
    
    // 设定Cursor
    void ili_SetCursor(u8 x, u16 y)
    {
      ili_WrReg(0x20, x);
      ili_WrReg(0x21, y);
    }
    
    
    // 设定显示区域
    void ili_SetDispArea(u16 x0, u16 y0, u8 xLength, u16 yLength, u16 xOffset, u16 yOffset)
    {
    #if ID_AM==000
      ili_SetCursor(x0+xLength-1+xOffset, y0+yLength-1+yOffset);
    #elif ID_AM==001
      ili_SetCursor(x0+xLength-1+xOffset, y0+yLength-1+yOffset);
    #elif ID_AM==010
      ili_SetCursor(x0+xOffset, y0+yLength-1+yOffset);
    #elif ID_AM==011
      ili_SetCursor(x0+xOffset, y0+yLength-1+yOffset);
    #elif ID_AM==100
      ili_SetCursor(x0+xLength-1+xOffset, y0+yOffset);
    #elif ID_AM==101
      ili_SetCursor(x0+xLength-1+xOffset, y0+yOffset);
    #elif ID_AM==110
      ili_SetCursor(x0+xOffset, y0+yOffset);
    #elif ID_AM==111
      ili_SetCursor(x0+xOffset, y0+yOffset);
    #endif
      ili_WrReg(0x50, x0+xOffset);             // 水平 GRAM起始位置
      ili_WrReg(0x51, x0+xLength-1+xOffset);   // 水平GRAM终止位置
      ili_WrReg(0x52, y0+yOffset);             // 垂直GRAM起始位置
      ili_WrReg(0x53, y0+yLength-1+yOffset);   // 垂直GRAM终止位置
      ili_WrCmd(0x00, 0x22);
    }          
    
    
    // 清屏
    void ili_ClearScreen(u32 bColor)
    {
      u32 i;
    
      ili_nCS=0;
      DB_o_EN;
    
      ili_SetDispArea(0, 0, 240, 320, 0, 0);
      for (i=0; i<76800; i++) ili_WrDB_16b(bColor);
    
      ili_nCS=1;
    }
    
    
    // 画点(单次操作)
    void ili_PlotPoint(u8 x, u16 y, u16 color)
    {
      ili_nCS=0;
      DB_o_EN;
    
      ili_SetCursor(x, y);
      ili_WrCmd(0x00, 0x22);
      ili_WrDB_16b(color);
    
      ili_nCS=1;
    }
    
    
    // 画点(连续操作的一部分)
    void ili_PlotPixel(u8 x, u16 y, u16 color)
    {
      ili_SetCursor(x, y);
      ili_WrCmd(0x00, 0x22);
      ili_WrDB_16b(color);
    }
    
    
    // 画一个大点
    void ili_PlotBigPoint(u8 x, u16 y, u16 color)
    {
      u8 i, j;
      ili_nCS=0;
      DB_o_EN;
      for(i=0; i<3; i++)
      {
        for(j=0; j<3; j++) ili_PlotPixel(x+i, y+j, color);
      }
      ili_nCS=1;
    }
    
    
    // 打印ASCII码(8x16)
    void ili_PutAscii_8x16(u16 x, u16 y, uc8 c, u32 fColor, u32 bColor)
    {
      u32 i, j;
      u8 temp;
    
      ili_nCS=0;
      DB_o_EN;
    
      ili_SetDispArea(x, y, 8, 16, 0, 0);
      for(i=0; i<16; i++) 
      {
        temp = ascii_8x16_tab[c*16+i];
        for(j=0; j<8; j++) 
        {
          if((temp&0x80) == 0x80) 
            ili_WrDB_16b(fColor);
          else
            ili_WrDB_16b(bColor);
          temp <<= 1;
        }
      }
    
      ili_nCS=1;
    }
    
    
    // 打印汉字(16x16)
    void ili_PutGB16(u16 x, u16 y, uc8 c[2], u32 fColor, u32 bColor)
    {
      u32 i, j, k;
      u16 temp;
    
      ili_nCS=0;
      DB_o_EN;
    
      ili_SetDispArea(x, y, 16, 16, 0, 0);
      for(k=0; k<64; k++) // 64表示自建汉字库中的个数,循环查询内码
      { 
        if ( (GB16[k].Index[0]==c[0])
          && (GB16[k].Index[1]==c[1]) )
        { 
          for(i=0; i<32; i++) 
          {
            temp = GB16[k].Msk[i];
            for(j=0; j<8; j++) 
            {
              if((temp&0x80)==0x80) 
                ili_WrDB_16b(fColor);
              else
                ili_WrDB_16b(bColor);
              temp <<= 1;
            } 
          }
        }  
      }
    
      ili_nCS=1;
    }
    
    
    // 打印字符串
    void ili_PutString(u16 x, u16 y, uc8 *s, u32 fColor, u32 bColor)
    {
      u8 l=0;
      while(*s != '\0')
      {
        if(*s < 0x80)
        {
          ili_PutAscii_8x16(x+l*8, y, *s, fColor, bColor);
          s++; 
          l++;
        }
        else
        {
          ili_PutGB16(x+l*8, y, (u8*)s, fColor, bColor);
          s+=2;
          l+=2;
        }
      }
    }
    
    
    // 彩条测试
    void ili_DispColorBar(void)
    {
      u16 V, H;
    
      ili_nCS=0;
      DB_o_EN;
    
      ili_SetDispArea(0, 0, 240, 320, 0, 0);
      for(H=0; H<240; H++)
      {
        for(V=0; V<40; V++) ili_WrDB_16b(White);
      }
      for(H=0;H<240;H++)
      {
        for(V=40; V<80; V++) ili_WrDB_16b(Black);
      }
      for(H=0;H<240;H++)
      {
        for(V=80; V<120; V++) ili_WrDB_16b(Blue);
      }
      for(H=0;H<240;H++)
      {
        for(V=120; V<160; V++) ili_WrDB_16b(Red);
      }
      for(H=0;H<240;H++)
      {
        for(V=160; V<200; V++) ili_WrDB_16b(Magenta);
      }
      for(H=0;H<240;H++)
      {
        for(V=200; V<240; V++) ili_WrDB_16b(Green);
      }
      for(H=0;H<240;H++)
      {
        for(V=240; V<280; V++) ili_WrDB_16b(Cyan);
      }
      for(H=0;H<240;H++)
      {
        for(V=280;V<320;V++) ili_WrDB_16b(Yellow);
      }
    
      ili_nCS=1;
    }

    注意几个地方:

    1. 初始化函数内的void ili_Initial(void)的硬件复位,nRST一定要拉低足够长时间再拉高,此处取1ms,否则会出现白屏现象。

      ili_nRST=0;
      ili_DelayMs(1);
      ili_nRST=1;

    2. 为了减少DB双向总线的方向切换次数及打开关闭nCS片选的此处,每次操作中只设定一次DB方向,且只打开关闭片选一次。比方在初始化函数内的void ili_Initial(void)内。

      // 打开片选,输出使能
      ili_nCS=0;
      DB_o_EN;
      // 关闭片选
      ili_nCS=1;

    因此,特别需要注意,写一组或一个寄存器前后,或写一个或一组数据到DB总线前后,只做一次设定DB方向和打开关闭片选动作。此外,千万不要将nCS永远拉低,浪费功率,最好用的时候打开,不用的时候关断。

    3. 连续重复某个动作的时候,也执行第2条。比方说第246~266行,ili_PlotPixel()函数的引用。

    步骤3 测试ILI9325驱动

    代码3.1 main.c

    #include <stdio.h>                    // printf()
    #include <unistd.h>                   // usleep()
    #include "my_types.h"                 // 数据类型
    #include "debug.h"                    // debug
    #include "sd_card.h"                  // sd卡
    #include "ili932x.h"                  // ili9325
    
    
    //#define ENABLE_APP_DEBUG // turn on debug message
    #ifdef ENABLE_APP_DEBUG
        #define APP_DEBUG(x)    DEBUG(x)
    #else
        #define APP_DEBUG(x)
    #endif
    
    
    int main(void)
    {
      ili_Initial();            // 初始化ILI9325
      ili_DispColorBar();       // 彩条测试
      while(1);
      return 0;
    }

    测试效果如下(50¥的摄像头拍的,凑活看吧)。

    image 

    源码下载

    lcd_at_nios_nii_part.zip

    目录

    [原创][连载].基于SOPC的简易数码相框 -  Quartus II部分(硬件部分)

    [原创][连载].基于SOPC的简易数码相框 -  Nios II SBTE部分(软件部分)-  配置工作

    [原创][连载].基于SOPC的简易数码相框 -  Nios II SBTE部分(软件部分)-  SD卡(SPI模式)驱动

    [原创][连载].基于SOPC的简易数码相框 -  Nios II SBTE部分(软件部分)-  TFT-LCD(控制器为ILI9325)驱动

    [原创][连载].基于SOPC的简易数码相框 -  Nios II SBTE部分(软件部分)-  从SD卡内读取图片文件,然后显示在TFT-LCD上

    [原创][连载].基于SOPC的简易数码相框 -  Nios II SBTE部分(软件部分)-  优化工作

    [原创][连载].基于SOPC的简易数码相框 -  Nios II SBTE部分(软件部分)-  ADS7843触摸屏驱动测试

  • 相关阅读:
    949. Largest Time for Given Digits
    450. Delete Node in a BST
    983. Minimum Cost For Tickets
    16. 3Sum Closest java solutions
    73. Set Matrix Zeroes java solutions
    347. Top K Frequent Elements java solutions
    215. Kth Largest Element in an Array java solutions
    75. Sort Colors java solutions
    38. Count and Say java solutions
    371. Sum of Two Integers java solutions
  • 原文地址:https://www.cnblogs.com/yuphone/p/1918307.html
Copyright © 2011-2022 走看看