大涂涂 发表于 2023-7-2 18:47

【STM32H5开发板】3.使用SPI接口驱动ST7789LCD显示屏

本帖最后由 大涂涂 于 2023-7-3 00:41 编辑

<p>&nbsp; &nbsp; 基于前面搭建好的开发环境,这次开始对STMH563开发板进行外设的应用开发,首先为了后续的的实验需要显示内容,这次实验首先进行LCD显示驱动的开发。</p>

<p>这里使用的是 ST7789&nbsp; 芯片的 1.14 寸串口显示屏,使用的是 SPI 接口进行通讯的。</p>

<p>1. 查看ST7789&nbsp; LCD 显示屏的接口</p>

<p>它的分辨率是&nbsp; 135 x 240 , 需要连接 SCL , SDA,&nbsp; RES,&nbsp; DC , CS 几个信号线,以及 电源和背光线。</p>

<p>&nbsp;</p>

<p>2.STMH563 的SPI 接口</p>

<p>STMH563 SPI 接口电器特性如下图:</p>

<p> &nbsp;STMH563 接口接LCD时,设置为主模式,其时序如下图:</p>

<p> &nbsp;</p>

<p>3.STMH563 连接 ST7789&nbsp;硬件连接</p>

<p>通过资料可以知道,STMH563 有3组SPI接口,这里我们选择SP1 接口,使用以下引脚连接LCD</p>

<p>&nbsp; &nbsp; LCD模块 &nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;STMH563单片机&nbsp;<br />
&nbsp; &nbsp; &nbsp; &nbsp;BLK&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 接 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;PB2&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //液晶屏背光控制信号,如果不需要控制,接3.3V,也可以通过IO控制亮灭<br />
&nbsp; &nbsp; &nbsp; &nbsp;SCK &nbsp; &nbsp; &nbsp; &nbsp; 接 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;PB3&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //液晶屏SPI总线时钟信号<br />
&nbsp; &nbsp; &nbsp; &nbsp;SDA&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;接 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;PB4&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //液晶屏数据/命令控制信号<br />
&nbsp; &nbsp; &nbsp; &nbsp;RES &nbsp; &nbsp; &nbsp; &nbsp; 接 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;PB9&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //液晶屏复位控制信号<br />
&nbsp; &nbsp; &nbsp; &nbsp;CS&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;接 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;PB10&nbsp; &nbsp; &nbsp; &nbsp; //液晶屏片选控制信号</p>

<p>开发板连接线如下图:</p>

<p>&nbsp;</p>

<p>4.软件驱动移植开发</p>

<p>ST 7789 串口屏提供了 STM32F103 的驱动例程序,因此这里主要就是把它移植到 H563 上来,原代码主要驱动如下:</p>

<pre>
<code class="language-cpp">#include &quot;lcd.h&quot;
#include &quot;stdlib.h&quot;
#include &quot;delay.h&quot;       
#include &quot;spi.h&quot;

//管理LCD重要参数
//默认为竖屏
_lcd_dev lcddev;

//画笔颜色,背景颜色
u16 POINT_COLOR = 0x0000,BACK_COLOR = 0xFFFF;
u16 DeviceCode;       

/*****************************************************************************
* <a href="home.php?mod=space&amp;uid=32621" target="_blank">@name </a>:void LCD_WR_REG(u8 data)
* <a href="home.php?mod=space&amp;uid=311857" target="_blank">@date </a>:2018-08-09
* <a href="home.php?mod=space&amp;uid=665173" target="_blank">@FUNCTION </a>:Write an 8-bit command to the LCD screen
* @parameters :data:Command value to be written
* @retvalue   :None
******************************************************************************/
void LCD_WR_REG(u8 data)
{
   LCD_CS_CLR;   
       LCD_RS_CLR;          
   SPI_WriteByte(SPI2,data);
   LCD_CS_SET;       
}

/*****************************************************************************
* @name       :void LCD_WR_DATA(u8 data)
* @date       :2018-08-09
* @function   :Write an 8-bit data to the LCD screen
* @parameters :data:data value to be written
* @retvalue   :None
******************************************************************************/
void LCD_WR_DATA(u8 data)
{
   LCD_CS_CLR;
       LCD_RS_SET;
   SPI_WriteByte(SPI2,data);
   LCD_CS_SET;
}

