一、概述
在第一篇中我们测试了LCD的刷新速度,使用了官方提供的gd32e50x_lcd_eval.c文件已经实现的lcd_clear函数实现整屏数据填充;另外官方还提供了画水平线、画垂直线、画空心矩形和实心矩形的函数实现;本篇我们主要在调用官方提供的函数绘制图片查看显示效果之前,我们还添加了画线函数,可以实现任意起点和终点之间的连接,不局限于水平线和垂直线;还添加了画圆形图案的函数,使用中点画圆算法,实现了实心圆和空心圆的绘制;
二、任意起点、终点线的绘制
/*******************************************************************************
* [url=home.php?mod=space&uid=159083]@brief[/url] * @param
* @retval
* [url=home.php?mod=space&uid=1020061]@attention[/url] *******************************************************************************/
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;
}
}
}
三、空心圆、实心圆的绘制
/*******************************************************************************
* @brief
* @param
* @retval
* @attention
*******************************************************************************/
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--;
}
}
}
四、结合官方提供的水平线、垂直线、空心矩形、实心矩形绘制DEMO图案
/*******************************************************************************
* @brief
* @param
* @retval
* @attention
*******************************************************************************/
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);
}
五、运行效果图
六、调试问题
在下载的官方GD32E50x_Firmware_Library_V1.1.2和GD32E50x_Demo_Suites_V1.1.1这两个文件夹中都有关于LCD有底层驱动代码,我开始使用的是GD32E50x_Firmware_Library_V1.1.2中的官方代码,在显示的时候总是读取不到LCD的Device_Code,更别说显示正常了,但使用GD32E50x_Demo_Suites_V1.1.1中的官方驱动代码,显示就是正常的,然后就对照官方例程一点点的定位,最后发现官方提供的驱动是支持不同型号TFT驱动芯片的,而我开发板上的TFT驱动芯片的操作时序配置不匹配导致了操作不成功的问题,具体修改如下所示:
/*!
\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);
}
七、工程源码
引用: freebsder 发表于 2021-2-25 22:29 绘图纯粹是算法了,考校的是算法功力,其实没啥特别考验mcu的
有的哈,一个是算法的实现,还有就是MCU执行的效率和速度哈……