[GD32E503 Review]——07.LCD Part 2: Drawing Custom Patterns
[Copy link]
1. Overview
In the first article, we tested the refresh speed of the LCD and used the lcd_clear function implemented in the official gd32e50x_lcd_eval.c file to fill the entire screen with data. In addition, the official also provided functions for drawing horizontal lines, vertical lines, hollow rectangles, and solid rectangles. In this article, before calling the official function to draw pictures and check the display effect, we also added a line drawing function, which can connect any starting point and end point, not limited to horizontal and vertical lines. We also added a function for drawing circular patterns, using the midpoint circle drawing algorithm to achieve the drawing of solid and hollow circles.
2. Drawing of arbitrary starting and ending lines
void LCD_DrawLine(uint16_t StartX, uint16_t StartY, uint16_t EndX, uint16_t EndY, uint16_t Color)
{
uint16_t CurrentX = StartX;
uint16_t CurrentY = StartY;
int16_t DeltaX = EndX - StartX;
int16_t DeltaY = EndY - StartY;
int16_t IncreaseX = 0, OffsetX = 0;
int16_t IncreaseY = 0, OffsetY = 0;
uint16_t Distance = 0;
if(DeltaX > 0)
{
IncreaseX = 1;
}
else if(DeltaX == 0)
{
IncreaseX = 0;
}
else
{
IncreaseX = -1;
DeltaX = -DeltaX;
}
if(DeltaY > 0)
{
IncreaseY = 1;
}
else if(DeltaY == 0)
{
IncreaseY = 0;
}
else
{
IncreaseY = -1;
DeltaY = -DeltaY;
}
if(DeltaX > DeltaY) Distance = DeltaX;
else Distance = DeltaY;
for(uint16_t i = 0; i <= Distance + 1; i++)
{
lcd_point_set(CurrentX, CurrentY, Color);
OffsetX += DeltaX;
OffsetY += DeltaY;
if(OffsetX > Distance)
{
OffsetX -= Distance;
CurrentX += IncreaseX;
}
if(OffsetY > Distance)
{
OffsetY -= Distance;
CurrentY += IncreaseY;
}
}
}
3. Drawing of hollow circle and solid circle
void LCD_DrawCircle(uint16_t CenterX, uint16_t CenterY, uint16_t Radius, uint16_t Color, uint8_t Filled)
{
int16_t CurrentX = 0, CurrentY = Radius;
int16_t Distance = 3 - (Radius << 0x01);
while(CurrentX <= CurrentY)
{
if(Filled)
{
for(int16_t i = CurrentX; i <= CurrentY; i++)
{
lcd_point_set(CenterX + CurrentX, CenterY + i, Color);
lcd_point_set(CenterX - CurrentX, CenterY + i, Color);
lcd_point_set(CenterX - i, CenterY + CurrentX, Color);
lcd_point_set(CenterX - i, CenterY - CurrentX, Color);
lcd_point_set(CenterX - CurrentX, CenterY - i, Color);
lcd_point_set(CenterX + CurrentX, CenterY - i, Color);
lcd_point_set(CenterX + i, CenterY - CurrentX, Color);
lcd_point_set(CenterX + i, CenterY + CurrentX, Color);
}
}
else
{
lcd_point_set(CenterX + CurrentX, CenterY + CurrentY, Color);
lcd_point_set(CenterX - CurrentX, CenterY + CurrentY, Color);
lcd_point_set(CenterX - CurrentY, CenterY + CurrentX, Color);
lcd_point_set(CenterX - CurrentY, CenterY - CurrentX, Color);
lcd_point_set(CenterX - CurrentX, CenterY - CurrentY, Color);
lcd_point_set(CenterX + CurrentX, CenterY - CurrentY, Color);
lcd_point_set(CenterX + CurrentY, CenterY - CurrentX, Color);
lcd_point_set(CenterX + CurrentY, CenterY + CurrentX, Color);
}
CurrentX++;
if(Distance < 0)
{
Distance += (4 * CurrentX + 6);
}
else
{
Distance += (10 + 4 * (CurrentX - CurrentY));
CurrentY--;
}
}
}
4. Draw the DEMO pattern by combining the horizontal lines, vertical lines, hollow rectangles and solid rectangles provided by the official website
void LCD_Demo(void)
{
LCD_DrawLine(50, 50, 50, 100, LCD_COLOR_RED);
LCD_DrawLine(50, 50, 100, 50, LCD_COLOR_RED);
LCD_DrawLine(50, 50, 100, 100, LCD_COLOR_RED);
lcd_rectangle_draw(120, 120, 170, 170, LCD_COLOR_YELLOW);
LCD_DrawCircle(50, 200, 40, LCD_COLOR_BLACK, 0);
LCD_DrawCircle(50, 200, 20, LCD_COLOR_BLACK, 1);
lcd_rectangle_fill(140, 240, 160, 260, LCD_COLOR_YELLOW);
LCD_DrawCircle(150, 250, 40, LCD_COLOR_WHITE, 0);
}
5. Operation effect diagram
6. Debugging issues
In the two folders of the downloaded official GD32E50x_Firmware_Library_V1.1.2 and GD32E50x_Demo_Suites_V1.1.1, there are low-level driver codes for LCD. I started using the official code in GD32E50x_Firmware_Library_V1.1.2. When displaying, I could not read the LCD Device_Code, let alone display it normally. However, using the official driver code in GD32E50x_Demo_Suites_V1.1.1, the display was normal. Then I compared it with the official routines little by little, and finally found that the official driver supports different models of TFT driver chips, and the operation timing configuration of the TFT driver chip on my development board does not match, which leads to the problem of unsuccessful operation. The specific modifications are as follows:
/*!
\brief lcd peripheral initialize
\param[in] none
\param[out] none
\retval none
*/
void exmc_lcd_init(void)
{
exmc_norsram_parameter_struct lcd_init_struct;
exmc_norsram_timing_parameter_struct lcd_timing_init_struct;
/* EXMC clock enable */
rcu_periph_clock_enable(RCU_EXMC);
/* GPIO clock enable */
rcu_periph_clock_enable(RCU_GPIOD);
rcu_periph_clock_enable(RCU_GPIOE);
rcu_periph_clock_enable(RCU_GPIOG);
/* configure EXMC_D[0~15]*/
/* PD14(EXMC_D0), PD15(EXMC_D1),PD0(EXMC_D2), PD1(EXMC_D3), PD8(EXMC_D13), PD9(EXMC_D14), PD10(EXMC_D15) */
gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0 | GPIO_PIN_1| GPIO_PIN_8 | GPIO_PIN_9 |
GPIO_PIN_10 | GPIO_PIN_14 | GPIO_PIN_15);
/* PE7(EXMC_D4), PE8(EXMC_D5), PE9(EXMC_D6), PE10(EXMC_D7), PE11(EXMC_D8), PE12(EXMC_D9),
PE13(EXMC_D10), PE14(EXMC_D11), PE15(EXMC_D12) */
gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_7 | GPIO_PIN_8 | GPIO_PIN_9 |
GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 |
GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15);
/* configure PE2(EXMC_A23) */
gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
/* configure PD4(NOE) and PD5(NWE) */
gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_4 | GPIO_PIN_5);
/* configure PG9(EXMC NE1) */
gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
lcd_timing_init_struct.asyn_access_mode = EXMC_ACCESS_MODE_A;
lcd_timing_init_struct.syn_data_latency = EXMC_DATALAT_2_CLK;
lcd_timing_init_struct.syn_clk_division = EXMC_SYN_CLOCK_RATIO_DISABLE;
lcd_timing_init_struct.bus_latency = 2;
#if 0
lcd_timing_init_struct.asyn_data_setuptime = 10;
lcd_timing_init_struct.asyn_address_holdtime = 2;
lcd_timing_init_struct.asyn_address_setuptime = 5;
#else
lcd_timing_init_struct.asyn_data_setuptime = 18;
lcd_timing_init_struct.asyn_address_holdtime = 3;
lcd_timing_init_struct.asyn_address_setuptime = 8;
#endif
lcd_init_struct.norsram_region = EXMC_BANK0_NORSRAM_REGION0;
lcd_init_struct.write_mode = EXMC_ASYN_WRITE;
lcd_init_struct.extended_mode = DISABLE;
lcd_init_struct.asyn_wait = DISABLE;
lcd_init_struct.nwait_signal = DISABLE;
lcd_init_struct.memory_write = ENABLE;
lcd_init_struct.nwait_config = EXMC_NWAIT_CONFIG_BEFORE;
lcd_init_struct.wrap_burst_mode = DISABLE;
lcd_init_struct.nwait_polarity = EXMC_NWAIT_POLARITY_LOW;
lcd_init_struct.burst_mode = DISABLE;
lcd_init_struct.databus_width = EXMC_NOR_DATABUS_WIDTH_16B;
lcd_init_struct.memory_type = EXMC_MEMORY_TYPE_SRAM;
lcd_init_struct.address_data_mux = DISABLE;
lcd_init_struct.read_write_timing = &lcd_timing_init_struct;
lcd_init_struct.write_timing = &lcd_timing_init_struct;
exmc_norsram_init(&lcd_init_struct);
exmc_norsram_enable(EXMC_BANK0_NORSRAM_REGION1);
}
7. Project source code
Project_LCD_DRAW.zip
(428.28 KB, downloads: 17)
|