/*****************************************************************************
* @name       :void LCD_WriteReg(u8 LCD_Reg, u16 LCD_RegValue)
* @date       :2018-08-09
* @function   :Write data into registers
* @parameters :LCD_Reg:Register address
                LCD_RegValue:Data to be written
* @retvalue   :None
******************************************************************************/
void LCD_WriteReg(u8 LCD_Reg, u16 LCD_RegValue)
{       
        LCD_WR_REG(LCD_Reg);
        LCD_WR_DATA(LCD_RegValue);                         
}          

/*****************************************************************************
* @name       :void LCD_WriteRAM_Prepare(void)
* @date       :2018-08-09
* @function   :Write GRAM
* @parameters :None
* @retvalue   :None
******************************************************************************/       
void LCD_WriteRAM_Prepare(void)
{
        LCD_WR_REG(lcddev.wramcmd);
}       

/*****************************************************************************
* @name       :void Lcd_WriteData_16Bit(u16 Data)
* @date       :2018-08-09
* @function   :Write an 16-bit command to the LCD screen
* @parameters :Data:Data to be written
* @retvalue   :None
******************************************************************************/       
void Lcd_WriteData_16Bit(u16 Data)
{       
   LCD_CS_CLR;
   LCD_RS_SET;
   SPI_WriteByte(SPI2,Data&gt;&gt;8);
       SPI_WriteByte(SPI2,Data);
   LCD_CS_SET;
}

/*****************************************************************************
* @name       :void LCD_DrawPoint(u16 x,u16 y)
* @date       :2018-08-09
* @function   :Write a pixel data at a specified location
* @parameters :x:the x coordinate of the pixel
                y:the y coordinate of the pixel
* @retvalue   :None
******************************************************************************/       
void LCD_DrawPoint(u16 x,u16 y)
{
        LCD_SetCursor(x,y);//设置光标位置
        Lcd_WriteData_16Bit(POINT_COLOR);
}

/*****************************************************************************
* @name       :void LCD_Clear(u16 Color)
* @date       :2018-08-09
* @function   :Full screen filled LCD screen
* @parameters :color:Filled color
* @retvalue   :None
******************************************************************************/       
void LCD_Clear(u16 Color)
{
unsigned int i,m;
        LCD_SetWindows(0,0,lcddev.width-1,lcddev.height-1);   
        LCD_CS_CLR;
        LCD_RS_SET;
        for(i=0;i&lt;lcddev.height;i++)
        {
    for(m=0;m&lt;lcddev.width;m++)
    {       
                        SPI_WriteByte(SPI2,Color&gt;&gt;8);
                        SPI_WriteByte(SPI2,Color);
                }
        }
       LCD_CS_SET;
}

/*****************************************************************************
* @name       :void LCD_GPIOInit(void)
* @date       :2018-08-09
* @function   :Initialization LCD screen GPIO
* @parameters :None
* @retvalue   :None
******************************************************************************/       
void LCD_GPIOInit(void)
{
        GPIO_InitTypeDefGPIO_InitStructure;             
        RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB ,ENABLE);        //使能GPIOB时钟
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9| GPIO_Pin_10| GPIO_Pin_12|GPIO_Pin_11; //GPIOB9,10,11,12
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   //推挽输出
        GPIO_Init(GPIOB, &amp;GPIO_InitStructure);//初始化
        GPIO_SetBits(GPIOB,GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_12|GPIO_Pin_11);       
}

/*****************************************************************************
* @name       :void LCD_RESET(void)
* @date       :2018-08-09
* @function   :Reset LCD screen
* @parameters :None
* @retvalue   :None
******************************************************************************/       
void LCD_RESET(void)
{
        LCD_RST_CLR;
        delay_ms(20);       
        LCD_RST_SET;
        delay_ms(20);
}

