美文网首页C语言&嵌入式
【STM32学习记录】4、1.44寸TFT液晶屏显示字符、汉字和

【STM32学习记录】4、1.44寸TFT液晶屏显示字符、汉字和

作者: AXYZdong | 来源:发表于2020-03-28 20:54 被阅读0次

    Author:AXYZdong
    自动化专业 工科男
    有一点思考,有一点想法,有一点理性

    概述

    MCU:某宝的STM32F407VET6最小系统板,点此详见
    外部资源:某宝的TFT液晶屏(下面会附上图片)
    点此下载完整工程
    ==文末有惊喜,希望可以坚持看下去==

    4.1硬件设计

    在这里插入图片描述
    Pin 引脚说明
    VCC 电源正
    GND 电源负
    NC no connect ,不需要接线
    LED 背光控制信号
    CLK(SCL) SPI总线时钟引脚
    SDI(SDA) SPI总线数据引脚
    RS 寄存器/数据选择控制引脚
    RST 复位控制引脚
    CS 片选控制引脚

    这里有个小疑问:为啥引出两个GND和NC?不知道制造商怎么想的?有知道的小伙伴可以私信我呢。

    要注意一下,NC这个引脚是不需要接线的。
    LED:背光控制信号,如果不需要控制时,接电源+3.3V
    ==关键词:SPI总线驱动==

    4.2软件设计

    4.2.1编程要点

    1、初始化GPIO口来模拟SPI,每个人设置的GPIO口不同,开发板与TFT接线也会不同。之后再设置液晶屏初始化。

    2、TFT驱动程序,这里的驱动程序可以参考别人写的,然后自己再加以修改或者补充。驱动程序包括:向TFT写数据,设置TFT显示区域、设置TFT某点的颜色等等,具体的在代码里注释说明。

    3、取模,包括文字取模和图片取模。根据自己的需要来取模。需要取模软件的可以私信我。
    (PS:其实这几个步骤和上一篇文章的OLED差不多的啦,只是修(fu)改(zhi)了一下)

    4.2.2代码说明

    1、宏定义Lcd_Driver.h

    #define RED       0xf800
    #define GREEN     0x07e0
    #define BLUE      0x001f
    #define WHITE     0xffff
    #define BLACK     0x0000
    #define YELLOW  0xFFE0
    #define GRAY0   0xEF7D          //灰色0 3165 00110 001011 00101
    #define GRAY1   0x8410          //灰色1 00000 000000 00000
    #define GRAY2   0x4208          //灰色2  1111111111011111
    
    #define LCD_CTRL        GPIOB       //定义TFT数据端口
    #define LCD_LED         GPIO_Pin_9  //MCU_PB9--->>TFT --BL
    #define LCD_SCL         GPIO_Pin_10 //PB13--->>TFT --SCL/SCK
    #define LCD_SDA         GPIO_Pin_12 //PB15 MOSI--->>TFT --SDA/DIN
    #define LCD_RS          GPIO_Pin_11 //PB11--->>TFT --RS/DC
    #define LCD_RST           GPIO_Pin_14   //PB10--->>TFT --RST
    #define LCD_CS          GPIO_Pin_13  //MCU_PB11--->>TFT --CS/CE
    
    //#define LCD_CS_SET(x) LCD_CTRL->ODR=(LCD_CTRL->ODR&~LCD_CS)|(x ? LCD_CS:0)
    //液晶控制口置1操作语句宏定义
    
    #define LCD_CS_SET      LCD_CTRL->BSRRL=LCD_CS    
    #define LCD_RS_SET      LCD_CTRL->BSRRL=LCD_RS    
    #define LCD_SDA_SET     LCD_CTRL->BSRRL=LCD_SDA    
    #define LCD_SCL_SET     LCD_CTRL->BSRRL=LCD_SCL    
    #define LCD_RST_SET     LCD_CTRL->BSRRL=LCD_RST    
    #define LCD_LED_SET     LCD_CTRL->BSRRL=LCD_LED   
    
    //液晶控制口置0操作语句宏定义
    #define LCD_CS_CLR      LCD_CTRL->BSRRH=LCD_CS    
    #define LCD_RS_CLR      LCD_CTRL->BSRRH=LCD_RS    
    #define LCD_SDA_CLR     LCD_CTRL->BSRRH=LCD_SDA    
    #define LCD_SCL_CLR     LCD_CTRL->BSRRH=LCD_SCL    
    #define LCD_RST_CLR     LCD_CTRL->BSRRH=LCD_RST    
    #define LCD_LED_CLR     LCD_CTRL->BSRRH=LCD_LED 
    #define LCD_DATAOUT(x) LCD_DATA->ODR=x; //数据输出
    #define LCD_DATAIN     LCD_DATA->IDR;   //数据输入
    #define LCD_WR_DATA(data){\
    
    LCD_RS_SET;\
    LCD_CS_CLR;\
    LCD_DATAOUT(data);\
    LCD_WR_CLR;\
    LCD_WR_SET;\
    LCD_CS_SET;\
    } 
    
    void LCD_GPIO_Init(void);
    void Lcd_WriteIndex(u8 Index);
    void Lcd_WriteData(u8 Data);
    void Lcd_WriteReg(u8 Index,u8 Data);
    u16 Lcd_ReadReg(u8 LCD_Reg);
    void Lcd_Reset(void);
    void Lcd_Init(void);
    void Lcd_Clear(u16 Color);
    void Lcd_SetXY(u16 x,u16 y);
    void Gui_DrawPoint(u16 x,u16 y,u16 Data);
    unsigned int Lcd_ReadPoint(u16 x,u16 y);
    void Lcd_SetRegion(u16 x_start,u16 y_start,u16 x_end,u16 y_end);
    void LCD_WriteData_16Bit(u16 Data);
    
    

    2、TFT驱动文件Lcd_Driver.c

    #include "stm32f4xx.h"
    #include "Lcd_Driver.h"
    #include "LCD_Config.h"
    #include "delay.h"
    
    //本程序使用的是模拟SPI接口驱动
    //可自由更改接口IO配置,使用任意最少4 IO即可完成液晶驱动显示
    
    接口定义在Lcd_Driver.h内定义,请根据接线修改并修改相应IO初始化LCD_GPIO_Init()
    #define LCD_CTRL        GPIOB       //定义TFT数据端口
    #define LCD_LED         GPIO_Pin_9  //PB9--->>TFT --BL
    #define LCD_RS          GPIO_Pin_10 //PB11--->>TFT --RS/DC
    #define LCD_CS          GPIO_Pin_11  //PB11--->>TFT --CS/CE
    #define LCD_RST             GPIO_Pin_12 //PB10--->>TFT --RST
    #define LCD_SCL         GPIO_Pin_13 //PB13--->>TFT --SCL/SCK
    #define LCD_SDA         GPIO_Pin_15 //PB15 MOSI--->>TFT --SDA/DIN
    *******************************************************************************/
    
    //液晶IO初始化配置
    void LCD_GPIO_Init(void)
    {
        GPIO_InitTypeDef  GPIO_InitStructure;      
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB ,ENABLE);   
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9| GPIO_Pin_10| GPIO_Pin_11| GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14| GPIO_Pin_15;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
          
    }
    //向SPI总线传输一个8位数据
    void  SPI_WriteData(u8 Data)
    {
        unsigned char i=0;
        for(i=8;i>0;i--)
        {
            if(Data&0x80)   
          LCD_SDA_SET; //输出数据
          else LCD_SDA_CLR;
           
          LCD_SCL_CLR;       
          LCD_SCL_SET;
          Data<<=1; 
        }
    }
    //向液晶屏写一个8位指令
    void Lcd_WriteIndex(u8 Index)
    {
       //SPI 写命令时序开始
       LCD_CS_CLR;
       LCD_RS_CLR;
         SPI_WriteData(Index);
       LCD_CS_SET;
    }
    
    //向液晶屏写一个8位数据
    void Lcd_WriteData(u8 Data)
    {
       LCD_CS_CLR;
       LCD_RS_SET;
       SPI_WriteData(Data);
       LCD_CS_SET; 
    }
    //向液晶屏写一个16位数据
    void LCD_WriteData_16Bit(u16 Data)
    {
       LCD_CS_CLR;
       LCD_RS_SET;
         SPI_WriteData(Data>>8);      //写入高8位数据
         SPI_WriteData(Data);           //写入低8位数据
       LCD_CS_SET; 
    }
    
    void Lcd_WriteReg(u8 Index,u8 Data)
    {
        Lcd_WriteIndex(Index);
      Lcd_WriteData(Data);
    }
    
    void Lcd_Reset(void)
    {
        LCD_RST_CLR;
        delay_ms(100);
        LCD_RST_SET;
        delay_ms(50);
    }
    
    //LCD Init For 1.44Inch LCD Panel with ST7735R.
    void Lcd_Init(void)
    {   
        LCD_GPIO_Init();
        Lcd_Reset(); //Reset before LCD Init.
    
        //LCD Init For 1.44Inch LCD Panel with ST7735R.
        Lcd_WriteIndex(0x11);//Sleep exit 
        delay_ms (120);
            
        //ST7735R Frame Rate
        Lcd_WriteIndex(0xB1); 
        Lcd_WriteData(0x01); 
        Lcd_WriteData(0x2C); 
        Lcd_WriteData(0x2D); 
    
        Lcd_WriteIndex(0xB2); 
        Lcd_WriteData(0x01); 
        Lcd_WriteData(0x2C); 
        Lcd_WriteData(0x2D); 
    
        Lcd_WriteIndex(0xB3); 
        Lcd_WriteData(0x01); 
        Lcd_WriteData(0x2C); 
        Lcd_WriteData(0x2D); 
        Lcd_WriteData(0x01); 
        Lcd_WriteData(0x2C); 
        Lcd_WriteData(0x2D); 
        
        Lcd_WriteIndex(0xB4); //Column inversion 
        Lcd_WriteData(0x07); 
        
        //ST7735R Power Sequence
        Lcd_WriteIndex(0xC0); 
        Lcd_WriteData(0xA2); 
        Lcd_WriteData(0x02); 
        Lcd_WriteData(0x84); 
        Lcd_WriteIndex(0xC1); 
        Lcd_WriteData(0xC5); 
    
        Lcd_WriteIndex(0xC2); 
        Lcd_WriteData(0x0A); 
        Lcd_WriteData(0x00); 
    
        Lcd_WriteIndex(0xC3); 
        Lcd_WriteData(0x8A); 
        Lcd_WriteData(0x2A); 
        Lcd_WriteIndex(0xC4); 
        Lcd_WriteData(0x8A); 
        Lcd_WriteData(0xEE); 
        
        Lcd_WriteIndex(0xC5); //VCOM 
        Lcd_WriteData(0x0E); 
        
        Lcd_WriteIndex(0x36); //MX, MY, RGB mode 
        Lcd_WriteData(0xC8); 
        
        //ST7735R Gamma Sequence
        Lcd_WriteIndex(0xe0); 
        Lcd_WriteData(0x0f); 
        Lcd_WriteData(0x1a); 
        Lcd_WriteData(0x0f); 
        Lcd_WriteData(0x18); 
        Lcd_WriteData(0x2f); 
        Lcd_WriteData(0x28); 
        Lcd_WriteData(0x20); 
        Lcd_WriteData(0x22); 
        Lcd_WriteData(0x1f); 
        Lcd_WriteData(0x1b); 
        Lcd_WriteData(0x23); 
        Lcd_WriteData(0x37); 
        Lcd_WriteData(0x00);    
        Lcd_WriteData(0x07); 
        Lcd_WriteData(0x02); 
        Lcd_WriteData(0x10); 
    
        Lcd_WriteIndex(0xe1); 
        Lcd_WriteData(0x0f); 
        Lcd_WriteData(0x1b); 
        Lcd_WriteData(0x0f); 
        Lcd_WriteData(0x17); 
        Lcd_WriteData(0x33); 
        Lcd_WriteData(0x2c); 
        Lcd_WriteData(0x29); 
        Lcd_WriteData(0x2e); 
        Lcd_WriteData(0x30); 
        Lcd_WriteData(0x30); 
        Lcd_WriteData(0x39); 
        Lcd_WriteData(0x3f); 
        Lcd_WriteData(0x00); 
        Lcd_WriteData(0x07); 
        Lcd_WriteData(0x03); 
        Lcd_WriteData(0x10);  
        
        Lcd_WriteIndex(0x2a);
        Lcd_WriteData(0x00);
        Lcd_WriteData(0x00);
        Lcd_WriteData(0x00);
        Lcd_WriteData(0x7f);
    
        Lcd_WriteIndex(0x2b);
        Lcd_WriteData(0x00);
        Lcd_WriteData(0x00);
        Lcd_WriteData(0x00);
        Lcd_WriteData(0x9f);
        
        Lcd_WriteIndex(0xF0); //Enable test command  
        Lcd_WriteData(0x01); 
        Lcd_WriteIndex(0xF6); //Disable ram power save mode 
        Lcd_WriteData(0x00); 
        
        Lcd_WriteIndex(0x3A); //65k mode 
        Lcd_WriteData(0x05); 
        
        
        Lcd_WriteIndex(0x29);//Display on    
    }
    
    
    /*************************************************
    函数名:LCD_Set_Region
    功能:设置lcd显示区域,在此区域写点数据自动换行
    入口参数:xy起点和终点
    返回值:无
    *************************************************/
    void Lcd_SetRegion(u16 x_start,u16 y_start,u16 x_end,u16 y_end)
    {       
        Lcd_WriteIndex(0x2a);
        Lcd_WriteData(0x00);
        Lcd_WriteData(x_start+2);
        Lcd_WriteData(0x00);
        Lcd_WriteData(x_end+2);
    
        Lcd_WriteIndex(0x2b);
        Lcd_WriteData(0x00);
        Lcd_WriteData(y_start+3);
        Lcd_WriteData(0x00);
        Lcd_WriteData(y_end+3);
        
        Lcd_WriteIndex(0x2c);
    
    }
    
    /*************************************************
    函数名:LCD_Set_XY
    功能:设置lcd显示起始点
    入口参数:xy坐标
    返回值:无
    *************************************************/
    void Lcd_SetXY(u16 x,u16 y)
    {
        Lcd_SetRegion(x,y,x,y);
    }
    
        
    /*************************************************
    函数名:LCD_DrawPoint
    功能:画一个点
    入口参数:无
    返回值:无
    *************************************************/
    void Gui_DrawPoint(u16 x,u16 y,u16 Data)
    {
        Lcd_SetRegion(x,y,x+1,y+1);
        LCD_WriteData_16Bit(Data);
    
    }    
    
    /*****************************************
     函数功能:读TFT某一点的颜色                          
     出口参数:color  点颜色值                                 
    ******************************************/
    unsigned int Lcd_ReadPoint(u16 x,u16 y)
    {
      unsigned int Data;
      Lcd_SetXY(x,y);
    
      //Lcd_ReadData();//丢掉无用字节
      //Data=Lcd_ReadData();
      Lcd_WriteData(Data);
      return Data;
    }
    /*************************************************
    函数名:Lcd_Clear
    功能:全屏清屏函数
    入口参数:填充颜色COLOR
    返回值:无
    *************************************************/
    void Lcd_Clear(u16 Color)               
    {   
       unsigned int i,m;
       Lcd_SetRegion(0,0,X_MAX_PIXEL-1,Y_MAX_PIXEL-1);
       Lcd_WriteIndex(0x2C);
       for(i=0;i<X_MAX_PIXEL;i++)
        for(m=0;m<Y_MAX_PIXEL;m++)
        {   
            LCD_WriteData_16Bit(Color);
        }   
    }
    

    3、延时函数文件delay.c

    #include "stm32f4xx.h"
    #include "delay.h" 
    static u8  fac_us=0;//us延时倍乘数
    static u16 fac_ms=0;//ms延时倍乘数
    //初始化延迟函数
    //SYSTICK的时钟固定为HCLK时钟的1/8
    //SYSCLK:系统时钟
    void delay_init(u8 SYSCLK)
    {
        SysTick->CTRL&=0xfffffffb;//bit2清空,选择外部时钟  HCLK/8
        fac_us=SYSCLK/8;            
        fac_ms=(u16)fac_us*1000;
    }                                   
    //延时nms
    //注意nms的范围
    //SysTick->LOAD为24位寄存器,所以,最大延时为:
    //nms<=0xffffff*8*1000/SYSCLK
    //SYSCLK单位为Hz,nms单位为ms
    //对72M条件下,nms<=1864 
    void delay_ms(u16 nms)
    {                 
        u32 temp;          
        SysTick->LOAD=(u32)nms*fac_ms;//时间加载(SysTick->LOAD为24bit)
        SysTick->VAL =0x00;           //清空计数器
        SysTick->CTRL=0x01 ;          //开始倒数  
        do
        {
            temp=SysTick->CTRL;
        }
        while(temp&0x01&&!(temp&(1<<16)));//等待时间到达   
        SysTick->CTRL=0x00;       //关闭计数器
        SysTick->VAL =0X00;       //清空计数器           
    }   
    //延时nus
    //nus为要延时的us数.                                             
    void delay_us(u32 nus)
    {       
        u32 temp;            
        SysTick->LOAD=nus*fac_us; //时间加载             
        SysTick->VAL=0x00;        //清空计数器
        SysTick->CTRL=0x01 ;      //开始倒数     
        do
        {
            temp=SysTick->CTRL;
        }
        while(temp&0x01&&!(temp&(1<<16)));//等待时间到达   
        SysTick->CTRL=0x00;       //关闭计数器
        SysTick->VAL =0X00;       //清空计数器    
    }
    

    4、图像显示驱动文件GUI.c

    #include "stm32f4xx.h"
    #include "Lcd_Driver.h"
    #include "GUI.h"
    #include "delay.h"
    #include "font.h"
    //从ILI93xx读出的数据为GBR格式,而我们写入的时候为RGB格式。
    //通过该函数转换
    //c:GBR格式的颜色值
    //返回值:RGB格式的颜色值
    u16 LCD_BGR2RGB(u16 c)
    {
      u16  r,g,b,rgb;   
      b=(c>>0)&0x1f;
      g=(c>>5)&0x3f;
      r=(c>>11)&0x1f;    
      rgb=(b<<11)+(g<<5)+(r<<0);         
      return(rgb);
    
    }
    void Gui_Circle(u16 X,u16 Y,u16 R,u16 fc) 
    {//Bresenham算法 
        unsigned short  a,b; 
        int c; 
        a=0; 
        b=R; 
        c=3-2*R; 
        while (a<b) 
        { 
            Gui_DrawPoint(X+a,Y+b,fc);     //        7 
            Gui_DrawPoint(X-a,Y+b,fc);     //        6 
            Gui_DrawPoint(X+a,Y-b,fc);     //        2 
            Gui_DrawPoint(X-a,Y-b,fc);     //        3 
            Gui_DrawPoint(X+b,Y+a,fc);     //        8 
            Gui_DrawPoint(X-b,Y+a,fc);     //        5 
            Gui_DrawPoint(X+b,Y-a,fc);     //        1 
            Gui_DrawPoint(X-b,Y-a,fc);     //        4 
    
            if(c<0) c=c+4*a+6; 
            else 
            { 
                c=c+4*(a-b)+10; 
                b-=1; 
            } 
           a+=1; 
        } 
        if (a==b) 
        { 
            Gui_DrawPoint(X+a,Y+b,fc); 
            Gui_DrawPoint(X+a,Y+b,fc); 
            Gui_DrawPoint(X+a,Y-b,fc); 
            Gui_DrawPoint(X-a,Y-b,fc); 
            Gui_DrawPoint(X+b,Y+a,fc); 
            Gui_DrawPoint(X-b,Y+a,fc); 
            Gui_DrawPoint(X+b,Y-a,fc); 
            Gui_DrawPoint(X-b,Y-a,fc); 
        } 
        
    } 
    //画线函数,使用Bresenham 画线算法
    void Gui_DrawLine(u16 x0, u16 y0,u16 x1, u16 y1,u16 Color)   
    {
    int dx,             // difference in x's
        dy,             // difference in y's
        dx2,            // dx,dy * 2
        dy2, 
        x_inc,          // amount in pixel space to move during drawing
        y_inc,          // amount in pixel space to move during drawing
        error,          // the discriminant i.e. error i.e. decision variable
        index;          // used for looping 
    
    
        Lcd_SetXY(x0,y0);
        dx = x1-x0;//计算x距离
        dy = y1-y0;//计算y距离
    
        if (dx>=0)
        {
            x_inc = 1;
        }
        else
        {
            x_inc = -1;
            dx    = -dx;  
        } 
        
        if (dy>=0)
        {
            y_inc = 1;
        } 
        else
        {
            y_inc = -1;
            dy    = -dy; 
        } 
    
        dx2 = dx << 1;
        dy2 = dy << 1;
    
        if (dx > dy)//x距离大于y距离,那么每个x轴上只有一个点,每个y轴上有若干个点
        {//且线的点数等于x距离,以x轴递增画点
            // initialize error term
            error = dy2 - dx; 
    
            // draw the line
            for (index=0; index <= dx; index++)//要画的点数不会超过x距离
            {
                //画点
                Gui_DrawPoint(x0,y0,Color);
                
                // test if error has overflowed
                if (error >= 0) //是否需要增加y坐标值
                {
                    error-=dx2;
    
                    // move to next line
                    y0+=y_inc;//增加y坐标值
                } // end if error overflowed
    
                // adjust the error term
                error+=dy2;
    
                // move to the next pixel
                x0+=x_inc;//x坐标值每次画点后都递增1
            } // end for
        } // end if |slope| <= 1
        else//y轴大于x轴,则每个y轴上只有一个点,x轴若干个点
        {//以y轴为递增画点
            // initialize error term
            error = dx2 - dy; 
    
            // draw the line
            for (index=0; index <= dy; index++)
            {
                // set the pixel
                Gui_DrawPoint(x0,y0,Color);
    
                // test if error overflowed
                if (error >= 0)
                {
                    error-=dy2;
    
                    // move to next line
                    x0+=x_inc;
                } // end if error overflowed
    
                // adjust the error term
                error+=dx2;
    
                // move to the next pixel
                y0+=y_inc;
            } // end for
        } // end else |slope| > 1
    }
    
    
    
    void Gui_box(u16 x, u16 y, u16 w, u16 h,u16 bc)
    {
        Gui_DrawLine(x,y,x+w,y,0xEF7D);
        Gui_DrawLine(x+w-1,y+1,x+w-1,y+1+h,0x2965);
        Gui_DrawLine(x,y+h,x+w,y+h,0x2965);
        Gui_DrawLine(x,y,x,y+h,0xEF7D);
        Gui_DrawLine(x+1,y+1,x+1+w-2,y+1+h-2,bc);
    }
    void Gui_box2(u16 x,u16 y,u16 w,u16 h, u8 mode)
    {
        if (mode==0)    {
            Gui_DrawLine(x,y,x+w,y,0xEF7D);
            Gui_DrawLine(x+w-1,y+1,x+w-1,y+1+h,0x2965);
            Gui_DrawLine(x,y+h,x+w,y+h,0x2965);
            Gui_DrawLine(x,y,x,y+h,0xEF7D);
            }
        if (mode==1)    {
            Gui_DrawLine(x,y,x+w,y,0x2965);
            Gui_DrawLine(x+w-1,y+1,x+w-1,y+1+h,0xEF7D);
            Gui_DrawLine(x,y+h,x+w,y+h,0xEF7D);
            Gui_DrawLine(x,y,x,y+h,0x2965);
        }
        if (mode==2)    {
            Gui_DrawLine(x,y,x+w,y,0xffff);
            Gui_DrawLine(x+w-1,y+1,x+w-1,y+1+h,0xffff);
            Gui_DrawLine(x,y+h,x+w,y+h,0xffff);
            Gui_DrawLine(x,y,x,y+h,0xffff);
        }
    }
    
    
    /**************************************************************************************
    功能描述: 在屏幕显示一凸起的按钮框
    输    入: u16 x1,y1,x2,y2 按钮框左上角和右下角坐标
    输    出: 无
    **************************************************************************************/
    void DisplayButtonDown(u16 x1,u16 y1,u16 x2,u16 y2)
    {
        Gui_DrawLine(x1,  y1,  x2,y1, GRAY2);  //H
        Gui_DrawLine(x1+1,y1+1,x2,y1+1, GRAY1);  //H
        Gui_DrawLine(x1,  y1,  x1,y2, GRAY2);  //V
        Gui_DrawLine(x1+1,y1+1,x1+1,y2, GRAY1);  //V
        Gui_DrawLine(x1,  y2,  x2,y2, WHITE);  //H
        Gui_DrawLine(x2,  y1,  x2,y2, WHITE);  //V
    }
    
    /**************************************************************************************
    功能描述: 在屏幕显示一凹下的按钮框
    输    入: u16 x1,y1,x2,y2 按钮框左上角和右下角坐标
    输    出: 无
    **************************************************************************************/
    void DisplayButtonUp(u16 x1,u16 y1,u16 x2,u16 y2)
    {
        Gui_DrawLine(x1,  y1,  x2,y1, WHITE); //H
        Gui_DrawLine(x1,  y1,  x1,y2, WHITE); //V
        
        Gui_DrawLine(x1+1,y2-1,x2,y2-1, GRAY1);  //H
        Gui_DrawLine(x1,  y2,  x2,y2, GRAY2);  //H
        Gui_DrawLine(x2-1,y1+1,x2-1,y2, GRAY1);  //V
        Gui_DrawLine(x2  ,y1  ,x2,y2, GRAY2); //V
    }
    
    
    void Gui_DrawFont_GBK16(u16 x, u16 y, u16 fc, u16 bc, u8 *s)
    {
        unsigned char i,j;
        unsigned short k,x0;
        x0=x;
    
        while(*s) 
        {   
            if((*s) < 128) 
            {
                k=*s;
                if (k==13) 
                {
                    x=x0;
                    y+=16;
                }
                else 
                {
                    if (k>32) k-=32; else k=0;
        
                    for(i=0;i<16;i++)
                    for(j=0;j<8;j++) 
                        {
                            if(asc16[k*16+i]&(0x80>>j)) Gui_DrawPoint(x+j,y+i,fc);
                            else 
                            {
                                if (fc!=bc) Gui_DrawPoint(x+j,y+i,bc);
                            }
                        }
                    x+=8;
                }
                s++;
            }
                
            else 
            {
            
    
                for (k=0;k<hz16_num;k++) 
                {
                  if ((hz16[k].Index[0]==*(s))&&(hz16[k].Index[1]==*(s+1)))
                  { 
                        for(i=0;i<16;i++)
                        {
                            for(j=0;j<8;j++) 
                                {
                                    if(hz16[k].Msk[i*2]&(0x80>>j))  Gui_DrawPoint(x+j,y+i,fc);
                                    else {
                                        if (fc!=bc) Gui_DrawPoint(x+j,y+i,bc);
                                    }
                                }
                            for(j=0;j<8;j++) 
                                {
                                    if(hz16[k].Msk[i*2+1]&(0x80>>j))    Gui_DrawPoint(x+j+8,y+i,fc);
                                    else 
                                    {
                                        if (fc!=bc) Gui_DrawPoint(x+j+8,y+i,bc);
                                    }
                                }
                        }
                    }
                  }
                s+=2;x+=16;
            } 
            
        }
    }
    
    void Gui_DrawFont_GBK24(u16 x, u16 y, u16 fc, u16 bc, u8 *s)
    {
        unsigned char i,j;
        unsigned short k;
    
        while(*s) 
        {
            if( *s < 0x80 ) 
            {
                k=*s;
                if (k>32) k-=32; else k=0;
    
                for(i=0;i<16;i++)
                for(j=0;j<8;j++) 
                    {
                        if(asc16[k*16+i]&(0x80>>j)) 
                        Gui_DrawPoint(x+j,y+i,fc);
                        else 
                        {
                            if (fc!=bc) Gui_DrawPoint(x+j,y+i,bc);
                        }
                    }
                s++;x+=8;
            }
            else 
            {
    
                for (k=0;k<hz24_num;k++) 
                {
                  if ((hz24[k].Index[0]==*(s))&&(hz24[k].Index[1]==*(s+1)))
                  { 
                        for(i=0;i<24;i++)
                        {
                            for(j=0;j<8;j++) 
                                {
                                    if(hz24[k].Msk[i*3]&(0x80>>j))
                                    Gui_DrawPoint(x+j,y+i,fc);
                                    else 
                                    {
                                        if (fc!=bc) Gui_DrawPoint(x+j,y+i,bc);
                                    }
                                }
                            for(j=0;j<8;j++) 
                                {
                                    if(hz24[k].Msk[i*3+1]&(0x80>>j))    Gui_DrawPoint(x+j+8,y+i,fc);
                                    else {
                                        if (fc!=bc) Gui_DrawPoint(x+j+8,y+i,bc);
                                    }
                                }
                            for(j=0;j<8;j++) 
                                {
                                    if(hz24[k].Msk[i*3+2]&(0x80>>j))    
                                    Gui_DrawPoint(x+j+16,y+i,fc);
                                    else 
                                    {
                                        if (fc!=bc) Gui_DrawPoint(x+j+16,y+i,bc);
                                    }
                                }
                        }
                  }
                }
                s+=2;x+=24;
            }
        }
    }
    void Gui_DrawFont_Num32(u16 x, u16 y, u16 fc, u16 bc, u16 num)
    {
        unsigned char i,j,k,c;
        //lcd_text_any(x+94+i*42,y+34,32,32,0x7E8,0x0,sz32,knum[i]);
    //  w=w/8;
    
        for(i=0;i<32;i++)
        {
            for(j=0;j<4;j++) 
            {
                c=*(sz32+num*32*4+i*4+j);
                for (k=0;k<8;k++)   
                {
        
                    if(c&(0x80>>k)) Gui_DrawPoint(x+j*8+k,y+i,fc);
                    else {
                        if (fc!=bc) Gui_DrawPoint(x+j*8+k,y+i,bc);
                    }
                }
            }
        }
    }
    

    5、TFT显示图像文件QDTFT_demo.c

    #include "stm32f4xx.h"
    #include "Lcd_Driver.h"
    #include "GUI.h"
    #include "delay.h"
    #include "Picture.h"
    #include "QDTFT_demo.h"
    unsigned char Num[10]={0,1,2,3,4,5,6,7,8,9};
    void Redraw_Mainmenu(void)
    {
    
        Lcd_Clear(GRAY0);
        
        Gui_DrawFont_GBK16(48,0,BLUE,GRAY0,"CSDN");
        
    //  DisplayButtonUp(15,18,113,28);
        Gui_DrawFont_GBK16(32,20,RED,GRAY0,"AXYZdong");
    
        DisplayButtonUp(15,38,113,58); //x1,y1,x2,y2
        Gui_DrawFont_GBK16(32,40,YELLOW,GRAY0,"文字显示");
    
        DisplayButtonUp(15,68,113,88); //x1,y1,x2,y2
        Gui_DrawFont_GBK16(2,70,BLUE,GRAY0,"Tel:17855525056");
    
        DisplayButtonUp(15,98,113,118); //x1,y1,x2,y2
        Gui_DrawFont_GBK16(0,100,RED,GRAY0,"www.AXYZdong.com");
        delay_ms(1500);
    }
    
    void Num_Test(void)
    {
        u8 i=0;
        Lcd_Clear(GRAY0);
        Gui_DrawFont_GBK16(32,60,RED,GRAY0,"Num Test");
        delay_ms(1000);
        Lcd_Clear(GRAY0);
    
        for(i=0;i<10;i++)
        {
        Gui_DrawFont_Num32((i%3)*42,32*(i/3),RED,GRAY0,Num[i+1]);
        delay_ms(100);
        }
        
    }
    
    void Font_Test(void)
    {
        Lcd_Clear(GRAY0);
        Gui_DrawFont_GBK16(16,60,BLUE,GRAY0,"文字显示测试");
    
        delay_ms(1000);
        Lcd_Clear(GRAY0);
        Gui_DrawFont_GBK16(16,20,YELLOW,GRAY0,"全动电子技术");
        Gui_DrawFont_GBK16(16,40,BLUE,GRAY0,"专注液晶批发");
        Gui_DrawFont_GBK16(16,60,RED,GRAY0, "全程技术支持");
        Gui_DrawFont_GBK16(4,80,BLUE,GRAY0,"Tel:17855525056");
        Gui_DrawFont_GBK16(4,100,RED,GRAY0, "www.youdong.com"); 
        delay_ms(1800); 
    }
    
    void Color_Test(void)
    {
        u8 i=1;
        Lcd_Clear(GRAY0);
        
        Gui_DrawFont_GBK16(24,60,BLUE,GRAY0,"Color Test");
        delay_ms(200);
    
        while(i--)
        {
            Lcd_Clear(WHITE);
            Lcd_Clear(BLACK);
            Lcd_Clear(RED);
          Lcd_Clear(GREEN);
          Lcd_Clear(BLUE);
        }       
    }
    
    //取模方式 水平扫描 从左到右 低位在前
    void showimage(const unsigned char *p) //显示40*40 QQ图片
    {
        int i,j,k; 
        unsigned char picH,picL;
        Lcd_Clear(WHITE); //清屏  
        
        for(k=0;k<3;k++)
        {
            for(j=0;j<3;j++)
            {   
                Lcd_SetRegion(40*j,40*k,40*j+39,40*k+39);       //坐标设置
                for(i=0;i<40*40;i++)
                 {  
                    picL=*(p+i*2);  //数据低位在前
                    picH=*(p+i*2+1);                
                    LCD_WriteData_16Bit(picH<<8|picL);                          
                 }  
             }
        }       
    }
    
    //取模方式 水平扫描 从左到右 低位在前
    void showphoto(const unsigned char *p) //显示128*128图片
    {
        int i; 
        unsigned char picH,picL;
    //  Lcd_Clear(WHITE); //清屏  
        
        Lcd_SetRegion(0,0,127,127);     //坐标设置
            for(i=0;i<128*128;i++)
         {  
            picL=*(p+i*2);  //数据低位在前
            picH=*(p+i*2+1);                
            LCD_WriteData_16Bit(picH<<8|picL);                          
         }      
    }
    void QDTFT_Test_Demo(void)
    {
    //  Lcd_Init();
        LCD_LED_SET;//通过IO控制背光亮             
        Redraw_Mainmenu();//绘制主菜单(部分内容由于分辨率超出物理值可能无法显示)
    //  Color_Test();//简单纯色填充
    //  Num_Test();//数码管字体
    //  Font_Test();//中英文显示     
    //  showphoto(gImage_Robotmaster);//图片显示示例
    //  delay_ms(1200);
    //  LCD_LED_CLR;//IO控制背光灭   
    }
    
    

    6、主函数main.c

    //  作    者   : AXYZdong
    //  生成日期   : 2020-02-03
    //  最近修改   : 2020-03-02 
    //  功能描述   : TFT SPI接口演示例程(stm32系列)
    //              GND    电源地
    //              VCC  接5V或3.3v电源
    //              LED  接PB9
    //              SCL  接PB10
    //              SDA  接PB12
    //              RS   接PB11
    //              RST  接PB14
    //              CS   接PB13               
    //              ------------------------------------------------------------ 
    
    /*Left--Right Pin:VCC GND GND NC NC LED SCL SDA RS RST CS*/
    
    #include "stm32f4xx.h"
    #include "delay.h"
    #include "QDTFT_demo.h"
    #include "Lcd_Driver.h"
    #include "GUI.h"
    
    
    int main(void)
    {
    
      SystemInit();     //System init.
      delay_init(72);   //Delay init.
      Lcd_Init();
      while(1)
      {  
        QDTFT_Test_Demo();  //See the test details in QDTFT_Demo.c      
      }
    
    }
    

    上的代码比较多,如有不懂的地方可以私信我呢。
    上面程序实现的功能我拍了两张图片,可以看看。


    在这里插入图片描述

    当然,显示字符、汉字和图片是TFT最最基本的功能,作为一个显示的媒介,如果与其他的器件建立起通信,将其他器件产生的信息在TFT上显示出来,这样我们就可以直观的获取想要的信息。

    那么,该如何建立相互之间的通信关系?如何直观的显示在TFT上?是我今后所要探索和学习的地方。博客也会不定期更新,期待不久的某一篇会更新到相关内容。(hhh,先卖个关子)

    下一篇,更精彩!

    如果觉着帮到你的话,\color{ red}{点个赞支持一下呢}!!!^ _ ^
    码字不易,大家的支持就是我坚持下去的动力。点赞后不要忘了\color{ red}{关注}我哦!

    相关文章

      网友评论

        本文标题:【STM32学习记录】4、1.44寸TFT液晶屏显示字符、汉字和

        本文链接:https://www.haomeiwen.com/subject/qvzsuhtx.html