不含stm32 底层的代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
MyStm32Code/bsp/Src/bsp_lcd.c

905 lines
28 KiB

2 years ago
#include "bsp_lcd.h"
#include "elog.h"
LCD_TypeDef cur_lcd = INCH_4_3;
LCD_DrawPropTypeDef DrawProp[2];
MY_LCD_TypeDef my_lcd = {
0, 0, // 宽度 高度
0, 4, // 横屏还是竖屏控制:0,竖屏;1,横屏,像素大小。
LTDC_PIXEL_FORMAT_ARGB8888, // PIXEL Format
LCD_COLOR_WHITE, // color
LCD_COLOR_BLACK, // back_color
NULL, // LCD_DrawPropTypeDef draw_prop[2];
0, // show_num_mode
0, //active layer
{LCD_BUF_ADDRESS,LCD_BUF_ADDRESS}, // Layer0 Addr
};
// static void LCD_Draw_Point(uint16_t x, uint16_t y, uint32_t color);
// static void DrawChar(uint16_t Xpos, uint16_t Ypos, const uint8_t *c);
extern void DrawChar(uint16_t Xpos, uint16_t Ypos, const uint8_t *c);
void LCD_Init()
{
LTDC_Init();
// TODO my_lcd 调用LTDC画点,无需考虑坐标切换
LCD_DisplayDirection(1);
#if LCD_PIXFORMAT == LTDC_PIXEL_FORMAT_ARGB8888 || LCD_PIXFORMAT == LTDC_PIXEL_FORMAT_RGB888
my_lcd.pixelsize = 4; // 每个像素占4个字节
#else
my_lcd.pixelsize = 2; // 每个像素占2个字节
#endif
my_lcd.layeraddr[0] = LCD_BUF_ADDRESS;
my_lcd.layeraddr[1] = LCD_BUF_ADDRESS + my_lcd.width * my_lcd.height * my_lcd.pixelsize;
LCD_SetLayer(0, my_lcd.layeraddr[0] , my_lcd.color_format, LCD_COLOR_GREEN,255);
LCD_SetLayer(1, my_lcd.layeraddr[1], my_lcd.color_format, LCD_COLOR_GREEN,0);
LCD_Set_Active_layer(0);
LCD_Clear(LTDC_COLOR_GREEN); //清屏
LTDC_DISP_ON();
// LTDC_Display_Dir(1);
// my_lcd.width = my_ltdc.width;
// my_lcd.height = my_ltdc.height;
// my_lcd.activelayer = my_ltdc.activelayer;
// TODO 添加 DrawProp[2] 定义
my_lcd.draw_prop[0].BackColor = LCD_COLOR_WHITE; // 设置层的字体颜色
my_lcd.draw_prop[0].pFont = &Font16; // 设置层的字体类型
my_lcd.draw_prop[0].pCnFont = &CH_Font16; // 设置层的字体类型
my_lcd.draw_prop[0].TextColor = LCD_COLOR_BLACK; // 设置层的字体背景颜色
my_lcd.draw_prop[1].BackColor = LCD_COLOR_WHITE; // 设置层的字体颜色
my_lcd.draw_prop[1].pFont = &Font16; // 设置层的字体类型
my_lcd.draw_prop[1].pCnFont = &CH_Font16; // 设置层的字体类型
my_lcd.draw_prop[1].TextColor = LCD_COLOR_BLACK; // 设置层的字体背景颜色
}
void LCD_DisplayDirection(uint8_t dir){
my_lcd.dir = dir;
// my_ltdc.dir = dir; // 显示方向
if(dir==0) //竖屏
{
my_lcd.width=my_ltdc.pixel_height;
my_lcd.height=my_ltdc.pixel_width;
}else if(dir==1) //横屏
{
my_lcd.width=my_ltdc.pixel_width;
my_lcd.height=my_ltdc.pixel_height;
}
}
void LCD_Set_Active_layer( uint8_t layer_no )
{
my_lcd.activelayer = layer_no;
my_ltdc.activelayer = layer_no;
}
void LCD_SetLayer( uint8_t layer,uint32_t buf_addr, uint32_t layer_color_format,
uint32_t layer_back_color,uint8_t alpha )
{
LTDC_Layer_Parameter_Config( layer,buf_addr,my_lcd.color_format,alpha,
0,6,7,LCD_COLOR_GREEN);//层参数配置
LTDC_Layer_Window_Config(layer,0,0,my_ltdc.pixel_width,my_ltdc.pixel_height); //层窗口配置,以LCD面板坐标系为基准,不要随便修改!
}
/**
* @brief LCD当前层文字颜色
* @param Color:
* @retval
*/
void LCD_SetTextColor(uint32_t Color)
{
my_lcd.draw_prop[my_lcd.activelayer].TextColor = Color;
}
/**
* @brief LCD当前层文字颜色
* @retval
*/
uint32_t LCD_GetTextColor(void)
{
return my_lcd.draw_prop[my_lcd.activelayer].TextColor;
}
/**
* @brief LCD当前层的文字背景颜色
* @param Color:
* @retval
*/
void LCD_SetBackColor(uint32_t Color)
{
my_lcd.draw_prop[my_lcd.activelayer].BackColor = Color;
}
/**
* @brief LCD当前层的文字背景颜色
* @retval
*/
uint32_t LCD_GetBackColor(void)
{
return my_lcd.draw_prop[my_lcd.activelayer].BackColor;
}
/**
* @brief LCD文字的颜色和背景的颜色
* @param TextColor:
* @param BackColor:
* @retval
*/
void LCD_SetColors(uint32_t TextColor, uint32_t BackColor)
{
LCD_SetTextColor (TextColor);
LCD_SetBackColor (BackColor);
}
/**
* @brief LCD当前层显示的字体
* @param fonts:
* @retval None
*/
void LCD_SetFont(sFONT *fonts)
{
my_lcd.draw_prop[my_lcd.activelayer].pFont = fonts;
}
/**
* @brief LCD当前层显示的字体
* @retval
*/
sFONT *LCD_GetFont(void)
{
return my_lcd.draw_prop[my_lcd.activelayer].pFont;
}
/*******************************************************************************
*******************************************************************************/
// static void LCD_Draw_Point(uint16_t x, uint16_t y, uint32_t color)
// {
// LTDC_Draw_Point(x, y, color);
// }
//画点函数
//x,y:写入坐标
//color:颜色值
void LCD_Draw_Point(uint16_t x,uint16_t y,uint32_t color)
{
if(my_lcd.dir) //横屏
{
*(uint32_t*)((uint32_t)my_lcd.layeraddr[my_lcd.activelayer]+my_lcd.pixelsize*(my_lcd.width*y+x))=color;
}else //竖屏
{
*(uint32_t*)((uint32_t)my_lcd.layeraddr[my_lcd.activelayer]+my_lcd.pixelsize*(my_lcd.height*(my_lcd.width-x)+y))=color;
// *(uint32_t*)((uint32_t)my_lcd.layeraddr[my_lcd.activelayer]+my_lcd.pixelsize*(my_ltdc.pixel_width*(my_ltdc.pixel_height-x)+y))=color;
}
}
//读点函数
//x,y:读取点的坐标
//返回值:颜色值
uint32_t LCD_Read_Point(uint16_t x,uint16_t y)
{
// return *(uint32_t*)((uint32_t)my_lcd.layeraddr[my_lcd.activelayer]+my_ltdc.pixelsize*(my_ltdc.pixel_width*y+x));
if(my_lcd.dir) //横屏
{
return *(uint32_t*)((uint32_t)my_lcd.layeraddr[my_lcd.activelayer]+my_lcd.pixelsize*(my_lcd.width*y+x));
}else //竖屏
{
return *(uint32_t*)((uint32_t)my_lcd.layeraddr[my_lcd.activelayer]+my_lcd.pixelsize*(my_lcd.height*(my_lcd.width-x)+y));
}
}
/**
* @brief
* @param Xpos:
* @param Ypos:
* @param c:
* @retval
*/
void DrawChar(uint16_t Xpos, uint16_t Ypos, const uint8_t *c)
{
uint32_t i = 0, j = 0;
uint16_t height, width;
uint8_t offset;
uint8_t *pchar;
uint8_t tempchar;
uint32_t line;
uint8_t t,t1;
uint8_t y0 = Ypos;
height = my_lcd.draw_prop[my_lcd.activelayer].pFont->Height;//获取正在使用字体高度
width = my_lcd.draw_prop[my_lcd.activelayer].pFont->Width; //获取正在使用字体宽度
offset = 8 *((width + 7)/8) - width ;//计算字符的每一行像素的偏移值,实际存储大小-字体宽度
for(i = 0; i < height; i++)//遍历字体高度绘点
{
pchar = ((uint8_t *)c + (width + 7)/8 * i);//计算字符的每一行像素的偏移地址
switch( ((width + 7)/8) )//根据字体宽度来提取不同字体的实际像素值
{
case 1:
line = pchar[0]; //提取字体宽度小于8的字符的像素值
break;
case 2:
line = (pchar[0]<< 8) | pchar[1]; //提取字体宽度大于8小于16的字符的像素值
break;
case 3:
default:
line = (pchar[0]<< 16) | (pchar[1]<< 8) | pchar[2]; //提取字体宽度大于16小于24的字符的像素值
break;
}
for (j = 0; j < width; j++)//遍历字体宽度绘点
{
if( line & (1 << (width- j + offset- 1)) ) //根据每一行的像素值及偏移位置按照当前字体颜色进行绘点
{
LCD_Draw_Point((Xpos + j), Ypos, my_lcd.draw_prop[my_lcd.activelayer].TextColor);
}
else //如果这一行没有字体像素则按照背景颜色绘点
{
LCD_Draw_Point((Xpos + j), Ypos, my_lcd.draw_prop[my_lcd.activelayer].BackColor);
}
}
Ypos++;
}
}
/***************************************************************************************************************
* : LCD_DisplayChar
*
* : x - 0~799
* y - 0~479
* c - ASCII字符
*
* :
*
* : 1. 使 LCD_SetFont(&Font24) 2412ASCII字体
* 2. 使 LCD_SetColor(0xff0000FF)
* 3. 使 LCD_SetBackColor(0xff000000)
* 4. 使 LCD_DisplayChar( 10, 10, 'a') (10,10) 'a'
*
***************************************************************************************************************/
/**
* @brief
* @param Xpos: X轴起始坐标
* @param Ypos: Y轴起始坐标
* @param Ascii: ascii , 0x20 0x7E
* @retval
*/
void LCD_DisplayChar(uint16_t Xpos, uint16_t Ypos, uint8_t Ascii)
{
// DrawChar(Xpos, Ypos, &DrawProp[ActiveLayer].pFont->table[(Ascii-' ') *\
// DrawProp[ActiveLayer].pFont->Height * ((DrawProp[ActiveLayer].pFont->Width + 7) / 8)]);
DrawChar(Xpos, Ypos, &my_lcd.draw_prop[my_lcd.activelayer].pFont->table[(Ascii-' ') * \
my_lcd.draw_prop[my_lcd.activelayer].pFont->Height * \
((my_lcd.draw_prop[my_lcd.activelayer].pFont->Width + 7) / 8)] );
}
/**
* @brief
* @param Xpos: X轴起始坐标
* @param Ypos: Y轴起始坐标
* @param Text:
* @param Mode: CENTER_MODERIGHT_MODELEFT_MODE
* @retval None
*/
void LCD_DisplayStringAt(uint16_t Xpos, uint16_t Ypos, uint8_t *Text, Text_AlignModeTypdef Mode)
{
uint16_t ref_column = 1, i = 0;
uint32_t size = 0, xsize = 0;
uint8_t *ptr = Text;
/* 获取字符串大小 */
while (*ptr++) size ++ ;
/* 每一行可以显示字符的数量 */
xsize = (my_lcd.width/my_lcd.draw_prop[my_lcd.activelayer].pFont->Width);
switch (Mode)
{
case CENTER_MODE:
{
ref_column = Xpos + ((xsize - size)* my_lcd.draw_prop[my_lcd.activelayer].pFont->Width) / 2;
break;
}
case LEFT_MODE:
{
ref_column = Xpos;
break;
}
case RIGHT_MODE:
{
ref_column = - Xpos + ((xsize - size)*my_lcd.draw_prop[my_lcd.activelayer].pFont->Width);
break;
}
default:
{
ref_column = Xpos;
break;
}
}
/*检查起始行是否在显示范围内 */
if ((ref_column < 1) || (ref_column >= 0x8000))
{
ref_column = 1;
}
/* 使用字符显示函数显示每一个字符*/
while ( (*Text != 0) & (((my_lcd.width - (i*my_lcd.draw_prop[my_lcd.activelayer].pFont->Width)) & 0xFFFF) \
>= my_lcd.draw_prop[my_lcd.activelayer].pFont->Width) )
{
/* 显示一个字符 */
LCD_DisplayChar( ref_column, Ypos, *Text );
/* 根据字体大小计算下一个偏移位置 */
ref_column += my_lcd.draw_prop[my_lcd.activelayer].pFont->Width;
/* 指针指向下一个字符 */
Text++;
i++;
}
}
/**
* @brief (60)
* @param Line:
* @param ptr:
* @retval
*/
void LCD_DisplayStringLine(uint16_t Line, uint8_t *ptr)
{
LCD_DisplayStringAt(0, LINE(Line), ptr, LEFT_MODE);
}
void LCD_DisplayNumber( uint16_t Line, int32_t number, uint8_t len)
{
char Number_Buffer[15]; // 用于存储转换后的字符串
// if( LCD.ShowNum_Mode == Fill_Zero) // 多余位补0
if( my_lcd.show_num_mode ==0) // 多余位补0
{
sprintf( Number_Buffer , "%0.*d",len, number ); // 将 number 转换成字符串,便于显示
}
else // 多余位补空格
{
sprintf( Number_Buffer , "%*d",len, number ); // 将 number 转换成字符串,便于显示
}
LCD_DisplayStringAt(0, LINE(Line), (char *)Number_Buffer , LEFT_MODE) ; // 将转换得到的字符串显示出来
}
/***************************************************************************************************************************************
* : LCD_DisplayDecimals
*
* : x - 0~799
* y - 0~479
* decimals - , double型取值1.7 x 10^-308~ 1.7 x 10^+30815~16
*
* len -
* 1 -123.123 len <=8 -123.123
* 2 -123.123 len =10 -123.123()
* 3 -123.123 len =10 LCD_ShowNumMode() 0 -00123.123
*
* decs -
* 1.12345 decs 41.1235
*
* :
*
* : 1. 使 LCD_SetTextFont(&CH_Font24) 24242412ASCII字符字体
* 2. 使 LCD_SetColor(0xff0000FF)
* 3. 使 LCD_SetBackColor(0xff000000)
* 4. 使 LCD_DisplayDecimals( 10, 10, a, 5, 3) (10,10)a,53
*
*****************************************************************************************************************************************/
void LCD_DisplayDecimals( uint16_t Line, double decimals, uint8_t len, uint8_t decs)
{
char Number_Buffer[20]; // 用于存储转换后的字符串
// if( LCD.ShowNum_Mode == Fill_Zero) // 多余位填充0模式
if( my_lcd.show_num_mode ==0) // 多余位补0
{
sprintf( Number_Buffer , "%0*.*lf",len,decs, decimals ); // 将 number 转换成字符串,便于显示
}
else // 多余位填充空格
{
sprintf( Number_Buffer , "%*.*lf",len,decs, decimals ); // 将 number 转换成字符串,便于显示
}
LCD_DisplayStringAt(0, LINE(Line), (char *)Number_Buffer, LEFT_MODE) ; // 将转换得到的字符串显示出来
}
/**
* @brief
* @param usX X坐标
* @param usY Y坐标
* @param usChar
* @retval
*/
void LCD_DispChar_CH (uint16_t Xpos, uint16_t Ypos, uint16_t Text)
{
uint32_t i = 0, j = 0;
uint16_t height, width;
uint8_t offset;
uint8_t *pchar;
// uint8_t Buffer[HEIGHT_CH_CHAR*3];
uint8_t Buffer[HEIGHT_CH_CHAR*3];
uint32_t line;
GetGBKCode (Buffer, Text ); // TODO 获得Buffer
// height = HEIGHT_CH_CHAR;//取字模数据//获取正在使用字体高度
// width = WIDTH_CH_CHAR; //获取正在使用字体宽度
height = my_lcd.draw_prop[my_lcd.activelayer].pCnFont->Height;//获取正在使用字体高度
width = my_lcd.draw_prop[my_lcd.activelayer].pCnFont->Width; //获取正在使用字体宽度
offset = 8 *((width + 7)/8) - width ;//计算字符的每一行像素的偏移值,实际存储大小-字体宽度
for(i = 0; i < height; i++)//遍历字体高度绘点
{
pchar = ((uint8_t *)Buffer + (width + 7)/8 * i);//计算字符的每一行像素的偏移地址
switch(((width + 7)/8))//根据字体宽度来提取不同字体的实际像素值
{
case 1:
line = pchar[0]; //提取字体宽度小于8的字符的像素值
break;
case 2:
line = (pchar[0]<< 8) | pchar[1]; //提取字体宽度大于8小于16的字符的像素值
break;
case 3:
default:
line = (pchar[0]<< 16) | (pchar[1]<< 8) | pchar[2]; //提取字体宽度大于16小于24的字符的像素值
break;
}
for (j = 0; j < width; j++)//遍历字体宽度绘点
{
if(line & (1 << (width- j + offset- 1))) //根据每一行的像素值及偏移位置按照当前字体颜色进行绘点
{
LCD_Draw_Point((Xpos + j), Ypos, DrawProp[ActiveLayer].TextColor);
}
else//如果这一行没有字体像素则按照背景颜色绘点
{
LCD_Draw_Point((Xpos + j), Ypos, DrawProp[ActiveLayer].BackColor);
}
}
Ypos++;
}
}
/**
* @brief
Font24格式
* @param Line: LINE(0) - LINE(N)
* @param *ptr:
* @retval None
*/
void LCD_DisplayStringLine_EN_CH(uint16_t Line, uint8_t *ptr)
{
uint16_t refcolumn = 0;
/* 判断显示位置不能超出液晶的边界 */
while ((refcolumn < LCD_PIXEL_WIDTH) && ((*ptr != 0) & (((refcolumn + DrawProp[ActiveLayer].pFont->Width) & 0xFFFF) >= DrawProp[ActiveLayer].pFont->Width)))
{
/* 使用LCD显示一个字符 */
if ( * ptr <= 126 ) //英文字符
{
LCD_DisplayChar(refcolumn, LINE(Line), *ptr);
/* 根据字体偏移显示的位置 */
refcolumn += DrawProp[ActiveLayer].pFont->Width;
/* 指向字符串中的下一个字符 */
ptr++;
}
else //汉字字符
{
uint16_t usCh;
/*一个汉字两字节*/
usCh = * ( uint16_t * ) ptr;
/*交换编码顺序*/
usCh = ( usCh << 8 ) + ( usCh >> 8 );
/*显示汉字*/
LCD_DispChar_CH ( refcolumn,LINE(Line) , usCh );
/*显示位置偏移*/
refcolumn += WIDTH_CH_CHAR;
/* 指向字符串中的下一个字符 */
ptr += 2;
}
}
}
void LCD_DrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
{
int16_t deltax = 0, deltay = 0, x = 0, y = 0, xinc1 = 0, xinc2 = 0,
yinc1 = 0, yinc2 = 0, den = 0, num = 0, num_add = 0, num_pixels = 0,
curpixel = 0;
deltax = ABS(x2 - x1); /* 求x轴的绝对值 */
deltay = ABS(y2 - y1); /* 求y轴的绝对值 */
x = x1; /* 第一个像素的x坐标起始值 */
y = y1; /* 第一个像素的y坐标起始值 */
if (x2 >= x1) /* x坐标值为递增 */
{
xinc1 = 1;
xinc2 = 1;
}
else /* x坐标值为递减 */
{
xinc1 = -1;
xinc2 = -1;
}
if (y2 >= y1) /* y坐标值为递增 */
{
yinc1 = 1;
yinc2 = 1;
}
else /* y坐标值为递减 */
{
yinc1 = -1;
yinc2 = -1;
}
if (deltax >= deltay) /* 每个 y 坐标值至少有一个x坐标值*/
{
xinc1 = 0; /* 当分子大于或等于分母时不要改变 x */
yinc2 = 0; /* 不要为每次迭代更改 y */
den = deltax;
num = deltax / 2;
num_add = deltay;
num_pixels = deltax; /* x比y多的值 */
}
else /* 每个 x 坐标值至少有一个y坐标值 */
{
xinc2 = 0; /* 不要为每次迭代更改 x */
yinc1 = 0; /* 当分子大于或等于分母时不要改变 y */
den = deltay;
num = deltay / 2;
num_add = deltax;
num_pixels = deltay; /* y比x多的值 */
}
for (curpixel = 0; curpixel <= num_pixels; curpixel++)
{
LCD_Draw_Point(x, y, DrawProp[my_ltdc.activelayer].TextColor); /* 绘制当前像素点 */
num += num_add; /* 在分数的基础上增加分子 */
if (num >= den) /* 检查分子大于或等于分母 */
{
num -= den; /* 计算新的分子值 */
x += xinc1; /* x值递增 */
y += yinc1; /* y值递增 */
}
x += xinc2; /* y值递增 */
y += yinc2; /* y值递增 */
}
}
/**
* @brief
* @param x1: X坐标值
* @param y1: Y坐标值
* @param x2: X坐标值
* @param y2: Y坐标值
* @param x3: X坐标值
* @param y3: Y坐标值
* @retval
*/
void FillTriangle(uint16_t x1, uint16_t x2, uint16_t x3, uint16_t y1, uint16_t y2, uint16_t y3)
{
int16_t deltax = 0, deltay = 0, x = 0, y = 0, xinc1 = 0, xinc2 = 0,
yinc1 = 0, yinc2 = 0, den = 0, num = 0, num_add = 0, num_pixels = 0,
curpixel = 0;
deltax = ABS(x2 - x1); /* 求x轴的绝对值 */
deltay = ABS(y2 - y1); /* 求y轴的绝对值 */
x = x1; /* 第一个像素的x坐标起始值 */
y = y1; /* 第一个像素的y坐标起始值 */
if (x2 >= x1) /* x坐标值为递增*/
{
xinc1 = 1;
xinc2 = 1;
}
else /* x坐标值为递减 */
{
xinc1 = -1;
xinc2 = -1;
}
if (y2 >= y1) /* y坐标值为递增*/
{
yinc1 = 1;
yinc2 = 1;
}
else /* y坐标值为递减 */
{
yinc1 = -1;
yinc2 = -1;
}
if (deltax >= deltay) /* 每个 y 坐标值至少有一个x坐标值*/
{
xinc1 = 0; /* 当分子大于或等于分母时不要改变 x */
yinc2 = 0; /* 不要为每次迭代更改 y */
den = deltax;
num = deltax / 2;
num_add = deltay;
num_pixels = deltax; /* x比y多的值 */
}
else /* 每个 x 坐标值至少有一个y坐标值 */
{
xinc2 = 0; /* 不要为每次迭代更改 x */
yinc1 = 0; /* 当分子大于或等于分母时不要改变 y */
den = deltay;
num = deltay / 2;
num_add = deltax;
num_pixels = deltay; /* y比x多的值 */
}
for (curpixel = 0; curpixel <= num_pixels; curpixel++)
{
LCD_DrawLine(x, y, x3, y3);
num += num_add; /* 在分数的基础上增加分子 */
if (num >= den) /* 判断分子是否大于或等于分母 */
{
num -= den; /* 计算新的分子值 */
x += xinc1; /* x值递增 */
y += yinc1; /* y值递增 */
}
x += xinc2; /* x值递增 */
y += yinc2; /* y值递增 */
}
}
// 画矩形
//(x1,y1),(x2,y2):矩形的对角坐标
void LCD_DrawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
{
LCD_DrawLine(x1, y1, x2, y1);
LCD_DrawLine(x1, y1, x1, y2);
LCD_DrawLine(x1, y2, x2, y2);
LCD_DrawLine(x2, y1, x2, y2);
}
// 在指定位置画一个指定大小的圆
//(x,y):中心点
// r :半径
void LCD_DrawCircle(uint16_t x, uint16_t y, uint16_t r)
{
int Xadd = -r, Yadd = 0, err = 2-2*r, e2;
do {
LCD_Draw_Point(x-Xadd,y+Yadd,my_lcd.color);
LCD_Draw_Point(x+Xadd,y+Yadd,my_lcd.color);
LCD_Draw_Point(x+Xadd,y-Yadd,my_lcd.color);
LCD_Draw_Point(x-Xadd,y-Yadd,my_lcd.color);
e2 = err;
if (e2 <= Yadd) {
err += ++Yadd*2+1;
if (-Xadd == Yadd && e2 <= Xadd) e2 = 0;
}
if (e2 > Xadd) err += ++Xadd*2+1;
}
while (Xadd <= 0);
}
// 在指定区域内填充单个颜色
//(sx,sy),(ex,ey):填充矩形对角坐标,区域大小为:(ex-sx+1)*(ey-sy+1)
// color:要填充的颜色
void LCD_Fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint32_t color)
{
// TODO: 未测试正确
uint32_t offline;
uint32_t address;
offline = my_lcd.width - (ex-sx+1);
address = my_lcd.layeraddr[my_lcd.activelayer] + my_lcd.pixelsize*(sy*my_lcd.width +sx);
// DMA2D->CR = 0x00030000UL; // 配置为寄存器到储存器模式
// DMA2D->OCOLR = color; // 设置填充使用的颜色,格式应该与设置的颜色格式相同
// DMA2D->OMAR = (uint32_t)address; // 填充区域的起始内存地址
// DMA2D->OOR = offline; // 行偏移,即跳过的像素,注意是以像素为单位
// DMA2D->OPFCCR = my_lcd.color_format; // 设置颜色格式
// DMA2D->NLR = (uint32_t)( (ex-sx+1) << 16) | (uint16_t)(ey-sy+1); // 设置填充区域的宽和高,单位是像素
// // 传输中断
// // DMA2D->CR |= DMA2D_IT_TC|DMA2D_IT_TE|DMA2D_IT_CE;
// // DMA2D->CR |= DMA2D_CR_START;
// // 启动传输 阻塞 -- 阻塞一般用于清屏,R2M 模式
// DMA2D->CR |= DMA2D_CR_START;
// while (DMA2D->CR & DMA2D_CR_START) {}
DMA2D_Fill(address, (ex-sx+1), (ey-sy+1), offline, my_lcd.color_format, color);
}
// 在指定区域内填充指定颜色块
//(sx,sy),(ex,ey):填充矩形对角坐标,区域大小为:(ex-sx+1)*(ey-sy+1)
// color:要填充的颜色
// 注意两个地址的offline
void LCD_Color_Fill(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, uint16_t *color)
{
// LTDC_Color_Fill(sx, sy, ex, ey, color);
uint32_t offline;
offline = my_lcd.width - (ex-sx+1);
DMA2D_MemCopy(my_lcd.color_format,
color, (uint32_t)my_lcd.layeraddr[my_lcd.activelayer],
(ex-sx+1), (ey-sy+1), offline, offline );
}
void LCD_Clear( uint32_t color)
{
LCD_Fill( 0, 0, my_lcd.width, my_lcd.height, color );
}
/***************************************************************************************************************************************
* : LCD_FillRect
*
* : x - 0~799
* y - 0~479
* width - 800
* height - 480
*
* : (x,y)
*
* : 1. 使DMA2D实现
* 2.
*
*****************************************************************************************************************************************/
void LCD_FillRect(uint16_t x, uint16_t y, uint16_t width, uint16_t height)
{
DMA2D->CR &= ~(DMA2D_CR_START); // 停止DMA2D
DMA2D->CR = DMA2D_R2M; // 寄存器到SDRAM
DMA2D->OPFCCR = my_lcd.color_format; // 设置颜色格式
DMA2D->OCOLR = my_lcd.color; // 颜色
// if(my_lcd.dir == 1) //横屏填充
// {
// DMA2D->OOR = my_lcd.width - width; // 设置行偏移
// DMA2D->OMAR = my_ltdc.layeraddr[my_ltdc.activelayer] + LCD.BytesPerPixel*(my_lcd.width * y + x); // 地址;
// DMA2D->NLR = (width<<16)|(height); // 设定长度和宽度
// }
// else //竖屏填充
// {
// DMA2D->OOR = my_lcd.width - height; // 设置行偏移
// DMA2D->OMAR = my_ltdc.layeraddr[my_ltdc.activelayer] + LCD.BytesPerPixel*((my_lcd.height - x - 1 - width)*LCD_Width + y); // 地址
// DMA2D->NLR = (width)|(height<<16); // 设定长度和宽度
// }
DMA2D->OOR = my_lcd.width - width; // 设置行偏移
DMA2D->OMAR = my_lcd.layeraddr[my_lcd.activelayer] + my_lcd.pixelsize*(my_lcd.width * y + x); // 地址;
DMA2D->NLR = (width<<16)|(height); // 设定长度和宽度
DMA2D->CR |= DMA2D_CR_START; // 启动DMA2D
while (DMA2D->CR & DMA2D_CR_START) ; // 等待传输完成
}
/***************************************************************************************************************************************
* : LCD_FillCircle
*
* : x - 0~799
* y - 0~479
* r -
*
* : (x,y) r
*
* : 1. ST官方评估板的例程
* 2.
*
*****************************************************************************************************************************************/
void LCD_FillCircle(uint16_t x, uint16_t y, uint16_t r)
{
int32_t D; /* Decision Variable */
uint32_t CurX;/* Current X Value */
uint32_t CurY;/* Current Y Value */
D = 3 - (r << 1);
CurX = 0;
CurY = r;
while (CurX <= CurY)
{
if(CurY > 0)
{
LCD_DrawLine(x - CurX, y - CurY,x - CurX,y - CurY + 2*CurY);
LCD_DrawLine(x + CurX, y - CurY,x + CurX,y - CurY + 2*CurY);
}
if(CurX > 0)
{
LCD_DrawLine(x - CurY, y - CurX,x - CurY,y - CurX + 2*CurX);
LCD_DrawLine(x + CurY, y - CurX,x + CurY,y - CurX + 2*CurX);
}
if (D < 0)
{
D += (CurX << 2) + 6;
}
else
{
D += ((CurX - CurY) << 2) + 10;
CurY--;
}
CurX++;
}
LCD_DrawCircle(x, y, r);
}
/***************************************************************************************************************************************
* : LCD_DrawImage
*
* : x - 0~799
* y - 0~479
* width - 800
* height - 480
* *pImage -
*
* :
*
* : 使 LCD_SetColor()
*
*****************************************************************************************************************************************/
void LCD_DrawImage(uint16_t x,uint16_t y,uint16_t width,uint16_t height,const uint8_t *pImage)
{
uint8_t disChar; //字模的值
uint16_t Xaddress = x; //水平坐标
uint16_t i=0,j=0,m=0;
for(i = 0; i <height; i++)
{
for(j = 0; j <(float)width/8; j++)
{
disChar = *pImage;
for(m = 0; m < 8; m++)
{
if(disChar & 0x01)
{
LCD_Draw_Point(Xaddress,y,my_lcd.color); //当前模值不为0时,使用画笔色绘点
}
else
{
LCD_Draw_Point(Xaddress,y,my_lcd.color); //否则使用背景色绘制点
}
disChar >>= 1;
Xaddress++; //水平坐标自加
if( (Xaddress - x)==width ) //如果水平坐标达到了字符宽度,则退出当前循环
{ //进入下一行的绘制
Xaddress = x;
y++;
break;
}
}
pImage++;
}
}
}