/*****************************************************************************
* @name       :void LCD_RESET(void)
* @date       :2018-08-09
* @function   :Initialization LCD screen
* @parameters :None
* @retvalue   :None
******************************************************************************/              
void LCD_Init(void)
{
        SPI2_Init(); //硬件SPI2初始化
        LCD_GPIOInit();//LCD GPIO初始化                                                                               
        LCD_RESET(); //LCD 复位
//************* ST7789V初始化**********//       
        delay_ms(120);                //ms
        LCD_WR_REG(0x11);   //Sleep out
        delay_ms(120);                //Delay 120ms
        LCD_WR_REG(0x36);   
        LCD_WR_DATA(0x00);
        LCD_WR_REG(0x3A);   
        LCD_WR_DATA(0x05);//0x05( 65K Color)
        LCD_WR_REG(0x21);   
        LCD_WR_REG(0xB2);   
        LCD_WR_DATA(0x05);   
        LCD_WR_DATA(0x05);   
        LCD_WR_DATA(0x00);   
        LCD_WR_DATA(0x33);   
        LCD_WR_DATA(0x33);   
        LCD_WR_REG(0xB7);   
        LCD_WR_DATA(0x23);   
        LCD_WR_REG(0xBB);   
        LCD_WR_DATA(0x22);   
        LCD_WR_REG(0xC0);   
        LCD_WR_DATA(0x2C);   
        LCD_WR_REG(0xC2);   
        LCD_WR_DATA(0x01);   
        LCD_WR_REG(0xC3);   
        LCD_WR_DATA(0x13);   
        LCD_WR_REG(0xC4);   
        LCD_WR_DATA(0x20);   
        LCD_WR_REG(0xC6);   
        LCD_WR_DATA(0x0F);   
        LCD_WR_REG(0xD0);   
        LCD_WR_DATA(0xA4);   
        LCD_WR_DATA(0xA1);   
        LCD_WR_REG(0xD6);   
        LCD_WR_DATA(0xA1);   
        LCD_WR_REG(0xE0);
        LCD_WR_DATA(0x70);
        LCD_WR_DATA(0x06);
        LCD_WR_DATA(0x0C);
        LCD_WR_DATA(0x08);
        LCD_WR_DATA(0x09);
        LCD_WR_DATA(0x27);
        LCD_WR_DATA(0x2E);
        LCD_WR_DATA(0x34);
        LCD_WR_DATA(0x46);
        LCD_WR_DATA(0x37);
        LCD_WR_DATA(0x13);
        LCD_WR_DATA(0x13);
        LCD_WR_DATA(0x25);
        LCD_WR_DATA(0x2A);
        LCD_WR_REG(0xE1);
        LCD_WR_DATA(0x70);
        LCD_WR_DATA(0x04);
        LCD_WR_DATA(0x08);
        LCD_WR_DATA(0x09);
        LCD_WR_DATA(0x07);
        LCD_WR_DATA(0x03);
        LCD_WR_DATA(0x2C);
        LCD_WR_DATA(0x42);
        LCD_WR_DATA(0x42);
        LCD_WR_DATA(0x38);
        LCD_WR_DATA(0x14);
        LCD_WR_DATA(0x14);
        LCD_WR_DATA(0x27);
        LCD_WR_DATA(0x2C);
        LCD_WR_REG(0x29);   //Display on
       
//        LCD_WR_REG(0x2A);   //Column Address Set
//        LCD_WR_DATA(0x00);   
//        LCD_WR_DATA(0x34);   //52
//        LCD_WR_DATA(0x00);   
//        LCD_WR_DATA(0xBA);   //186
//        LCD_WR_REG(0x2B);   //Row Address Set
//        LCD_WR_DATA(0x00);   
//        LCD_WR_DATA(0x28);   //40
//        LCD_WR_DATA(0x01);   
//        LCD_WR_DATA(0x17);   //279
//        LCD_WR_REG(0x2C);
//        LCD_WR_REG(0x11);   //Sleep out
//        delay_ms(120);                //Delay 120ms
//        LCD_WR_REG(0x10);   //Sleep in
//        delay_ms(120);                //Delay 120ms
       
LCD_direction(USE_HORIZONTAL);//设置LCD显示方向
        LCD_LED=1;//点亮背光       
        LCD_Clear(WHITE);//清全屏白色
}

