前日,在看官方的TG STK 的LCD的例程时,才发现程序写的似乎是有一些难懂。虽然知道他是将每个8字或则米字的Com和Segment抽出来,组成一个数组,该数组叫做const MCU_DISPLAY EFM_Display。
以其中的米字为例来说,他为米字的每个Segment定义了所属的Com,以及Segment的具体bit。因为TG STK上总共有7个米字,因此他定义了CHAR_TypeDef Text[7]这个数组,每个CHAR_TypeDef包含了14个COM的定义以及14个Segment的定义。对应了每个米字的14个段。
8字也是一样的原理来写的。
但是每个segment到底是怎么对应的,具体就需要通过核对LCD的真值表做这张表格了。一旦抽象完成,则后续的操作就会变得有规律了。因此后续用函数操作时也比较容易。
这里我们也可以换一种方式来操作LCD。通过查看TG 的Reference manual,我们可以发现,EFM32是将同一COM口上的Segment编到了同一个寄存器里的各个bit位。因此TG里面有8个寄存器,分别叫做LCD_SEGD0L ~ LCD_SEGD7L只要明确知道这个原理之后,剩下的就是怎么去操作这些寄存器了。
另外,我们也知道每个32bit的寄存器,都可以通过bitband来操作,因此,LCD的操作可以换一种思路,还是抽象,但是抽象出来的东西,用bitband来表示。
第一步:用bitband来表示LCD_SEGD0L ~ LCD_SEGD7L里面的所有bit的值。以LCD_SEGD0L为例:
#define COM0_S0 0x43140800
#define COM0_S1 0x43140804
//略
#define COM0_S22 0x43140858
#define COM0_S23 0x4314085C
第二步:根据LCD的真值表来抽象出一张表格.暂时将TG STK上的米字按照8字来定义。因为有7个米字。
const unsigned long LED_Segment[7][8] = {
{COM1_S1,COM1_S2,COM5_S2,COM7_S2,COM7_S1,COM3_S1,COM4_S1,COM4_S2},
{COM1_S3,COM1_S4,COM5_S4,COM7_S4,COM7_S3,COM3_S3,COM4_S3,COM4_S4},
{COM1_S5,COM1_S6,COM5_S6,COM7_S6,COM7_S5,COM3_S5,COM4_S5,COM4_S6},
{COM1_S7,COM1_S8,COM5_S8,COM7_S8,COM7_S7,COM3_S7,COM4_S7,COM4_S8},
{COM0_S9 ,COM1_S10, COM5_S10, COM7_S10, COM6_S9 ,COM2_S9 ,COM3_S9 ,COM4_S10},
{COM0_S11,COM1_S12,COM5_S12,COM7_S12,COM6_S11,COM2_S11,COM3_S11,COM4_S12},
{COM1_S13,COM1_S14,COM5_S14,COM7_S14,COM7_S13,COM3_S13,COM4_S13,COM4_S14},
};
第三步:定义8字显示的数组,或则米字显示的数组。以下是显示0~9,以及空白的定义.
需要根据LCD的针对8字或米字的定义来设计显示数组。
const char LCD_SEGMENT[11] = {0x3f,0x06,0xdb,0xcf,0xe6,0xed,0xfd,0x07,0xff,0xef,0x00};
第四步:写显示函数。
//Num表示在LCD那个8字上显示数据
//Data表示显示多少,范围为0~9,10代表空白
void Num_Show (unsigned char Num, unsigned char Data)
{
for(unsigned char i = 0; i < 8; i++)
{
unsigned long *Point;
Point = ((unsigned long *)LED_Segment[Num][i]);
if(LCD_SEGMENT[Data] & (0x01 << i))
{
*Point = 1;
}
else
{
*Point = 0;
}
}
}
以上就是一种操作LCD的思路了。这只是一个框架性的思路。
具体例程如下: