首先,看一下LCD液晶屏幕的引腳資料。從圖中我們得知這是一個4com,44段的LCD。
以米字型數(shù)碼管為例。首先創(chuàng)建一個結(jié)構(gòu)體,這個結(jié)構(gòu)體描述每個段所對應(yīng)的COM,也就是給上圖表格建立數(shù)據(jù)模型。
typedef struct
{
uint32_t com[14]; //存儲每個段對應(yīng)的哪一位
uint32_t bit[14]; //14個段
} CHAR_TypeDef;
由上圖LCD的表格和數(shù)據(jù)模型,給這個結(jié)構(gòu)建立數(shù)組用于查詢。因?yàn)槊课粩?shù)碼管要14個數(shù)據(jù),7位米字形數(shù)碼共14*7=98個數(shù)據(jù)。
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
},
建立完這個核心表格后,查表即可。
查的時候是大循環(huán)7個數(shù)碼,小循環(huán)每個數(shù)碼14位。代碼如下所示。
for (index = 0; index < 7;index++) //大循環(huán),7個米字形數(shù)碼管
{
data = (int) *string;
bitfield = Nuvo_alphabet[data]; //段碼
for (i = 0; i < 14;i++) //每個米字形數(shù)碼管14個段
{
bit = NANO1XXDISPLAY.Text[index].bit[i];
com = NANO1XXDISPLAY.Text[index].com[i];
if (bitfield & (1 << i)) //重要,當(dāng)前位顯示則刷新
{
LCD_EnableSegment(com, bit);//和CPU有關(guān)
}
}
string++;
}
這樣就能完美顯示了。和LED數(shù)碼管不同,為了布線方便,LCD的段碼硬件連線不是連續(xù)的,只能查出段碼后再每一位查詢。
對于段碼表格Nuvo_alphabet就更簡單了,和LED數(shù)碼管一樣。
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 */
拿數(shù)字1來說,只有BC是顯示的,所以值是0x0006,既是0b0000 0000 0000 0110。
怎么樣,這樣的思路很好吧,表格的方式記錄LCD特征值可以很方便的移植和提高程序的效率。想當(dāng)年我是無數(shù)的IF實(shí)現(xiàn)的,太丟人了。
當(dāng)然,因?yàn)橹挥卸螢?時才刷新數(shù)據(jù)寄存器,所以,數(shù)據(jù)變化時,老數(shù)據(jù)1不會消失。我們在每次刷新之前,要清空全部數(shù)據(jù)寄存器。
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;
}