1.添加了必要的注释和readme文件以提高代码可读性和项目文档化。2.增加了按键按下时LCD屏幕显示功能

This commit is contained in:
2026-01-25 15:42:48 +08:00
parent 373b31adfd
commit 6a861cee4e
30 changed files with 2311 additions and 50645 deletions

View File

@@ -1319,28 +1319,45 @@ void FillBoxScreen(uint8_t x, uint8_t y, uint8_t len, uint8_t high, uint8_t byte
y++; /* 移动到下一行 */
}
}
/**
* @brief LCD 控制与背光 GPIO 初始化
* @note 初始化 UC1698U 控制器所需的 GPIO 引脚,分为两组:
* GPIOB 组(控制信号与背光):
* | 引脚 | 功能 | 说明 |
* |------|----------|----------------|
* | PB0 | 背光 | 背光开关 |
* | PB10 | RST | 复位信号 |
* | PB11 | CS | 片选 |
* | PB12 | RD | 读使能 |
* | PB13 | WR | 写使能 |
* | PB14 | CD | 命令/数据选择 |
* GPIOE 组(数据总线):
* | 引脚 | 功能 | 说明 |
* |-----------|----------|-------------------------|
* | PE8~PE15 | D0~D7 | 8 位并行数据总线 |
* 配置为推挽输出、上拉、高速模式
* @retval 无
*/
void LCD_GPIO_Init(void)
{
GPIO_InitTypeDef gpio_init_struct;
__HAL_RCC_GPIOB_CLK_ENABLE(); // 时钟初始化
__HAL_RCC_GPIOE_CLK_ENABLE(); // 时钟初始化
__HAL_RCC_GPIOB_CLK_ENABLE(); /**< 使能 GPIOB 时钟 */
__HAL_RCC_GPIOE_CLK_ENABLE(); /**< 使能 GPIOE 时钟 */
// 配置 LCD 引脚
/* ========== GPIOB控制信号与背光 ========== */
gpio_init_struct.Pin = GPIO_PIN_14 | GPIO_PIN_13 | GPIO_PIN_12 | GPIO_PIN_11 | GPIO_PIN_10 | GPIO_PIN_0;
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP; /*推挽输出模式*/
gpio_init_struct.Pull = GPIO_PULLUP;
gpio_init_struct.Speed = GPIO_SPEED_HIGH;
// 初始化 LCD 选引脚
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP; /**< 推挽输出 */
gpio_init_struct.Pull = GPIO_PULLUP; /**< 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_HIGH; /**< 高速 */
HAL_GPIO_Init(GPIOB, &gpio_init_struct);
// 配置 LCD 引脚
/* ========== GPIOE8 位数据总线 ========== */
gpio_init_struct.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP; /*推挽输出模式*/
gpio_init_struct.Pull = GPIO_PULLUP;
gpio_init_struct.Speed = GPIO_SPEED_HIGH;
// 初始化 LCD 选引脚
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP; /**< 推挽输出 */
gpio_init_struct.Pull = GPIO_PULLUP; /**< 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_HIGH; /**< 高速 */
HAL_GPIO_Init(GPIOE, &gpio_init_struct);
}
/**
@@ -1422,64 +1439,66 @@ void DisplayNANRUI_LOGO(void)
}
/*******************************************************************************
* FunctionName : Display_Picture()
* Description : 图片显示程序
* EntryParameter : none
* ReturnValue : none
*******************************************************************************/
/**
* @brief 在 LCD 上显示指定尺寸的位图
* @param Width 位图宽度(像素,不超过 160
* @param Height 位图高度(像素,不超过 160
* @param picture 位图数据指针(每像素 1 位,每行 Width/8 字节,行内取反显示)
* @note 使用 4K 色RGB444模式位图居中显示
* X 坐标按每 3 像素递增;每行末尾补 0 使点数能被 3 整除
* 若 Width 或 Height 大于 160 则直接返回
* @retval 无
*/
void Display_BMP(uint32_t Width, uint32_t Height, const uint8_t* picture)
{
uint8_t i,n;
uint8_t disp_point[4]={0x00,0x0f,0xf0,0xff};
uint8_t x, y;
uint32_t bytesNumOfRow;
set_color_mode(COLOR_4K_444);//设置4.4.4.模式
if(Width>160 || Height>160)
return ; //设置4.4.4.模式
x = ((160-Width)/2)/3; //x坐标为每3个像素点递增
y = (160-Height)/2 + Height; //x坐标为每3个像素点递增
bytesNumOfRow = Width/8;
for(i=0;i<Height;i++)
{
SetAddress(x, y-i);
for(n=0;n<bytesNumOfRow;n++)
{
WriteData(disp_point[(~picture[i*bytesNumOfRow+n]>>6)&0x03]);
WriteData(disp_point[(~picture[i*bytesNumOfRow+n]>>4)&0x03]);
WriteData(disp_point[(~picture[i*bytesNumOfRow+n]>>2)&0x03]);
WriteData(disp_point[(~picture[i*bytesNumOfRow+n]>>0)&0x03]);
}
WriteData(0x00); //补全每行末尾的数据,使总点数能被三整除
}
uint8_t i, n;
uint8_t disp_point[4] = {0x00, 0x0f, 0xf0, 0xff}; /**< 4K 色像素值映射 */
uint8_t x, y;
uint32_t bytesNumOfRow;
set_color_mode(COLOR_4K_444); /**< 设置 4K 色模式 */
if (Width > 160 || Height > 160)
return;
x = ((160 - Width) / 2) / 3; /**< 居中 X每 3 像素为一单位 */
y = (160 - Height) / 2 + Height; /**< 居中 Y自下而上绘制 */
bytesNumOfRow = Width / 8;
for (i = 0; i < Height; i++)
{
SetAddress(x, y - i);
for (n = 0; n < bytesNumOfRow; n++)
{
WriteData(disp_point[(~picture[i * bytesNumOfRow + n] >> 6) & 0x03]);
WriteData(disp_point[(~picture[i * bytesNumOfRow + n] >> 4) & 0x03]);
WriteData(disp_point[(~picture[i * bytesNumOfRow + n] >> 2) & 0x03]);
WriteData(disp_point[(~picture[i * bytesNumOfRow + n] >> 0) & 0x03]);
}
WriteData(0x00); /**< 补足使每行点数能被 3 整除 */
}
}
/*******************************************************************************
* FunctionName : DisplayNANRUI_BMP()
* Description : BMP格式显示测试
* EntryParameter : none
* ReturnValue : none
*******************************************************************************/
/**
* @brief 显示南瑞NANRUILogo 位图
* @note 调用 Display_BMP尺寸 128×50 像素,数据源为 NANRUI_BMP
* @retval 无
*/
void DisplayNANRUI_BMP(void)
{
const uint32_t xmax=128, ymax=50;
Display_BMP(xmax, ymax, NANRUI_BMP);
const uint32_t xmax = 128, ymax = 50;
Display_BMP(xmax, ymax, NANRUI_BMP);
}
/*******************************************************************************
* FunctionName : DisplayNANRUI_BMP()
* Description : BMP格式显示测试
* EntryParameter : none
* ReturnValue : none
*******************************************************************************/
/**
* @brief 显示 QQ Logo 位图
* @note 调用 Display_BMP尺寸 96×94 像素,数据源为 QQ_BMP
* @retval 无
*/
void DisplayQQ_BMP(void)
{
const uint32_t xmax=96, ymax=94;
Display_BMP(xmax, ymax, QQ_BMP);
const uint32_t xmax = 96, ymax = 94;
Display_BMP(xmax, ymax, QQ_BMP);
}
/**
* @brief 绘制单条水平线(内部函数)
@@ -1589,58 +1608,6 @@ void DiaplayHeadGraph(void)
/* 绘制左侧垂直边框从第18行开始高度142 */
DisplayVerticalLine(0, 18, 142, 0x80);
}
/**
* @brief 绘制带阴影效果的方框(内部函数)
* @param x 起始列坐标X坐标
* @param y 起始行坐标Y坐标
* @param len 方框宽度(像素单位)
* @param high 方框高度(行数)
* @note 绘制一个带3D阴影效果的方框
* 包括:左边框、上边框、下边框(带阴影)、右边框(带渐变阴影效果)
* @retval 无
*/
static void DrawBox(uint8_t x, uint8_t y, uint8_t len, uint8_t high)
{
/* 绘制左边框 */
DisplayVerticalLine(x, y, high, 0x80);
/* 绘制上边框 */
DisplayHorizontalLine(x, y, len);
/* 绘制下边框 */
DisplayHorizontalLine(x, y + high, len);
/* 绘制第一层阴影 */
writebyte(x, y + high + 1, 0x7F, RESET);
DisplayHorizontalLine(x + 1, y + high + 1, len);
/* 绘制第二层阴影 */
writebyte(x, y + high + 2, 0x3F, RESET);
DisplayHorizontalLine(x + 1, y + high + 2, len);
/* 绘制右边框(带渐变阴影效果) */
DisplayVerticalLine(x + len, y, high + 3, 0x80); /* 主边框 */
DisplayVerticalLine(x + len, y + 1, high + 2, 0xC0); /* 第一层阴影 */
DisplayVerticalLine(x + len, y + 2, high + 1, 0xE0); /* 第二层阴影 */
}
/**
* @brief 绘制无阴影效果的方框(内部函数)
* @param x 起始列坐标X坐标
* @param y 起始行坐标Y坐标
* @param len 方框宽度(像素单位)
* @param high 方框高度(行数)
* @note 绘制一个简单的方框,无阴影效果
* 包括:左边框、上边框、下边框、右边框
* @retval 无
*/
static void DrawBox_NoShadow(uint8_t x, uint8_t y, uint8_t len, uint8_t high)
{
DisplayVerticalLine(x, y, high, 0x80); /* 左边框 */
DisplayHorizontalLine(x, y, len); /* 上边框 */
DisplayHorizontalLine(x, y + high, len); /* 下边框 */
DisplayVerticalLine(x + len - 1, y, high, 0x20); /* 右边框 */
}
/**
* @brief 绘制一个像素点(带渐变效果)
* @param x 列坐标X坐标
@@ -1665,168 +1632,3 @@ void DrawPoint(uint8_t x, uint8_t y)
DisplayVerticalLine(x + 1, y + 4, 1, 0x60);
DisplayHorizontalLine(x + 1, y + 5, 1);
}
/**
* @brief 显示消息提示框(静态模式)
* @note 在屏幕指定位置显示一个带阴影的消息提示框
* 位置:坐标(10,40)尺寸33x50像素
* 先清除背景区域,然后绘制方框
* 动态框模式代码已注释需要定义DYNAMIC_BOX
* @retval 无
*/
void MessageBox(void)
{
/* 静态框模式 */
FillBoxScreen(9, 37, 35, 59, 0x00); /* 清除背景区域 */
DrawBox(10, 40, 33, 50); /* 绘制带阴影的方框 */
}
/**
* @brief 清除消息提示框
* @note 清除消息提示框的整个显示区域
* 位置和尺寸与MessageBox函数对应
* @retval 无
*/
void ClrMessageBox(void)
{
FillBoxScreen(9, 37, 35, 59, 0x00); /* 清除消息框区域 */
}
/**
* @brief 清除消息提示框内容区域
* @note 只清除消息框内部的内容区域,保留边框
* 用于刷新消息内容而不重新绘制边框
* @retval 无
*/
void ClrMessageBoxContent(void)
{
FillBoxScreen(11, 41, 31, 48, 0x00); /* 清除内容区域(保留边框) */
}
/**
* @brief 显示可编程消息提示框(支持静态和动态模式)
* @param x 起始列坐标X坐标
* @param y 起始行坐标Y坐标
* @param size 方框大小参数(影响方框尺寸)
* @note 根据编译选项显示静态或动态消息框
* 静态模式:直接绘制完整方框
* 动态模式:逐步绘制方框,产生动画效果
* 方框尺寸:宽度=size高度=size*3/2+9
* @retval 无
*/
void ProgramableMessageBox(uint8_t x, uint8_t y, uint8_t size)
{
#ifdef STATIC_BOX /* 静态框模式 */
FillBoxScreen(x - 1, y - 3, size + 2, size * 3 / 2 + 9, 0x00); /* 清除背景 */
DrawBox(x, y, size, size * 3 / 2 + 9); /* 绘制方框 */
#endif //#ifdef STATIC_BOX
#ifdef DYNAMIC_BOX /* 动态框模式 */
FillBoxScreen(x - 1, y - 3, size * 2 + 2, size * 3 + 9, 0x00); /* 清除背景 */
/* 逐步绘制方框,产生动画效果 */
for(int i = 0; i < size; i++)
{
EraseLine(x, y, i * 2, i * 3); /* 擦除旧线条 */
DrawBox(x, y, (i + 1) * 2, (i + 1) * 3); /* 绘制新方框 */
delay_ms(5); /* 延时,产生动画效果 */
}
#endif //#ifdef DYNAMIC_BOX
}
/**
* @brief 绘制下拉菜单组合框
* @param x 起始列坐标X坐标
* @param y 起始行坐标Y坐标
* @param len 菜单框宽度(像素单位)
* @param items 菜单项数量
* @note 根据编译选项显示静态或动态菜单框
* 静态模式:直接绘制完整菜单框
* 动态模式:逐步绘制菜单框,产生下拉动画效果
* 每个菜单项高度20像素
* @retval 无
*/
void DrawMenuComboBox(uint8_t x, uint8_t y, uint8_t len, uint8_t items)
{
#ifdef STATIC_BOX /* 静态框模式 */
FillBoxScreen(x - 1, y - 6, len + 3, items * 20 + 9, 0x00); /* 清除背景 */
DrawBox(x - 1, y - 3, len + 2, items * 20); /* 绘制菜单框 */
#endif //#ifdef STATIC_BOX
#ifdef DYNAMIC_BOX /* 动态框模式 */
FillBoxScreen(x - 2, y - 6, len + 3, items * 20 + 9, 0x00); /* 清除背景 */
/* 逐步绘制菜单框,产生下拉动画效果 */
for(int i = 0; i < items; i++)
{
EraseLine(x - 1, y - 6, len + 2, i * 20 + 3); /* 擦除旧线条 */
DrawBox(x - 1, y - 3, len + 2, (i + 1) * 20); /* 绘制新菜单框 */
delay_ms(15); /* 延时,产生动画效果 */
}
#endif //#ifdef DYNAMIC_BOX
}
/**
* @brief 显示消息设置提示框(带标题栏,清除背景)
* @param title 标题字符串指针GB2312编码
* @note 显示一个带标题栏的消息设置框
* 先清除背景区域,然后绘制无阴影方框
* 标题栏区域填充白色,标题文字反显
* 位置:坐标(8,40)尺寸37x70像素
* @retval 无
*/
void MessageSetBox(const uint8_t *title)
{
FillBoxScreen(7, 37, 39, 79, 0x00); /* 清除背景区域 */
DrawBox_NoShadow(8, 40, 37, 70); /* 绘制无阴影方框 */
FillBoxScreen(8, 40, 37, 20, 0xFF); /* 填充标题栏区域(白色) */
HZ12AndChar_Printf(18, 43, title, SET); /* 显示标题(反显) */
}
/**
* @brief 显示消息设置提示框(带标题栏,不清除背景)
* @param title 标题字符串指针GB2312编码
* @note 功能与MessageSetBox类似但不清除背景区域
* 用于在已有内容上叠加显示消息框
* @retval 无
*/
void MessageSetBox_NoClear(const uint8_t *title)
{
DrawBox_NoShadow(8, 40, 37, 70); /* 绘制无阴影方框 */
FillBoxScreen(8, 40, 37, 20, 0xFF); /* 填充标题栏区域(白色) */
HZ12AndChar_Printf(18, 43, title, SET); /* 显示标题(反显) */
}
/**
* @brief 清除消息设置框的内容显示区域
* @note 只清除消息框内部的内容区域,保留标题栏和边框
* 用于刷新消息内容而不重新绘制整个框
* @retval 无
*/
void ClrMessageSetBox(void)
{
FillBoxScreen(9, 61, 34, 48, 0x00); /* 清除内容区域(保留标题栏和边框) */
}
/**
* @brief 删除消息设置提示框
* @note 清除整个消息设置框的显示区域
* 包括标题栏、边框和内容区域
* @retval 无
*/
void DeleteMessageSetBox(void)
{
FillBoxScreen(7, 37, 39, 79, 0x00); /* 清除整个消息框区域 */
}
/**
* @brief 绘制记录框(用于显示记录列表)
* @param x 起始列坐标X坐标
* @param y 起始行坐标Y坐标
* @param len 框宽度(像素单位)
* @param items 记录项数量
* @note 绘制一个带阴影的记录列表框
* 每个记录项高度16像素显示区域19像素包括间距
* 先清除背景,然后绘制方框
* @retval 无
*/
void DrawRecordBox(uint8_t x, uint8_t y, uint8_t len, uint8_t items)
{
FillBoxScreen(x - 1, y - 3, len + 2, items * 16 + 6, 0x00); /* 清除背景 */
DrawBox(x - 1, y - 3, len + 2, items * 19); /* 绘制记录框 */
}