LCD is one of the commonly used screens in embedded development, and it is also one of the must-have screens for DIY developers. Therefore, this review conducts LCD testing, mainly to see how fast H533 drives LCD screen display.
1. Required Hardware
1. NUCLEO-H533 development board
2. 2.5-inch TFT-LCD display (ILI9341 driver chip) module
3. 8 DuPont wires (mainly used to connect to the LCD screen)
4. USB Type-C cable
2. Display Principle
Simply put, there are many pixels on the LCD screen (these pixels are like small LED lights). If you match the pixels of the picture to the pixels on the screen, you can display the corresponding picture or text. I won't go into the display principle, because there are too many online. Without further ado, let's go straight to the code test.
3. Code Writing
The basic codes are all examples provided by the transplantation manufacturer. There are already big guys who have written the wheel, so why do we need to reinvent the wheel? Therefore, this article mainly shows the test results.
1. Core code
The code for SPI writing data and writing LCD registers is as follows:
/* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, QD electronic SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
**************************************************************************************************/
#include "lcd.h"
#include "spi.h"
#include <stdio.h>
//管理LCD重要参数
//默认为竖屏
_lcd_dev lcddev;
//画笔颜色,背景颜色
uint16_t POINT_COLOR = 0x0000,BACK_COLOR = 0xFFFF;
uint16_t DeviceCode;
uint8_t LCD_SPI_WriteByte(uint8_t TxData) {
uint8_t RxData = 0X00;
#if LCD_FAST_WRITE
SPI2->CR1 = SPI_CR1_SSI;
SPI2->CR2 = 1;
SPI2->CR1 = SPI_CR1_SPE | SPI_CR1_SSI;
SPI2->CR1 = SPI_CR1_SPE | SPI_CR1_SSI | SPI_CR1_CSTART;
while ((SPI2->SR & SPI_FLAG_TXP) == 0);
*((__IO uint8_t *)&SPI2->TXDR) = TxData;
while ((SPI2->SR & SPI_FLAG_TXC) == 0);
SPI2->IFCR = SPI_IFCR_EOTC | SPI_IFCR_TXTFC;
SPI2->CR1 &= ~(SPI_CR1_SPE);
return RxData;
#else
if(HAL_SPI_TransmitReceive(LCD_SPI_Handle, &TxData, &RxData, 1, 100) != HAL_OK)
{
RxData = 0XFF;
}
#endif
return RxData;
}
/*****************************************************************************
* [url=home.php?mod=space&uid=32621]@name[/url] :void LCD_WR_REG(uint8_t data)
* [url=home.php?mod=space&uid=311857]@date[/url] :2018-08-09
* [url=home.php?mod=space&uid=665173]@FUNCTION[/url] :Write an 8-bit command to the LCD screen
* @parameters :data:Command value to be written
* @retvalue :None
******************************************************************************/
void LCD_WR_REG(uint8_t data)
{
LCD_CS_CLR;
LCD_RS_CLR;
LCD_SPI_WriteByte(data);
LCD_CS_SET;
}
/*****************************************************************************
* @name :void LCD_WR_DATA(uint8_t 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(uint8_t data)
{
LCD_CS_CLR;
LCD_RS_SET;
LCD_SPI_WriteByte(data);
LCD_CS_SET;
}
/*****************************************************************************
* @name :void LCD_WriteReg(uint8_t LCD_Reg, uint16_t 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(uint8_t LCD_Reg, uint16_t 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(uint16_t 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(uint16_t Data)
{
LCD_CS_CLR;
LCD_RS_SET;
LCD_SPI_WriteByte(Data>>8);
LCD_SPI_WriteByte(Data);
LCD_CS_SET;
}
/*****************************************************************************
* @name :void LCD_DrawPoint(uint16_t x,uint16_t 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(uint16_t x,uint16_t y)
{
LCD_SetCursor(x,y);//设置光标位置
Lcd_WriteData_16Bit(POINT_COLOR);
}
/*****************************************************************************
* @name :void LCD_Clear(uint16_t Color)
* @date :2018-08-09
* @function :Full screen filled LCD screen
* @parameters :color:Filled color
* @retvalue :None
******************************************************************************/
void LCD_Clear(uint16_t 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++)
{
Lcd_WriteData_16Bit(Color);
}
}
LCD_CS_SET;
}
/*****************************************************************************
* @name :void LCD_RESET(void)
* @date :2018-08-09
* @function :Reset LCD screen
* @parameters :None
* @retvalue :None
******************************************************************************/
void LCD_RESET(void)
{
LCD_RST_CLR;
HAL_Delay(100);
LCD_RST_SET;
HAL_Delay(50);
}
/*****************************************************************************
* @name :void LCD_RESET(void)
* @date :2018-08-09
* @function :Initialization LCD screen
* @parameters :None
* @retvalue :None
******************************************************************************/
void LCD_Init(void)
{
LCD_RESET(); //LCD 复位
//*************3.2inch ILI9341初始化**********//
LCD_WR_REG(0xCF);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0xD9); //C1
LCD_WR_DATA(0X30);
LCD_WR_REG(0xED);
LCD_WR_DATA(0x64);
LCD_WR_DATA(0x03);
LCD_WR_DATA(0X12);
LCD_WR_DATA(0X81);
LCD_WR_REG(0xE8);
LCD_WR_DATA(0x85);
LCD_WR_DATA(0x10);
LCD_WR_DATA(0x7A);
LCD_WR_REG(0xCB);
LCD_WR_DATA(0x39);
LCD_WR_DATA(0x2C);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x34);
LCD_WR_DATA(0x02);
LCD_WR_REG(0xF7);
LCD_WR_DATA(0x20);
LCD_WR_REG(0xEA);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_REG(0xC0); //Power control
LCD_WR_DATA(0x1B); //VRH[5:0]
LCD_WR_REG(0xC1); //P0
LCD_WR_DATA(0x12); //SAP[2:0];BT[3:0] //0x01
LCD_WR_REG(0xC5); //VCM control
LCD_WR_DATA(0x26); //3F
LCD_WR_DATA(0x26); //3C
LCD_WR_REG(0xC7); //VCM control2
LCD_WR_DATA(0XB0);
LCD_WR_REG(0x36); // Memory Access Control
LCD_WR_DATA(0x08);
LCD_WR_REG(0x3A);
LCD_WR_DATA(0x55);
LCD_WR_REG(0xB1);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x1A);
LCD_WR_REG(0xB6); // Display Function Control
LCD_WR_DATA(0x0A);
LCD_WR_DATA(0xA2);
LCD_WR_REG(0xF2); // 3Gamma Function Disable
LCD_WR_DATA(0x00);
LCD_WR_REG(0x26); //Gamma curve selected
LCD_WR_DATA(0x01);
LCD_WR_REG(0xE0); //Set Gamma
LCD_WR_DATA(0x1F);
LCD_WR_DATA(0x24);
LCD_WR_DATA(0x24);
LCD_WR_DATA(0x0D);
LCD_WR_DATA(0x12);
LCD_WR_DATA(0x09);
LCD_WR_DATA(0x52);
LCD_WR_DATA(0xB7);
LCD_WR_DATA(0x3F);
LCD_WR_DATA(0x0C);
LCD_WR_DATA(0x15);
LCD_WR_DATA(0x06);
LCD_WR_DATA(0x0E);
LCD_WR_DATA(0x08);
LCD_WR_DATA(0x00);
LCD_WR_REG(0XE1); //Set Gamma
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x1B);
LCD_WR_DATA(0x1B);
LCD_WR_DATA(0x02);
LCD_WR_DATA(0x0E);
LCD_WR_DATA(0x06);
LCD_WR_DATA(0x2E);
LCD_WR_DATA(0x48);
LCD_WR_DATA(0x3F);
LCD_WR_DATA(0x03);
LCD_WR_DATA(0x0A);
LCD_WR_DATA(0x09);
LCD_WR_DATA(0x31);
LCD_WR_DATA(0x37);
LCD_WR_DATA(0x1F);
LCD_WR_REG(0x2B);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x01);
LCD_WR_DATA(0x3f);
LCD_WR_REG(0x2A);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0x00);
LCD_WR_DATA(0xef);
LCD_WR_REG(0x11); //Exit Sleep
HAL_Delay(120);
LCD_WR_REG(0x29); //display on
LCD_direction(USE_HORIZONTAL);//设置LCD显示方向
LCD_BL_ON;//点亮背光
LCD_Clear(GREEN);//清全屏白色
}
/*****************************************************************************
* @name :void LCD_SetWindows(uint16_t xStar, uint16_t yStar,uint16_t xEnd,uint16_t 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(uint16_t xStar, uint16_t yStar,uint16_t xEnd,uint16_t yEnd)
{
LCD_WR_REG(lcddev.setxcmd);
LCD_WR_DATA(xStar>>8);
LCD_WR_DATA(0x00FF&xStar);
LCD_WR_DATA(xEnd>>8);
LCD_WR_DATA(0x00FF&xEnd);
LCD_WR_REG(lcddev.setycmd);
LCD_WR_DATA(yStar>>8);
LCD_WR_DATA(0x00FF&yStar);
LCD_WR_DATA(yEnd>>8);
LCD_WR_DATA(0x00FF&yEnd);
LCD_WriteRAM_Prepare(); //开始写入GRAM
}
/*****************************************************************************
* @name :void LCD_SetCursor(uint16_t Xpos, uint16_t Ypos)
* @date :2018-08-09
* @function :Set coordinate value
* @parameters :Xpos:the x coordinate of the pixel
Ypos:the y coordinate of the pixel
* @retvalue :None
******************************************************************************/
void LCD_SetCursor(uint16_t Xpos, uint16_t Ypos)
{
LCD_SetWindows(Xpos,Ypos,Xpos,Ypos);
}
/*****************************************************************************
* @name :void LCD_direction(uint8_t 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(uint8_t direction)
{
lcddev.setxcmd=0x2A;
lcddev.setycmd=0x2B;
lcddev.wramcmd=0x2C;
switch(direction){
case 0:
lcddev.width=LCD_W;
lcddev.height=LCD_H;
LCD_WriteReg(0x36,(1<<3)|(0<<6)|(0<<7));//BGR==1,MY==0,MX==0,MV==0
break;
case 1:
lcddev.width=LCD_H;
lcddev.height=LCD_W;
LCD_WriteReg(0x36,(1<<3)|(0<<7)|(1<<6)|(1<<5));//BGR==1,MY==1,MX==0,MV==1
break;
case 2:
lcddev.width=LCD_W;
lcddev.height=LCD_H;
LCD_WriteReg(0x36,(1<<3)|(1<<6)|(1<<7));//BGR==1,MY==0,MX==0,MV==0
break;
case 3:
lcddev.width=LCD_H;
lcddev.height=LCD_W;
LCD_WriteReg(0x36,(1<<3)|(1<<7)|(1<<5));//BGR==1,MY==1,MX==0,MV==1
break;
default:break;
}
}
2. Test code
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ICACHE_Init();
MX_SPI2_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
LCD_Init();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
main_test(); //
Test_Color(); //
Pic_test(); //
HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5);
}
/* USER CODE END 3 */
}
4. Download Verification
Phenomenon:
Display text, color, STM32LOGO picture;
It can be seen that it takes less than 1 second to refresh the color of the whole screen. It also takes less than 1 second to refresh the STM32LOGO (240*240*2 bytes) of the whole screen. Compared with the previous color and picture test using STM32L4R5, the doctor has improved the refresh rate.
project: