首先,看一下LCD液晶屏幕的引脚资料。从图中我们得知这是一个4com,44段的LCD。
以米字型数码管为例。首先创建一个结构体,这个结构体描述每个段所对应的COM,也就是给上图表格建立数据模型。
typedef struct
{
uint32_t com[14]; //存储每个段对应的哪一位
uint32_t bit[14]; //14个段
} CHAR_TypeDef;
由上图LCD的表格和数据模型,给这个结构建立数组用于查询。因为每位数码管要14个数据,7位米字形数码共14*7=98个数据。
const CHAR_TypeDef NANO1XXDISPLAY = {
//7个大字符
{ /* 1 */
/* A B C D */
.com[0] = 3, .com[1] = 2, .com[2] = 1, .com[3] = 0,
.bit[0] = 0, .bit[1] = 0, .bit[2] = 0, .bit[3] = 0,
/* E F G H */
.com[4] = 1, .com[5] = 2, .com[6] = 2, .com[7] = 3,
.bit[4] = 38, .bit[5] = 38, .bit[6] = 39, .bit[7] = 39,
/* J K M N */
.com[8] = 3, .com[9] = 2, .com[10] = 1, .com[11] = 0,
.bit[8] = 1, .bit[9] = 1, .bit[10] = 1, .bit[11] = 1,
/* P Q */
.com[12] = 0, .com[13] = 1,
.bit[12] = 39, .bit[13] = 39
},
{ /* 2 */
.com[0] = 3, .com[1] = 2, .com[2] = 1, .com[3] = 0,
.bit[0] = 4, .bit[1] = 4, .bit[2] = 4, .bit[3] = 4,
.com[4] = 1, .com[5] = 2, .com[6] = 2, .com[7] = 3,
.bit[4] = 2, .bit[5] = 2, .bit[6] = 3, .bit[7] = 3,
.com[8] = 3, .com[9] = 2, .com[10] = 1, .com[11] = 0,
.bit[8] = 5, .bit[9] = 5, .bit[10] = 5, .bit[11] = 5,
.com[12] = 0, .com[13] = 1,
.bit[12] = 3, .bit[13] = 3
},
建立完这个核心表格后,查表即可。
查的时候是大循环7个数码,小循环每个数码14位。代码如下所示。
for (index = 0; index < 7;index++) //大循环,7个米字形数码管
{
data = (int) *string;
bitfield = Nuvo_alphabet[data]; //段码
for (i = 0; i < 14;i++) //每个米字形数码管14个段
{
bit = NANO1XXDISPLAY.Text[index].bit[i];
com = NANO1XXDISPLAY.Text[index].com[i];
if (bitfield & (1 << i)) //重要,当前位显示则刷新
{
LCD_EnableSegment(com, bit);//和CPU有关
}
}
string++;
}
这样就能完美显示了。和LED数码管不同,为了布线方便,LCD的段码硬件连线不是连续的,只能查出段码后再每一位查询。
对于段码表格Nuvo_alphabet就更简单了,和LED数码管一样。
const uint16_t Nuvo_alphabet[] = {
0x0000, /* space */
0x1100, /* ! */
0x0280, /* " */
0x0000, /* # */
0x0000, /* $ */
0x0000, /* % */
0x0000, /* & */
0x0000, /* ? */
0x0039, /* ( */
0x000f, /* ) */
0x3fc0, /* * */
0x1540, /* + */
0x0000, /* , */
0x0440, /* - */
0x8000, /* . */
0x2200, /* / */
0x003f, /* 0 */
0x0006, /* 1 */
拿数字1来说,只有BC是显示的,所以值是0x0006,既是0b0000 0000 0000 0110。
怎么样,这样的思路很好吧,表格的方式记录LCD特征值可以很方便的移植和提高程序的效率。想当年我是无数的IF实现的,太丢人了。
当然,因为只有段为1时才刷新数据寄存器,所以,数据变化时,老数据1不会消失。我们在每次刷新之前,要清空全部数据寄存器。
void LCD_AlphaNumberOff(void)
{
LCD->MEM_0 &= ~0x0f0f0f0f;
LCD->MEM_1 &= ~0x0f0f0f0f;
LCD->MEM_2 &= ~0x0f0f0f0f;
LCD->MEM_3 &= ~0x0f0f0f0f;
LCD->MEM_4 &= ~0x0f0f0f0f;
LCD->MEM_5 &= ~0x0f070f0f;
LCD->MEM_6 &= ~0x00000f0f;
LCD->MEM_9 &= ~0x0f060000;
return;
}