In this test, the LCD display on the development board shows that the cache uses the SDRAM memory tested in the previous article.
1. Circuit hardware part
LCD display hardware circuit diagram
There are many jumper caps in the display circuit, which are the pin multiplexing function selection of the display. The default debugging of the board is the display function.
2. TFT-LCD (TLI) Interface Introduction
2.1 Introduction
TLI (TFT-LCD Interface) connects to the synchronous LCD interface and provides pixel data, clock and timing signals for the passive LCD display. It supports different fully programmable timing parameters for display. An embedded DMA continuously moves data from the system memory to TLI and then outputs it to the external LCD display. TLI supports two independent display layers and supports layer windowing and layer aliasing functions.
2.2 Features
Up to 24-bit parallel data output per pixel;
Supports resolution up to 2048*2048;
Fully programmable timing parameters;
Embedded DMA to handle pixel data copy;
Two independent layers with window and blending functions;
Support multiple pixel formats: ARGB8888, RGB888, RGB565, etc.;
Support CLUT (color lookup table) and color key format;
Dithering operation of pixel low bits.
2.3 Structure diagram
2.4、Display Timing Diagram
2.5. Mixing process block diagram
Each TLI layer supports windowing and two-layer mixing, which can mix two layers into one frame.
3. Procedure
3.1, lcd.c
#include "gd32h7xx.h"
#include "lcd/tli_lcd.h"
#include "exmc/exmc_sdram.h"
#include "lcd/font.h"
#define BACK_FRAME_START_ADDR SDRAM_DEVICE0_ADDR
#define FORE_FRAME_START_ADDR ((u32)(BACK_FRAME_START_ADDR + (LCD_PIXEL_WIDTH + 1) * LCD_PIXEL_HEIGHT * 2))
static u16 s_arrBackgroundFrame[(LCD_PIXEL_WIDTH + 1) * LCD_PIXEL_HEIGHT] __attribute__((at(BACK_FRAME_START_ADDR)));
static u16 s_arrForegroundFrame[(LCD_PIXEL_WIDTH + 1) * LCD_PIXEL_HEIGHT] __attribute__((at(FORE_FRAME_START_ADDR)));
StructTLILCDDev g_structTLILCDDev;
//设置层窗口
void LCDLayerWindowSet(EnumTLILCDLayer layer, u32 x, u32 y, u32 width, u32 height)
{
tli_layer_parameter_struct tli_layer_init_struct;
u32 swap, x0, y0;
tli_layer_struct_para_init(&tli_layer_init_struct);
if(LCD_SCREEN_VERTICAL == g_structTLILCDDev.dir)
{
x0 = x;
y0 = y + height - 1;
y = x0;
x = LCD_PIXEL_WIDTH - 1 - y0;
if(x >= LCD_PIXEL_WIDTH){return;}
if(y >= LCD_PIXEL_HEIGHT){return;}
swap = width;
width = height;
height = swap;
}
if((x + width) > LCD_PIXEL_WIDTH)
{
width = LCD_PIXEL_WIDTH - x;
}
if((y + height) > LCD_PIXEL_HEIGHT)
{
height = LCD_PIXEL_HEIGHT - y;
}
if(LCD_LAYER_BACKGROUND == layer)
{
tli_layer_init_struct.layer_window_leftpos = (x + HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH);
tli_layer_init_struct.layer_window_rightpos = (x + width + HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH - 1);
tli_layer_init_struct.layer_window_toppos = (y + VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH);
tli_layer_init_struct.layer_window_bottompos = (y + height + VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH - 1);
tli_layer_init_struct.layer_ppf = LAYER_PPF_RGB565;
tli_layer_init_struct.layer_sa = 0xFF;
tli_layer_init_struct.layer_default_blue = 0xFF;
tli_layer_init_struct.layer_default_green = 0xFF;
tli_layer_init_struct.layer_default_red = 0xFF;
tli_layer_init_struct.layer_default_alpha = 0xFF;
tli_layer_init_struct.layer_acf1 = LAYER_ACF1_PASA;
tli_layer_init_struct.layer_acf2 = LAYER_ACF2_PASA;
tli_layer_init_struct.layer_frame_bufaddr = (u32)s_arrBackgroundFrame;
tli_layer_init_struct.layer_frame_line_length = ((width * 2) + 3);
tli_layer_init_struct.layer_frame_buf_stride_offset = (width * 2);
tli_layer_init_struct.layer_frame_total_line_number = height;
tli_layer_init(LAYER0, &tli_layer_init_struct);
tli_color_key_disable(LAYER0);
tli_lut_disable(LAYER0);
if(LCD_SCREEN_HORIZONTAL == g_structTLILCDDev.dir)
{
g_structTLILCDDev.width[LCD_LAYER_BACKGROUND] = width;
g_structTLILCDDev.height[LCD_LAYER_BACKGROUND] = height;
}
else if(LCD_SCREEN_VERTICAL == g_structTLILCDDev.dir)
{
g_structTLILCDDev.width[LCD_LAYER_BACKGROUND] = height;
g_structTLILCDDev.height[LCD_LAYER_BACKGROUND] = width;
}
}
else if(LCD_LAYER_FOREGROUND == layer)
{
tli_layer_init_struct.layer_window_leftpos = (x + HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH);
tli_layer_init_struct.layer_window_rightpos = (x + width + HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH - 1);
tli_layer_init_struct.layer_window_toppos = (y + VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH);
tli_layer_init_struct.layer_window_bottompos = (y + height + VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH - 1);
tli_layer_init_struct.layer_ppf = LAYER_PPF_RGB565;
tli_layer_init_struct.layer_sa = 0xFF;
tli_layer_init_struct.layer_default_blue = 0xFF;
tli_layer_init_struct.layer_default_green = 0xFF;
tli_layer_init_struct.layer_default_red = 0xFF;
tli_layer_init_struct.layer_default_alpha = 0x00;
tli_layer_init_struct.layer_acf1 = LAYER_ACF1_PASA;
tli_layer_init_struct.layer_acf2 = LAYER_ACF2_PASA;
tli_layer_init_struct.layer_frame_bufaddr = (u32)s_arrForegroundFrame;
tli_layer_init_struct.layer_frame_line_length = ((width * 2) + 3);
tli_layer_init_struct.layer_frame_buf_stride_offset = (width * 2);
tli_layer_init_struct.layer_frame_total_line_number = height;
tli_layer_init(LAYER1, &tli_layer_init_struct);
tli_color_key_disable(LAYER1);
tli_lut_disable(LAYER1);
if(LCD_SCREEN_HORIZONTAL == g_structTLILCDDev.dir)
{
g_structTLILCDDev.width[LCD_LAYER_FOREGROUND] = width;
g_structTLILCDDev.height[LCD_LAYER_FOREGROUND] = height;
}
else if(LCD_SCREEN_VERTICAL == g_structTLILCDDev.dir)
{
g_structTLILCDDev.width[LCD_LAYER_FOREGROUND] = height;
g_structTLILCDDev.height[LCD_LAYER_FOREGROUND] = width;
}
}
tli_reload_config(TLI_REQUEST_RELOAD_EN);
}
//使能背景或前景层
void LCDLayerEnable(EnumTLILCDLayer layer)
{
if(LCD_LAYER_BACKGROUND == layer)
{
tli_layer_enable(LAYER0);
}
else if(LCD_LAYER_FOREGROUND == layer)
{
tli_layer_enable(LAYER1);
}
tli_reload_config(TLI_REQUEST_RELOAD_EN);
}
//禁用背景或前景层
void LCDLayerDisable(EnumTLILCDLayer layer)
{
if(LCD_LAYER_BACKGROUND == layer)
{
tli_layer_disable(LAYER0);
}
else if(LCD_LAYER_FOREGROUND == layer)
{
tli_layer_disable(LAYER1);
}
tli_reload_config(TLI_REQUEST_RELOAD_EN);
}
//切换层
void LCDLayerSwitch(EnumTLILCDLayer layer)
{
if(LCD_LAYER_BACKGROUND == layer)
{
g_structTLILCDDev.frameBuf = s_arrBackgroundFrame;
g_structTLILCDDev.currentLayer = LCD_LAYER_BACKGROUND;
}
else
{
g_structTLILCDDev.frameBuf = s_arrForegroundFrame;
g_structTLILCDDev.currentLayer = LCD_LAYER_FOREGROUND;
}
}
//设置当前层的透明度
void LCDTransparencySet(EnumTLILCDLayer layer, u8 trans)
{
if (LCD_LAYER_BACKGROUND == layer)
{
TLI_LXSA(LAYER0) &= ~(TLI_LXSA_SA);
TLI_LXSA(LAYER0) = trans;
}
else
{
TLI_LXSA(LAYER1) &= ~(TLI_LXSA_SA);
TLI_LXSA(LAYER1) = trans;
}
tli_reload_config(TLI_REQUEST_RELOAD_EN);
}
//开启LCD显示
void LCDDisplayOn(void)
{
tli_enable();
}
//关闭LCD显示
void LCDDisplayOff(void)
{
tli_disable();
}
//等待LCD行传输空闲
void LCDWaitHIdle(void)
{
while(RESET == tli_flag_get(TLI_FLAG_HDE));
while(SET == tli_flag_get(TLI_FLAG_HDE));
}
//等待LCD场传输空闲
void LCDWaitVIdle(void)
{
while(RESET == tli_flag_get(TLI_FLAG_VDE));
while(SET == tli_flag_get(TLI_FLAG_VDE));
}
//设置LCD显示方向
void LCDDisplayDir(EnumTLILCDDir dir)
{
u32 swap;
if(g_structTLILCDDev.dir != dir)
{
g_structTLILCDDev.dir = dir;
swap = g_structTLILCDDev.width[LCD_LAYER_BACKGROUND];
g_structTLILCDDev.width[LCD_LAYER_BACKGROUND] = g_structTLILCDDev.height[LCD_LAYER_BACKGROUND];
g_structTLILCDDev.height[LCD_LAYER_BACKGROUND] = swap;
swap = g_structTLILCDDev.width[LCD_LAYER_FOREGROUND];
g_structTLILCDDev.width[LCD_LAYER_FOREGROUND] = g_structTLILCDDev.height[LCD_LAYER_FOREGROUND];
g_structTLILCDDev.height[LCD_LAYER_FOREGROUND] = swap;
}
}
//清屏
void LCDClear(u32 color)
{
ipa_destination_parameter_struct ipa_destination_init_struct;
u8 red, green, blue;
RGB565ToRGB888A(color, &red, &green, &blue);
rcu_periph_clock_enable(RCU_IPA);
ipa_deinit();
ipa_pixel_format_convert_mode_set(IPA_FILL_UP_DE);
//设置目标图像参数
ipa_destination_struct_para_init(&ipa_destination_init_struct);
ipa_destination_init_struct.destination_pf = IPA_DPF_RGB565;
ipa_destination_init_struct.destination_memaddr = (u32)g_structTLILCDDev.frameBuf;
ipa_destination_init_struct.destination_lineoff = 0;
ipa_destination_init_struct.destination_prealpha = 0xFF;
ipa_destination_init_struct.destination_prered = red;
ipa_destination_init_struct.destination_pregreen = green;
ipa_destination_init_struct.destination_preblue = blue;
ipa_destination_init_struct.image_width = LCD_PIXEL_WIDTH;
ipa_destination_init_struct.image_height = LCD_PIXEL_HEIGHT;
ipa_destination_init(&ipa_destination_init_struct);
// //使能IPA内部定时器
// ipa_interval_clock_num_config(0);
// ipa_inter_timer_config(IPA_INTER_TIMER_ENABLE);
ipa_transfer_enable();
while(RESET == ipa_interrupt_flag_get(IPA_INT_FLAG_FTF));
ipa_interrupt_flag_clear(IPA_INT_FLAG_FTF);
ipa_deinit();
}
//画点
void LCDDrawPoint(u32 x, u32 y, u32 color)
{
u32 width, height;
width = g_structTLILCDDev.width[g_structTLILCDDev.currentLayer];
height = g_structTLILCDDev.height[g_structTLILCDDev.currentLayer];
if(x >= width || y >= height)
{
return;
}
if(LCD_SCREEN_HORIZONTAL == g_structTLILCDDev.dir)
{
g_structTLILCDDev.frameBuf[width * y + x] = color;
}
else
{
g_structTLILCDDev.frameBuf[height * x + (height - 1 - y)] = color;
}
}
//读点
u32 LCDReadPoint(u32 x, u32 y)
{
u32 width, height;
width = g_structTLILCDDev.width[g_structTLILCDDev.currentLayer];
height = g_structTLILCDDev.height[g_structTLILCDDev.currentLayer];
if(x >= width || y >= height)
{
return 0;
}
if(LCD_SCREEN_HORIZONTAL == g_structTLILCDDev.dir)
{
return g_structTLILCDDev.frameBuf[width * y + x];
}
else
{
return g_structTLILCDDev.frameBuf[height * x + (height - 1 - y)];
}
}
//LCD填充
void LCDFill(u32 x, u32 y, u32 width, u32 height, u32 color)
{
ipa_destination_parameter_struct ipa_destination_init_struct;
u32 destStartAddr;
u32 phyWidth, phyHeight;
u32 phyX, phyY;
u32 lineOff;
u32 swap;
u8 red, green, blue;
u32 x1, y1, x2, y2, color1, color2;
if(LCD_SCREEN_HORIZONTAL == g_structTLILCDDev.dir)
{
phyWidth = g_structTLILCDDev.width[g_structTLILCDDev.currentLayer];
phyHeight = g_structTLILCDDev.height[g_structTLILCDDev.currentLayer];
phyX = x;
phyY = y;
}
else if(LCD_SCREEN_VERTICAL == g_structTLILCDDev.dir)
{
phyWidth = g_structTLILCDDev.width[g_structTLILCDDev.currentLayer];
phyHeight = g_structTLILCDDev.height[g_structTLILCDDev.currentLayer];
swap = phyWidth;
phyWidth = phyHeight;
phyHeight = swap;
swap = width;
width = height;
height = swap;
phyX = phyWidth - y - width;
phyY = x;
}
if((phyX + width) > LCD_PIXEL_WIDTH)
{
width = LCD_PIXEL_WIDTH - phyX;
}
if((phyY + height) > LCD_PIXEL_HEIGHT)
{
height = LCD_PIXEL_HEIGHT - phyY;
}
if(LCD_SCREEN_HORIZONTAL == g_structTLILCDDev.dir)
{
x1 = phyX;
x2 = x1 + 1;
y1 = phyY + height;
y2 = y1;
}
else if(LCD_SCREEN_VERTICAL == g_structTLILCDDev.dir)
{
x1 = x + height;
x2 = x1;
y1 = y + width - 1;
y2 = y1 - 1;
}
color1 = LCDReadPoint(x1, y1);
color2 = LCDReadPoint(x2, y2);
destStartAddr = (u32)g_structTLILCDDev.frameBuf + g_structTLILCDDev.pixelSize * (phyWidth * phyY + phyX);
lineOff = phyWidth - width;
RGB565ToRGB888A(color, &red, &green, &blue);
rcu_periph_clock_enable(RCU_IPA);
ipa_deinit();
ipa_pixel_format_convert_mode_set(IPA_FILL_UP_DE);
//设置目标图像参数
ipa_destination_struct_para_init(&ipa_destination_init_struct);
ipa_destination_init_struct.destination_pf = IPA_DPF_RGB565;
ipa_destination_init_struct.destination_memaddr = destStartAddr;
ipa_destination_init_struct.destination_lineoff = lineOff;
ipa_destination_init_struct.destination_prealpha = 0xFF;
ipa_destination_init_struct.destination_prered = red;
ipa_destination_init_struct.destination_pregreen = green;
ipa_destination_init_struct.destination_preblue = blue;
ipa_destination_init_struct.image_width = width;
ipa_destination_init_struct.image_height = height;
ipa_destination_init(&ipa_destination_init_struct);
// //使能IPA内部定时器
// ipa_interval_clock_num_config(0);
// ipa_inter_timer_config(IPA_INTER_TIMER_ENABLE);
ipa_transfer_enable();
while(RESET == ipa_interrupt_flag_get(IPA_INT_FLAG_FTF));
ipa_interrupt_flag_clear(IPA_INT_FLAG_FTF);
ipa_deinit();
LCDDrawPoint(x1, y1, color1);
LCDDrawPoint(x2, y2, color2);
}
//LCD填充
void LCDFillPixel(u32 x0, u32 y0, u32 x1, u32 y1, u32 color)
{
u32 swap, width, height;
if(x0 > x1)
{
swap = x0;
x0 = x1;
x1 = swap;
}
if(y0 > y1)
{
swap = y0;
y0 = y1;
y1 = swap;
}
width = x1 - x0 + 1;
height = y1 - y0 + 1;
LCDFill(x0, y0, width, height, color);
}
void LCDColorFill(u32 x, u32 y, u32 width, u32 height, u16* color)
{
u32 x0, y0, i;
x0 = x;
y0 = y;
i = 0;
for(y = y0; y < y0 + height; y++)
{
for(x = x0; x < x0 + width; x++)
{
LCDDrawPoint(x, y, color[i]);
i++;
}
}
}
void LCDColorFillPixel(u32 x0, u32 y0, u32 x1, u32 y1, u16* color)
{
u32 x, y, swap, i;
if(x0 > x1)
{
swap = x0;
x0 = x1;
x1 = swap;
}
if(y0 > y1)
{
swap = y0;
y0 = y1;
y1 = swap;
}
i = 0;
for(y = y0; y <= y1; y++)
{
for(x = x0; x <= x1; x++)
{
LCDDrawPoint(x, y, color[i]);
i++;
}
}
}
void LCDDrawLine(u32 x0, u32 y0, u32 x1, u32 y1, u32 color)
{
int x, y, dx, dy, dx2, dy2, xStep, yStep, swap, sum;
dx = x1 - x0;
dy = y1 - y0;
if(dx < 0){dx = -dx;}
if(dy < 0){dy = -dy;}
dx2 = dx << 1;
dy2 = dy << 1;
if(dx >= dy)
{
if(x0 > x1)
{
swap = x0; x0 = x1; x1 = swap;
swap = y0; y0 = y1; y1 = swap;
}
if(y1 > y0){yStep = 1;}else{yStep = -1;}
x = x0;
y = y0;
sum = -dx;
while(x <= x1)
{
LCDDrawPoint(x, y, color);
x = x + 1;
sum = sum + dy2;
if(sum >= 0)
{
sum = sum - dx2;
y = y + yStep;
}
}
}
else
{
if(y0 > y1)
{
swap = x0; x0 = x1; x1 = swap;
swap = y0; y0 = y1; y1 = swap;
}
if(x1 > x0){xStep = 1;}else{xStep = -1;}
x = x0;
y = y0;
sum = -dy;
while(y <= y1)
{
LCDDrawPoint(x, y, color);
y = y + 1;
sum = sum + dx2;
if(sum >= 0)
{
sum = sum - dy2;
x = x + xStep;
}
}
}
}
void LCDDrawRectangle(u32 x1, u32 y1, u32 x2, u32 y2, u32 color)
{
LCDDrawLine(x1, y1, x2, y1, color);
LCDDrawLine(x1, y1, x1, y2, color);
LCDDrawLine(x1, y2, x2, y2, color);
LCDDrawLine(x2, y1, x2, y2, color);
}
void LCDDrawCircle(u32 x0, u32 y0, u32 r, u32 color)
{
int x, y, d;
x = 0;
y = r;
d = 5 - (r << 2);
while(x <= y)
{
LCDDrawPoint(x0 + x, y0 + y, color);
LCDDrawPoint(x0 + x, y0 - y, color);
LCDDrawPoint(x0 - x, y0 + y, color);
LCDDrawPoint(x0 - x, y0 - y, color);
LCDDrawPoint(x0 + y, y0 + x, color);
LCDDrawPoint(x0 - y, y0 + x, color);
LCDDrawPoint(x0 + y, y0 - x, color);
LCDDrawPoint(x0 - y, y0 - x, color);
x++;
if(d < 0)
{
d = d + (x << 3) + 12;
}
else
{
d = d + ((x - y) << 3) + 20;
y--;
}
}
}
void LCDShowChar(u32 x, u32 y, EnumTLILCDFont font, EnumTLILCDTextMode mode, u32 textColor, u32 backColor, u32 code)
{
u8 byte;
u32 i, j;
u32 y0;
u32 height;
u32 bufSize;
u8* enBuf;
u8* codeBuf;
switch (font)
{
case LCD_FONT_12: height = 12; break;
case LCD_FONT_16: height = 16; break;
case LCD_FONT_24: height = 24; break;
default: return;
}
switch (font)
{
case LCD_FONT_12: bufSize = 12; break;
case LCD_FONT_16: bufSize = 16; break;
case LCD_FONT_24: bufSize = 36; break;
default: return;
}
switch (font)
{
case LCD_FONT_12: enBuf = (u8*)asc2_1206[code - ' ']; break;
case LCD_FONT_16: enBuf = (u8*)asc2_1608[code - ' ']; break;
case LCD_FONT_24: enBuf = (u8*)asc2_2412[code - ' ']; break;
default: return;
}
codeBuf = enBuf;
y0 = y;
for(i = 0; i < bufSize; i++)
{
byte = codeBuf[i];
for(j = 0; j < 8; j++)
{
if(byte & 0x80)
{
LCDDrawPoint(x, y, textColor);
}
else if(LCD_TEXT_NORMAL == mode)
{
LCDDrawPoint(x, y, backColor);
}
byte <<= 1;
y++;
if(y >= g_structTLILCDDev.height[g_structTLILCDDev.currentLayer])
{
return;
}
if((y - y0) >= height)
{
y = y0;
x++;
if(x >= g_structTLILCDDev.width[g_structTLILCDDev.currentLayer])
{
return;
}
break;
}
}
}
}
void LCDShowString(u32 x, u32 y, u32 width, u32 height, EnumTLILCDFont font, EnumTLILCDTextMode mode, u32 textColor, u32 backColor, char* string)
{
u32 x0, x1, y1, cWidth, i, code;
x0 = x;
x1 = x0 + width - 1;
y1 = x1 + height - 1;
switch (font)
{
case LCD_FONT_12: cWidth = 6; break;
case LCD_FONT_16: cWidth = 8; break;
case LCD_FONT_24: cWidth = 12; break;
default: return;
}
i = 0;
while(0 != string[i])
{
if((u8)string[i] < 0x80) //ASCII码
{
LCDShowChar(x, y, font, mode, textColor, backColor, string[i]);
if((x + cWidth) > x1)
{
x = x0;
y = y + height;
if(y > y1)
{
return;
}
}
else
{
x = x + cWidth;
}
i = i + 1;
}
else
{
code = (string[i] << 8) | string[i + 1];
LCDShowChar(x, y, font, mode, textColor, backColor, code);
if((x + cWidth * 2) > x1)
{
x = x0;
y = y + height;
if(y > y1)
{
return;
}
}
else
{
x = x + cWidth * 2;
}
i = i + 2;
}
}
}
void LCDWindowSave(u32 x, u32 y, u32 width, u32 height, void* saveBuf)
{
ipa_foreground_parameter_struct ipa_fg_init_struct;
ipa_destination_parameter_struct ipa_destination_init_struct;
u32 foreStartAddr;
u32 phyWidth, phyHeight;
u32 phyX, phyY;
u32 lineOff;
u32 swap;
if(LCD_SCREEN_HORIZONTAL == g_structTLILCDDev.dir)
{
phyWidth = g_structTLILCDDev.width[g_structTLILCDDev.currentLayer];
phyHeight = g_structTLILCDDev.height[g_structTLILCDDev.currentLayer];
phyX = x;
phyY = y;
}
else if(LCD_SCREEN_VERTICAL == g_structTLILCDDev.dir)
{
phyWidth = g_structTLILCDDev.width[g_structTLILCDDev.currentLayer];
phyHeight = g_structTLILCDDev.height[g_structTLILCDDev.currentLayer];
swap = phyWidth;
phyWidth = phyHeight;
phyHeight = swap;
swap = width;
width = height;
height = swap;
phyX = phyWidth - y - width;
phyY = x;
}
if((phyX + width) > LCD_PIXEL_WIDTH)
{
width = LCD_PIXEL_WIDTH - phyX;
}
if((phyY + height) > LCD_PIXEL_HEIGHT)
{
height = LCD_PIXEL_HEIGHT - phyY;
}
foreStartAddr = (u32)g_structTLILCDDev.frameBuf + g_structTLILCDDev.pixelSize * (phyWidth * phyY + phyX);
lineOff = phyWidth - width;
rcu_periph_clock_enable(RCU_IPA);
ipa_deinit();
ipa_pixel_format_convert_mode_set(IPA_FGTODE);
//设置前景图像参数
ipa_foreground_struct_para_init(&ipa_fg_init_struct);
ipa_fg_init_struct.foreground_pf = FOREGROUND_PPF_RGB565;
ipa_fg_init_struct.foreground_memaddr = foreStartAddr;
ipa_fg_init_struct.foreground_lineoff = lineOff;
ipa_fg_init_struct.foreground_alpha_algorithm = IPA_FG_ALPHA_MODE_0;
ipa_fg_init_struct.foreground_prealpha = 0xFF;
ipa_fg_init_struct.foreground_prered = 0x00;
ipa_fg_init_struct.foreground_pregreen = 0x00;
ipa_fg_init_struct.foreground_preblue = 0x00;
ipa_foreground_init(&ipa_fg_init_struct);
//设置目标图像参数
ipa_destination_struct_para_init(&ipa_destination_init_struct);
ipa_destination_init_struct.destination_pf = IPA_DPF_RGB565;
ipa_destination_init_struct.destination_memaddr = (u32)saveBuf;
ipa_destination_init_struct.destination_lineoff = 0;
ipa_destination_init_struct.destination_prealpha = 0xFF;
ipa_destination_init_struct.destination_prered = 0x00;
ipa_destination_init_struct.destination_pregreen = 0x00;
ipa_destination_init_struct.destination_preblue = 0x00;
ipa_destination_init_struct.image_width = width;
ipa_destination_init_struct.image_height = height;
ipa_destination_init(&ipa_destination_init_struct);
// //使能IPA内部定时器
// ipa_interval_clock_num_config(0);
// ipa_inter_timer_config(IPA_INTER_TIMER_ENABLE);
ipa_transfer_enable();
while(RESET == ipa_interrupt_flag_get(IPA_INT_FLAG_FTF));
ipa_interrupt_flag_clear(IPA_INT_FLAG_FTF);
ipa_deinit();
}
void LCDWindowFill(u32 x, u32 y, u32 width, u32 height, void* imageBuf)
{
ipa_foreground_parameter_struct ipa_fg_init_struct;
ipa_destination_parameter_struct ipa_destination_init_struct;
u32 destStartAddr;
u32 phyWidth, phyHeight;
u32 phyX, phyY;
u32 lineOff;
u32 swap;
if(LCD_SCREEN_HORIZONTAL == g_structTLILCDDev.dir)
{
phyWidth = g_structTLILCDDev.width[g_structTLILCDDev.currentLayer];
phyHeight = g_structTLILCDDev.height[g_structTLILCDDev.currentLayer];
phyX = x;
phyY = y;
}
else if(LCD_SCREEN_VERTICAL == g_structTLILCDDev.dir)
{
phyWidth = g_structTLILCDDev.width[g_structTLILCDDev.currentLayer];
phyHeight = g_structTLILCDDev.height[g_structTLILCDDev.currentLayer];
swap = phyWidth;
phyWidth = phyHeight;
phyHeight = swap;
swap = width;
width = height;
height = swap;
phyX = phyWidth - y - width;
phyY = x;
}
if((phyX + width) > LCD_PIXEL_WIDTH)
{
width = LCD_PIXEL_WIDTH - phyX;
}
if((phyY + height) > LCD_PIXEL_HEIGHT)
{
height = LCD_PIXEL_HEIGHT - phyY;
}
destStartAddr = (u32)g_structTLILCDDev.frameBuf + g_structTLILCDDev.pixelSize * (phyWidth * phyY + phyX);
lineOff = phyWidth - width;
rcu_periph_clock_enable(RCU_IPA);
ipa_deinit();
ipa_pixel_format_convert_mode_set(IPA_FGTODE);
//设置前景图像参数
ipa_foreground_struct_para_init(&ipa_fg_init_struct);
ipa_fg_init_struct.foreground_pf = FOREGROUND_PPF_RGB565;
ipa_fg_init_struct.foreground_memaddr = (u32)imageBuf;
ipa_fg_init_struct.foreground_lineoff = 0;
ipa_fg_init_struct.foreground_alpha_algorithm = IPA_FG_ALPHA_MODE_0;
ipa_fg_init_struct.foreground_prealpha = 0xFF;
ipa_fg_init_struct.foreground_prered = 0x00;
ipa_fg_init_struct.foreground_pregreen = 0x00;
ipa_fg_init_struct.foreground_preblue = 0x00;
ipa_foreground_init(&ipa_fg_init_struct);
//设置目标图像参数
ipa_destination_struct_para_init(&ipa_destination_init_struct);
ipa_destination_init_struct.destination_pf = IPA_DPF_RGB565;
ipa_destination_init_struct.destination_memaddr = (u32)destStartAddr;
ipa_destination_init_struct.destination_lineoff = lineOff;
ipa_destination_init_struct.destination_prealpha = 0xFF;
ipa_destination_init_struct.destination_prered = 0x00;
ipa_destination_init_struct.destination_pregreen = 0x00;
ipa_destination_init_struct.destination_preblue = 0x00;
ipa_destination_init_struct.image_width = width;
ipa_destination_init_struct.image_height = height;
ipa_destination_init(&ipa_destination_init_struct);
// //使能IPA内部定时器
// ipa_interval_clock_num_config(0);
// ipa_inter_timer_config(IPA_INTER_TIMER_ENABLE);
ipa_transfer_enable();
while(RESET == ipa_interrupt_flag_get(IPA_INT_FLAG_FTF));
ipa_interrupt_flag_clear(IPA_INT_FLAG_FTF);
ipa_deinit();
}
void RGB565ToRGB888A(u16 rgb565, u8* r, u8* g, u8* b)
{
*r = ((0xF800 & rgb565) >> 11) & 0xFF;
*g = ((0x07E0 & rgb565) >> 5 ) & 0xFF;
*b = ((0x001F & rgb565) >> 0 ) & 0xFF;
}
u32 RGB565ToRGB888B(u16 rgb565)
{
u8 r, g, b;
r = ((0xF800 & rgb565) >> 11) & 0xFF;
g = ((0x07E0 & rgb565) >> 5 ) & 0xFF;
b = ((0x001F & rgb565) >> 0 ) & 0xFF;
return ((r << 16) | (g << 8) | (b << 0));
}
u32 RGB888ToRGB565A(u8 r, u8 g, u8 b)
{
r = r >> 3;
g = g >> 2;
b = b >> 3;
return ((r << 11) | (g << 5) | (b << 0));
}
u32 RGB888ToRGB565B(u32 rgb888)
{
u8 r, g, b;
r = (rgb888 >> 16) & 0xFF;
g = (rgb888 >> 8 ) & 0xFF;
b = (rgb888 >> 0 ) & 0xFF;
return RGB888ToRGB565A(r, g, b);
}
void init_lcd(void)
{
u32 i;
tli_parameter_struct tli_init_struct;
g_structTLILCDDev.pWidth = LCD_PIXEL_WIDTH;
g_structTLILCDDev.pHeight = LCD_PIXEL_HEIGHT;
g_structTLILCDDev.dir = LCD_SCREEN_HORIZONTAL;
g_structTLILCDDev.currentLayer = LCD_LAYER_BACKGROUND;
g_structTLILCDDev.frameBuf = s_arrBackgroundFrame;
g_structTLILCDDev.backFrameAddr = BACK_FRAME_START_ADDR;
g_structTLILCDDev.foreFrameAddr = FORE_FRAME_START_ADDR;
g_structTLILCDDev.pixelSize = 2;
for(i = 0; i < LCD_LAYER_MAX; i++)
{
g_structTLILCDDev.width[i] = g_structTLILCDDev.pWidth;
g_structTLILCDDev.height[i] = g_structTLILCDDev.pHeight;
}
rcu_periph_clock_enable(RCU_TLI);
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_GPIOC);
rcu_periph_clock_enable(RCU_GPIOD);
rcu_periph_clock_enable(RCU_GPIOE);
rcu_periph_clock_enable(RCU_GPIOF);
rcu_periph_clock_enable(RCU_GPIOH);
rcu_periph_clock_enable(RCU_GPIOG);
/* configure HSYNC(PE15), VSYNC(PA7), PCLK(PG7) */
gpio_af_set(GPIOE, GPIO_AF_14, GPIO_PIN_15);
gpio_af_set(GPIOA, GPIO_AF_14, GPIO_PIN_7);
gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_7);
gpio_mode_set(GPIOE, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_15);
gpio_output_options_set(GPIOE, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_15);
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_7);
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_7);
/* configure LCD_R7(PG6), LCD_R6(PH12), LCD_R5(PH11), LCD_R4(PA5), LCD_R3(PH9),LCD_R2(PH8),
LCD_R1(PH3), LCD_R0(PH2) */
gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_6);
gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_12);
gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_11);
gpio_af_set(GPIOA, GPIO_AF_14, GPIO_PIN_5);
gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_9);
gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_8);
gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_3);
gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_2);
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_6);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_6);
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_12);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_12);
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_11);
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_5);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_5);
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_9);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_9);
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_8);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_8);
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_3);
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_2);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_2);
/* configure LCD_G7(PD3), LCD_G6(PC7), LCD_G5(PC1), LCD_G4(PH15), LCD_G3(PH14), LCD_G2(PH13),LCD_G1(PB0), LCD_G0(PB1) */
gpio_af_set(GPIOD, GPIO_AF_14, GPIO_PIN_3);
gpio_af_set(GPIOC, GPIO_AF_14, GPIO_PIN_7);
gpio_af_set(GPIOC, GPIO_AF_14, GPIO_PIN_1);
gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_15);
gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_14);
gpio_af_set(GPIOH, GPIO_AF_14, GPIO_PIN_13);
gpio_af_set(GPIOB, GPIO_AF_14, GPIO_PIN_0);
gpio_af_set(GPIOB, GPIO_AF_14, GPIO_PIN_1);
gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_3);
gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_3);
gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_7);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_7);
gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_1);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_1);
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_15);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_15);
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_14);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_14);
gpio_mode_set(GPIOH, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_13);
gpio_output_options_set(GPIOH, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_13);
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_0);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_0);
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_1);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_1);
/* configure LCD_B7(PB9), LCD_B6(PB8), LCD_B5(PB5), LCD_B4(PC11), LCD_B3(PG11),LCD_B2(PG10), LCD_B1(PG12), LCD_B0(PG14) */
gpio_af_set(GPIOB, GPIO_AF_14, GPIO_PIN_9);
gpio_af_set(GPIOB, GPIO_AF_14, GPIO_PIN_8);
gpio_af_set(GPIOB, GPIO_AF_3, GPIO_PIN_5);
gpio_af_set(GPIOC, GPIO_AF_14, GPIO_PIN_11);
gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_11);
gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_10);
gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_12);
gpio_af_set(GPIOG, GPIO_AF_14, GPIO_PIN_14);
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_9);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_9);
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_8);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_8);
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_5);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_5);
gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11);
gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_11);
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_11);
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_10);
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_12);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_12);
gpio_mode_set(GPIOG, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_14);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_14);
/* configure LCD_DE(PF10) */
gpio_af_set(GPIOF, GPIO_AF_14, GPIO_PIN_10);
gpio_mode_set(GPIOF, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);
gpio_output_options_set(GPIOF, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_10);
/* LCD PWM BackLight(PG13) */
gpio_mode_set(GPIOG, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO_PIN_13);
gpio_output_options_set(GPIOG, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_13);
gpio_bit_set(GPIOG, GPIO_PIN_13);
//复位TLI
tli_deinit();
tli_struct_para_init(&tli_init_struct);
//配置TLI时钟
rcu_pll_input_output_clock_range_config(IDX_PLL2, RCU_PLL2RNG_1M_2M, RCU_PLL2VCO_150M_420M);
/* configure the PLL2 clock: CK_PLL2P/CK_PLL2Q/CK_PLL2R = HXTAL_VALUE / 25 * 150 / 3 */
if(ERROR == rcu_pll2_config(25, 150, 3, 3, 3)) {
while(1) {
}
}
rcu_pll_clock_output_enable(RCU_PLL2R);
rcu_tli_clock_div_config(RCU_PLL2R_DIV8);
rcu_osci_on(RCU_PLL2_CK);
if(ERROR == rcu_osci_stab_wait(RCU_PLL2_CK)) {
while(1) {
}
}
/* configure TLI parameter struct */
tli_init_struct.signalpolarity_hs = TLI_HSYN_ACTLIVE_LOW;
tli_init_struct.signalpolarity_vs = TLI_VSYN_ACTLIVE_LOW;
tli_init_struct.signalpolarity_de = TLI_DE_ACTLIVE_LOW;
tli_init_struct.signalpolarity_pixelck = TLI_PIXEL_CLOCK_TLI;
//LCD显示时序配置
tli_init_struct.synpsz_hpsz = HORIZONTAL_SYNCHRONOUS_PULSE - 1;
tli_init_struct.synpsz_vpsz = VERTICAL_SYNCHRONOUS_PULSE - 1;
tli_init_struct.backpsz_hbpsz = HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH - 1;
tli_init_struct.backpsz_vbpsz = VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH - 1;
tli_init_struct.activesz_hasz = HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH + ACTIVE_WIDTH - 1;
tli_init_struct.activesz_vasz = VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH + ACTIVE_HEIGHT - 1;
tli_init_struct.totalsz_htsz = HORIZONTAL_SYNCHRONOUS_PULSE + HORIZONTAL_BACK_PORCH + ACTIVE_WIDTH + HORIZONTAL_FRONT_PORCH - 1;
tli_init_struct.totalsz_vtsz = VERTICAL_SYNCHRONOUS_PULSE + VERTICAL_BACK_PORCH + ACTIVE_HEIGHT + VERTICAL_FRONT_PORCH - 1;
//配置背景色RGB值
tli_init_struct.backcolor_red = 0x00;
tli_init_struct.backcolor_green = 0x00;
tli_init_struct.backcolor_blue = 0x00;
tli_init(&tli_init_struct);
LCDLayerWindowSet(LCD_LAYER_BACKGROUND, 0, 0, LCD_PIXEL_WIDTH, LCD_PIXEL_HEIGHT);
LCDLayerWindowSet(LCD_LAYER_FOREGROUND, 0, 0, LCD_PIXEL_WIDTH, LCD_PIXEL_HEIGHT);
LCDLayerEnable(LCD_LAYER_BACKGROUND);
LCDLayerDisable(LCD_LAYER_FOREGROUND);
LCDTransparencySet(LCD_LAYER_BACKGROUND, 0xFF);
LCDTransparencySet(LCD_LAYER_FOREGROUND, 0xFF);
tli_dither_config(TLI_DITHER_ENABLE);
// tli_dither_config(TLI_DITHER_DISABLE);
tli_reload_config(TLI_REQUEST_RELOAD_EN);
tli_enable();
LCDLayerSwitch(LCD_LAYER_BACKGROUND);
LCDDisplayDir(LCD_SCREEN_HORIZONTAL);
LCDClear(LCD_COLOR_BLACK);
}
3.2, main.c
#include "main.h"
void cache_enable(void);
int main(void)
{
uint8_t x=0;
uint32_t sd=0;
cache_enable();
systick_config();
init_usart(115200);
init_led();
exmc_synchronous_dynamic_ram_init(EXMC_SDRAM_DEVICE0);
init_lcd();
LCDDisplayDir(LCD_SCREEN_HORIZONTAL);
LCDClear(LCD_COLOR_WHITE);
while(1)
{
switch(x)
{
case 0: LCDClear(LCD_COLOR_WHITE); break;
case 1: LCDClear(LCD_COLOR_RED ); break;
case 2: LCDClear(LCD_COLOR_GREEN); break;
case 3: LCDClear(LCD_COLOR_BLUE); break;
case 4: LCDClear(LCD_COLOR_YELLOW); break;
case 5: LCDClear(LCD_COLOR_MAGENTA); break;
case 6: LCDClear(LCD_COLOR_BLACK); break;
}
x++;
if(x>6)
{
x=0;
}
LCDShowString(10, 20, 300, 24, LCD_FONT_24, LCD_TEXT_TRANS, LCD_COLOR_RED, NULL, "GD32H759 TLI LCD TEST!");
delay_1ms(500);
}
}
void cache_enable(void)
{
/* enable i-cache */
SCB_EnableICache();
/* enable d-cache */
SCB_EnableDCache();
}
4. Operation
After downloading the program, run the video as follows:
TLI LCD
|