/*****************************************************************************
* @name       :void LCD_SetWindows(u16 xStar, u16 yStar,u16 xEnd,u16 yEnd)
* @date       :2018-08-09
* @function   :Setting LCD display window
* @parameters :xStar:the bebinning x coordinate of the LCD display window
                                                                yStar:the bebinning y coordinate of the LCD display window
                                                                xEnd:the endning x coordinate of the LCD display window
                                                                yEnd:the endning y coordinate of the LCD display window
* @retvalue   :None
******************************************************************************/
void LCD_SetWindows(u16 xStar, u16 yStar,u16 xEnd,u16 yEnd)
{       
        LCD_WR_REG(lcddev.setxcmd);       
        LCD_WR_DATA((xStar+lcddev.xoffset)&gt;&gt;8);
        LCD_WR_DATA(xStar+lcddev.xoffset);               
        LCD_WR_DATA((xEnd+lcddev.xoffset)&gt;&gt;8);
        LCD_WR_DATA(xEnd+lcddev.xoffset);

        LCD_WR_REG(lcddev.setycmd);       
        LCD_WR_DATA((yStar+lcddev.yoffset)&gt;&gt;8);
        LCD_WR_DATA(yStar+lcddev.yoffset);               
        LCD_WR_DATA((yEnd+lcddev.yoffset)&gt;&gt;8);
        LCD_WR_DATA(yEnd+lcddev.yoffset);

        LCD_WriteRAM_Prepare();        //开始写入GRAM                       
}   

/*****************************************************************************
* @name       :void LCD_SetCursor(u16 Xpos, u16 Ypos)
* @date       :2018-08-09
* @function   :Set coordinate value
* @parameters :Xpos:thex coordinate of the pixel
                                                                Ypos:they coordinate of the pixel
* @retvalue   :None
******************************************************************************/
void LCD_SetCursor(u16 Xpos, u16 Ypos)
{                                           
        LCD_SetWindows(Xpos,Ypos,Xpos,Ypos);       
}

/*****************************************************************************
* @name       :void LCD_direction(u8 direction)
* @date       :2018-08-09
* @function   :Setting the display direction of LCD screen
* @parameters :direction:0-0 degree
                        1-90 degree
                                                                                                        2-180 degree
                                                                                                        3-270 degree
* @retvalue   :None
******************************************************************************/
void LCD_direction(u8 direction)
{
                        lcddev.setxcmd=0x2A;
                        lcddev.setycmd=0x2B;
                        lcddev.wramcmd=0x2C;
        switch(direction){                  
                case 0:                                                                     
                        lcddev.width=LCD_W;
                        lcddev.height=LCD_H;       
                        lcddev.xoffset=52;
                        lcddev.yoffset=40;
                        LCD_WriteReg(0x36,0);//BGR==1,MY==0,MX==0,MV==0
                break;
                case 1:
                        lcddev.width=LCD_H;
                        lcddev.height=LCD_W;
                        lcddev.xoffset=40;
                        lcddev.yoffset=53;
                        LCD_WriteReg(0x36,(1&lt;&lt;6)|(1&lt;&lt;5));//BGR==1,MY==1,MX==0,MV==1
                break;
                case 2:                                                                     
                        lcddev.width=LCD_W;
                        lcddev.height=LCD_H;
                      lcddev.xoffset=53;
                        lcddev.yoffset=40;                       
                        LCD_WriteReg(0x36,(1&lt;&lt;6)|(1&lt;&lt;7));//BGR==1,MY==0,MX==0,MV==0
                break;
                case 3:
                        lcddev.width=LCD_H;
                        lcddev.height=LCD_W;
                        lcddev.xoffset=40;
                        lcddev.yoffset=52;
                        LCD_WriteReg(0x36,(1&lt;&lt;7)|(1&lt;&lt;5));//BGR==1,MY==1,MX==0,MV==1
                break;       
                default:break;
        }               
}       
</code></pre>

<p>&nbsp;</p>

<p>代码移植开发,主要修改就是把这段代码放到 H563的SDK下,修改SPI的调用以及相关的系统初始化,</p>

<p>需要注意的是,这个LCD它有一个初始的x,y 起始数据,其计算方法就是&nbsp; x=(240-w)/2, y=(320-h)/2, 因此可得 x=0,y= 92, 这样才能正确显示出内容,否则出现花屏&nbsp;</p>

<p>开发修改中的代码工程如下:</p>

<p> &nbsp;</p>

<p>5. 编译运行</p>

<p>经过修改,调试,烧写,最后成功的把ST7789移植到了 H653 上。</p>

<p>&nbsp;</p>

<p>&nbsp;</p>
页: [1]
查看完整版本: 【STM32H5开发板】3.使用SPI接口驱动ST7789LCD显示屏