【STM32H5开发板】3.使用SPI接口驱动ST7789LCD显示屏
本帖最后由 大涂涂 于 2023-7-3 00:41 编辑<p> 基于前面搭建好的开发环境,这次开始对STMH563开发板进行外设的应用开发,首先为了后续的的实验需要显示内容,这次实验首先进行LCD显示驱动的开发。</p>
<p>这里使用的是 ST7789 芯片的 1.14 寸串口显示屏,使用的是 SPI 接口进行通讯的。</p>
<p>1. 查看ST7789 LCD 显示屏的接口</p>
<p>它的分辨率是 135 x 240 , 需要连接 SCL , SDA, RES, DC , CS 几个信号线,以及 电源和背光线。</p>
<p> </p>
<p>2.STMH563 的SPI 接口</p>
<p>STMH563 SPI 接口电器特性如下图:</p>
<p> STMH563 接口接LCD时,设置为主模式,其时序如下图:</p>
<p> </p>
<p>3.STMH563 连接 ST7789 硬件连接</p>
<p>通过资料可以知道,STMH563 有3组SPI接口,这里我们选择SP1 接口,使用以下引脚连接LCD</p>
<p> LCD模块 STMH563单片机 <br />
BLK 接 PB2 //液晶屏背光控制信号,如果不需要控制,接3.3V,也可以通过IO控制亮灭<br />
SCK 接 PB3 //液晶屏SPI总线时钟信号<br />
SDA 接 PB4 //液晶屏数据/命令控制信号<br />
RES 接 PB9 //液晶屏复位控制信号<br />
CS 接 PB10 //液晶屏片选控制信号</p>
<p>开发板连接线如下图:</p>
<p> </p>
<p>4.软件驱动移植开发</p>
<p>ST 7789 串口屏提供了 STM32F103 的驱动例程序,因此这里主要就是把它移植到 H563 上来,原代码主要驱动如下:</p>
<pre>
<code class="language-cpp">#include "lcd.h"
#include "stdlib.h"
#include "delay.h"
#include "spi.h"
//管理LCD重要参数
//默认为竖屏
_lcd_dev lcddev;
//画笔颜色,背景颜色
u16 POINT_COLOR = 0x0000,BACK_COLOR = 0xFFFF;
u16 DeviceCode;
/*****************************************************************************
* <a href="home.php?mod=space&uid=32621" target="_blank">@name </a>:void LCD_WR_REG(u8 data)
* <a href="home.php?mod=space&uid=311857" target="_blank">@date </a>:2018-08-09
* <a href="home.php?mod=space&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>>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<lcddev.height;i++)
{
for(m=0;m<lcddev.width;m++)
{
SPI_WriteByte(SPI2,Color>>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, &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)>>8);
LCD_WR_DATA(xStar+lcddev.xoffset);
LCD_WR_DATA((xEnd+lcddev.xoffset)>>8);
LCD_WR_DATA(xEnd+lcddev.xoffset);
LCD_WR_REG(lcddev.setycmd);
LCD_WR_DATA((yStar+lcddev.yoffset)>>8);
LCD_WR_DATA(yStar+lcddev.yoffset);
LCD_WR_DATA((yEnd+lcddev.yoffset)>>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<<6)|(1<<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<<6)|(1<<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<<7)|(1<<5));//BGR==1,MY==1,MX==0,MV==1
break;
default:break;
}
}
</code></pre>
<p> </p>
<p>代码移植开发,主要修改就是把这段代码放到 H563的SDK下,修改SPI的调用以及相关的系统初始化,</p>
<p>需要注意的是,这个LCD它有一个初始的x,y 起始数据,其计算方法就是 x=(240-w)/2, y=(320-h)/2, 因此可得 x=0,y= 92, 这样才能正确显示出内容,否则出现花屏 </p>
<p>开发修改中的代码工程如下:</p>
<p> </p>
<p>5. 编译运行</p>
<p>经过修改,调试,烧写,最后成功的把ST7789移植到了 H653 上。</p>
<p> </p>
<p> </p>
页:
[1]