使用填充函数,实现在 LCD 上显示数码管字符
驱动源码
驱动代码的 API 接口如下所示。GUIDrawNixieTubeLine2 函数用于绘制单一的字符笔画,GUIDrawNixieTube 函数则用于绘制数码管字符。用户使用的时候,只关心 GUIDrawNixieTube 函数即可。GUIDrawNixieTube 函数调用 GUIDrawNixieTubeLine2 函数实现字符绘制。
GUIDrawNixieTube 函数各个参数的意义在源码中有注释,使用的时候需要仔细核对。
注意:GUIDrawNixieTube 函数中,space0 和 space1 用来控制不同笔画之间的间隙,间隙过小有可能会出现笔画重合的情况。
void GUIDrawNixieTubeLine2(unsigned int x, unsigned int y, unsigned int width, unsigned int height,
unsigned int type, unsigned int color);
void GUIDrawNixieTube(unsigned int x, unsigned int y, unsigned int width, unsigned int height,
unsigned int lineSize, unsigned int space0, unsigned int space1, char code,
unsigned int color, unsigned int bcolor);
驱动代码源码如下所示。
/*********************************************************************************************************
* 函数名称: GUIDrawNixieTubeLine2
* 函数功能: 绘制数码管直线
* 输入参数: x,y :整型变量。起点坐标
* width :整型变量。宽度。
* height:整型变量。高度。
* type :整型变量。线条类型取值范围 0-6,具体如下所示。
* _________
* | 0 |
* 5 | | 1
* |_________|
* | 6 |
* 4 | | 2
* |_________|
* 3
* color :颜色值。
* 输出参数: void
* 返 回 值: void
* 创建日期: 2023年10月24日
* 注 意:
*********************************************************************************************************/
void GUIDrawNixieTubeLine2(unsigned int x, unsigned int y, unsigned int width, unsigned int height,
unsigned int type, unsigned int color)
{
unsigned int tx0, ty0, tx1, ty1, x0, y0, x1, y1, inverseFlag;
//参数校验
if ((0 == width) || (0 == height) || (type > 6)) { return; }
//求解目标区域
tx0 = x;
ty0 = y;
tx1 = tx0 + width - 1;
ty1 = ty0 + height - 1;
//绘制
if (0 == type)
{
x0 = tx0;
x1 = tx1;
y0 = ty0;
y1 = ty1;
while ((y0 <= y1) && (x0 <= x1) && (x0 >= tx0) && (x1 <= tx1) && (y0 >= ty0) && (y1 <= ty1))
{
GUIFillColor(x0, y0, x1, y0, color);
y0++; x0++; x1--;
}
}
else if (1 == type)
{
x0 = x1 = tx1;
y0 = ty0;
y1 = ty1 - (1 * width / 3);
inverseFlag = 0;
while ((x0 >= tx0) && (x1 <= tx1) && (y0 >= ty0) && (y1 <= ty1))
{
GUIFillColor(x0, y0, x1, y1, color);
if (0 == inverseFlag)
{
x0--; x1--; y0++; y1++;
if (y1 > ty1)
{
y1 = ty1 - 1;
inverseFlag = 1;
}
}
else
{
x0--; x1--; y0++; y1--;
}
}
}
else if (2 == type)
{
x0 = x1 = tx1;
y0 = ty0 + (1 * width / 3);
y1 = ty1;
inverseFlag = 0;
while ((x0 >= tx0) && (x1 <= tx1) && (y0 >= ty0) && (y1 <= ty1))
{
GUIFillColor(x0, y0, x1, y1, color);
if (0 == inverseFlag)
{
x0--; x1--; y0--; y1--;
if (y0 < ty0)
{
y0 = ty0 + 1;
inverseFlag = 1;
}
}
else
{
x0--; x1--; y0++; y1--;
}
}
}
else if (3 == type)
{
x0 = tx0;
x1 = tx1;
y0 = ty0;
y1 = ty1;
while ((y0 <= y1) && (x0 <= x1) && (x0 >= tx0) && (x1 <= tx1) && (y0 >= ty0) && (y1 <= ty1))
{
GUIFillColor(x0, y1, x1, y1, color);
y1--; x0++; x1--;
}
}
else if (4 == type)
{
x0 = x1 = tx0;
y0 = ty0 + (1 * width / 3);
y1 = ty1;
inverseFlag = 0;
while ((x0 >= tx0) && (x1 <= tx1) && (y0 >= ty0) && (y1 <= ty1))
{
GUIFillColor(x0, y0, x1, y1, color);
if (0 == inverseFlag)
{
x0++; x1++; y0--; y1--;
if (y0 < ty0)
{
y0 = ty0 + 1;
inverseFlag = 1;
}
}
else
{
x0++; x1++; y0++; y1--;
}
}
}
else if (5 == type)
{
x0 = x1 = tx0;
y0 = ty0;
y1 = ty1 - (1 * width / 3);
inverseFlag = 0;
while ((x0 >= tx0) && (x1 <= tx1) && (y0 >= ty0) && (y1 <= ty1))
{
GUIFillColor(x0, y0, x1, y1, color);
if (0 == inverseFlag)
{
x0++; x1++; y0++; y1++;
if (y1 > ty1)
{
y1 = ty1 - 1;
inverseFlag = 1;
}
}
else
{
x0++; x1++; y0++; y1--;
}
}
}
else if (6 == type)
{
x0 = tx0;
x1 = tx1;
y0 = ty0;
y1 = (ty0 + ty1) / 2;
while ((y0 <= y1) && (x0 <= x1) && (x0 >= tx0) && (x1 <= tx1) && (y0 >= ty0) && (y1 <= ty1))
{
GUIFillColor(x0, y1, x1, y1, color);
y1--; x0++; x1--;
}
x0 = tx0;
x1 = tx1;
if (0 == (height % 2)) { y0 = (ty0 + ty1 + 1) / 2; }
else { y0 = (ty0 + ty1) / 2; }
y1 = ty1;
while ((y0 <= y1) && (x0 <= x1) && (x0 >= tx0) && (x1 <= tx1) && (y0 >= ty0) && (y1 <= ty1))
{
GUIFillColor(x0, y0, x1, y0, color);
y0++; x0++; x1--;
}
}
}
/*********************************************************************************************************
* 函数名称: GUIDrawNixieTube
* 函数功能: 绘制数码管
* 输入参数: x,y :整型变量。起点坐标
* width :整型变量。宽度。
* height :整型变量。高度。
* lineSize:整型变量。线条宽度。
* space0 :整型变量。用于控制 0-5 号线之间的缝隙大小。
* space1 :整型变量。用于控制 6 号线的缝隙大小。
* code :整型变量。字符编码,取值 '0'-'9'、'A'、'b'、'C'、'd'、'E'、'F'、'-'
* color :整型变量。颜色值
* bcolor :整型变量。背景颜色值。
* 输出参数: void
* 返 回 值: void
* 创建日期: 2023年10月24日
* 注 意:
*********************************************************************************************************/
void GUIDrawNixieTube(unsigned int x, unsigned int y, unsigned int width, unsigned int height,
unsigned int lineSize, unsigned int space0, unsigned int space1, char code,
unsigned int color, unsigned int bcolor)
{
//共阳极七段数码管译码表
//对应 '0'-'9'、'A'、'b'、'C'、'd'、'E'、'F'、'-'
static const unsigned char s_arrNixieTubeTbl[] = {
0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E, 0xBF };
unsigned int tx0, ty0, tx1, ty1, x0, y0, x1, y1, tWidth, tHeight, tCode;
//参数校验
if((0 == width) || (0 == height) || (0 == lineSize)) { return; }
//取出译码表中的数据
if ((code >= '0') && (code <= '9'))
{
tCode = s_arrNixieTubeTbl[code - '0'];
}
else
{
//'A'、'b'、'C'、'd'、'E'、'F'、'-'
switch (code)
{
case 'A': tCode = s_arrNixieTubeTbl[10]; break;
case 'b': tCode = s_arrNixieTubeTbl[11]; break;
case 'C': tCode = s_arrNixieTubeTbl[12]; break;
case 'd': tCode = s_arrNixieTubeTbl[13]; break;
case 'E': tCode = s_arrNixieTubeTbl[14]; break;
case 'F': tCode = s_arrNixieTubeTbl[15]; break;
case '-': tCode = s_arrNixieTubeTbl[16]; break;
default: return;
}
}
//确定显示区域大小
tx0 = x;
ty0 = y;
tx1 = tx0 + width - 1;
ty1 = ty0 + height - 1;
//绘制 0 号线
x0 = tx0 + space0;
x1 = tx1 - space0;
y0 = ty0;
y1 = ty0 + lineSize - 1;
tWidth = x1 - x0 + 1;
tHeight = y1 - y0 + 1;
if(0 == (tCode & 0x01)) { GUIDrawNixieTubeLine2(x0, y0, tWidth, tHeight, 0, color); }
else { GUIDrawNixieTubeLine2(x0, y0, tWidth, tHeight, 0, bcolor); }
tCode = tCode >> 1;
//绘制 1 号线
x0 = tx1 - lineSize + 1;
x1 = tx1;
y0 = ty0 + space0;
y1 = ((ty0 + ty1) / 2) - space0;
tWidth = x1 - x0 + 1;
tHeight = y1 - y0 + 1;
if (0 == (tCode & 0x01)) { GUIDrawNixieTubeLine2(x0, y0, tWidth, tHeight, 1, color); }
else { GUIDrawNixieTubeLine2(x0, y0, tWidth, tHeight, 1, bcolor); }
tCode = tCode >> 1;
//绘制 2 号线
x0 = tx1 - lineSize + 1;
x1 = tx1;
y0 = ((ty0 + ty1) / 2) + space0;
y1 = ty1 - space0;
tWidth = x1 - x0 + 1;
tHeight = y1 - y0 + 1;
if (0 == (tCode & 0x01)) { GUIDrawNixieTubeLine2(x0, y0, tWidth, tHeight, 2, color); }
else { GUIDrawNixieTubeLine2(x0, y0, tWidth, tHeight, 2, bcolor); }
tCode = tCode >> 1;
//绘制 3 号线
x0 = tx0 + space0;
x1 = tx1 - space0;
y0 = ty1 - lineSize + 1;
y1 = ty1;
tWidth = x1 - x0 + 1;
tHeight = y1 - y0 + 1;
if (0 == (tCode & 0x01)) { GUIDrawNixieTubeLine2(x0, y0, tWidth, tHeight, 3, color); }
else { GUIDrawNixieTubeLine2(x0, y0, tWidth, tHeight, 3, bcolor); }
tCode = tCode >> 1;
//绘制 4 号线
x0 = tx0;
y0 = ((ty0 + ty1) / 2) + space0;
x1 = tx0 + lineSize - 1;
y1 = ty1 - space0;
tWidth = x1 - x0 + 1;
tHeight = y1 - y0 + 1;
if (0 == (tCode & 0x01)) { GUIDrawNixieTubeLine2(x0, y0, tWidth, tHeight, 4, color); }
else { GUIDrawNixieTubeLine2(x0, y0, tWidth, tHeight, 4, bcolor); }
tCode = tCode >> 1;
//绘制 5 号线
x0 = tx0;
y0 = ty0 + space0;
x1 = tx0 + lineSize - 1;
y1 = ((ty0 + ty1) / 2) - space0;
tWidth = x1 - x0 + 1;
tHeight = y1 - y0 + 1;
if (0 == (tCode & 0x01)) { GUIDrawNixieTubeLine2(x0, y0, tWidth, tHeight, 5, color); }
else { GUIDrawNixieTubeLine2(x0, y0, tWidth, tHeight, 5, bcolor); }
tCode = tCode >> 1;
//绘制 6 号线
x0 = tx0 + space1;
x1 = tx1 - space1;
y0 = ((ty0 + ty1) / 2) - (lineSize / 2);
y1 = ((ty0 + ty1) / 2) + (lineSize / 2);
tWidth = x1 - x0 + 1;
tHeight = y1 - y0 + 1;
if (0 == (tCode & 0x01)) { GUIDrawNixieTubeLine2(x0, y0, tWidth, tHeight, 6, color); }
else { GUIDrawNixieTubeLine2(x0, y0, tWidth, tHeight, 6, bcolor); }
tCode = tCode >> 1;
}
测试代码
测试代码如下所示,这里做了一个简单的计时器,假定屏幕尺寸 800×480。
int main(void)
{
int min, sec;
//设置初始状态
min = 0;
sec = 0;
//初始化
InitLCD();
//刷纯黑背景
GUIFillColor(0, 0, 799, 479, GUI_COLOR_BLACK);
//绘制冒号
GUIFillColor(365, 200, 405, 240, GUI_COLOR_WHITE);
GUIFillColor(365, 300, 405, 340, GUI_COLOR_WHITE);
//主循环
while (1)
{
//显示当前时间
GUIDrawNixieTube(75 , 150, 100, 200, 25, 6, 13, (min / 10) + '0', GUI_COLOR_WHITE, GUI_COLOR_BLACK);
GUIDrawNixieTube(200, 150, 100, 200, 25, 6, 13, (min % 10) + '0', GUI_COLOR_WHITE, GUI_COLOR_BLACK);
GUIDrawNixieTube(475, 150, 100, 200, 25, 6, 13, (sec / 10) + '0', GUI_COLOR_WHITE, GUI_COLOR_BLACK);
GUIDrawNixieTube(600, 150, 100, 200, 25, 6, 13, (sec % 10) + '0', GUI_COLOR_WHITE, GUI_COLOR_BLACK);
//计数加一
sec = (sec + 1) % 60;
if (0 == sec)
{
min = (min + 1) % 60;
}
//延时 1s 钟
Sleep(1000);
}
return 0;
}
最终效果如下所示。这个数码管显示驱动可以轻松的移植到单片机上,在 LCD 或 OLED 显示数码管字符。
