[MCU] 【FM33LG0系列开发板测评】07.LCD & 段码显示软件实现框架

xld0932   2021-12-24 22:10 楼主

1、简介

FM33LG048带有一个用于驱动段码式液晶屏的LCD显示驱动模块,它能够最大支持8个COM,支持8*40、6*42、4*44的显示段数,16级的可调灰度,可选择1/3Bias或者1/4Bias;64Hz的典型帧刷新频率。

FM33LG0XX DEMO V1.1开发板上J14将部分LCD的COM端口和SEG端口以排针的形式引出,便于连接外扩段码式LCD液晶显示屏;接口原理图如下所示:

3.png

 

但有一点需要注意的是,J14的COM0~COM7、SEG0~SEG12与MCU端口引脚的功能定义相一致,其余的则连接到其它的SEG端口引脚上了,具体的连接对照表如下图所示:

4.png

 

2、液晶屏选择

我们在网上选购了一块显示段数相对较多的液晶屏,带有4个COM端口和25个SEG端口,全显示效果如下所示:

5.png

为了显示全部的内容,J14的SEG端口不够用了,正好我们将SPI1接口也扩展成SEG端口使用,这样正好满足SEG端口数要求,可以从第1小节的表格中看出接线线序。LCD的真值表如下图所示:

6.png

 

3、实现功能

通过FM33LG048自带的LCD液晶驱动模块,实现对LCD的驱动及显示,完成动态显示效果;结合自编写的段码显示软件实现框架,能够快速实现应用显示软件开发,进行快速产品迭代;这一软件框架不仅 适用于自带LCD液晶驱动模块的MCU,也适用于使用外部LCD液晶驱动芯片的形式,还适用于数码管的驱动显示。

 

4、硬件连接及显示效果

1.jpg

 

5、实现代码

5.1.定义段码显示常用的字符

/* Private variables ---------------------------------------------------------*/
const DIGITRON_STRUCT DIGITRON_TABLE[38] = 
{
    {' ', {0, 0, 0, 0, 0, 0, 0, 0}},
    {'0', {1, 1, 1, 1, 1, 1, 0, 0}},
    {'1', {0, 1, 1, 0, 0, 0, 0, 0}},
    {'2', {1, 1, 0, 1, 1, 0, 1, 0}},
    {'3', {1, 1, 1, 1, 0, 0, 1, 0}},
    {'4', {0, 1, 1, 0, 0, 1, 1, 0}},
    {'5', {1, 0, 1, 1, 0, 1, 1, 0}},
    {'6', {1, 0, 1, 1, 1, 1, 1, 0}},
    {'7', {1, 1, 1, 0, 0, 0, 0, 0}},
    {'8', {1, 1, 1, 1, 1, 1, 1, 0}},
    {'9', {1, 1, 1, 1, 0, 1, 1, 0}},
    {'A', {1, 1, 1, 0, 1, 1, 1, 0}},
    {'b', {0, 0, 1, 1, 1, 1, 1, 0}},
    {'c', {0, 0, 0, 1, 1, 0, 1, 0}},
    {'C', {1, 0, 0, 1, 1, 1, 0, 0}},
    {'d', {0, 1, 1, 1, 1, 0, 1, 0}},
    {'E', {1, 0, 0, 1, 1, 1, 1, 0}},
    {'F', {1, 0, 0, 0, 1, 1, 1, 0}},
    {'g', {1, 1, 1, 1, 0, 1, 1, 0}},
    {'H', {0, 1, 1, 0, 1, 1, 1, 0}},
    {'h', {0, 0, 1, 0, 1, 1, 1, 0}},
    {'i', {0, 0, 1, 0, 0, 0, 0, 0}},
    {'I', {0, 0, 0, 0, 1, 1, 0, 0}},
    {'J', {0, 1, 1, 1, 1, 0, 0, 0}},
    {'l', {0, 0, 0, 0, 1, 1, 0, 0}},
    {'L', {0, 0, 0, 1, 1, 1, 0, 0}},
    {'n', {0, 0, 1, 0, 1, 0, 1, 0}},
    {'o', {0, 0, 1, 1, 1, 0, 1, 0}},
    {'O', {1, 1, 1, 1, 1, 1, 0, 0}},
    {'P', {1, 1, 0, 0, 1, 1, 1, 0}},
    {'q', {1, 1, 1, 0, 0, 1, 1, 0}},
    {'r', {0, 0, 0, 0, 1, 0, 1, 0}},
    {'S', {1, 0, 1, 1, 0, 1, 1, 0}},
    {'t', {0, 0, 0, 1, 1, 1, 1, 0}},
    {'u', {0, 0, 1, 1, 1, 0, 0, 0}},
    {'U', {0, 1, 1, 1, 1, 1, 0, 0}},
    {'y', {0, 1, 1, 1, 0, 1, 1, 0}},
    {'-', {0, 0, 0, 0, 0, 0, 1, 0}},
};

 

5.2.根据LCD段码真值表及硬件连线线序,定义LCD段码查询表

/* Private variables ---------------------------------------------------------*/
const char LCD_CS_TABLE[4][44][3] = 
{
/*SEGX    00   01   02   03   04   05   06   07   08   09   10   11   12   13   14   15   16   17   18   19   20   21   22   23   24   25   26   27   28   29   30   31   32   33   34   35   36   37   38   39   40   41   42   43*/
/*COM0*/{"1D","P1","2D","P2","3D","P3","4D","C1","C2","W5","L1","5F","5A","  ","  ","  ","  ","  ","  ","  ","  ","  ","  ","  ","9F","9A","AF","AA","  ","  ","  ","  ","  ","  ","  ","  ","6F","6A","7F","7A","S4","S5","8F","8A"},
/*COM1*/{"1E","1C","2E","2C","3E","3C","4E","4C","C3","W4","L2","5G","5B","  ","  ","  ","  ","  ","  ","  ","  ","  ","  ","  ","9G","9B","AG","AB","  ","  ","  ","  ","  ","  ","  ","  ","6G","6B","7G","7B","S3","S6","8G","8B"},
/*COM2*/{"1G","1B","2G","2B","3G","3B","4G","4B","T1","W3","L3","5E","5C","  ","  ","  ","  ","  ","  ","  ","  ","  ","  ","  ","9E","9C","AE","AC","  ","  ","  ","  ","  ","  ","  ","  ","6E","6C","7E","7C","S2","S7","8E","8C"},
/*COM3*/{"1F","1A","2F","2A","3F","3A","4F","4A","W1","W2","L4","5D","P5","  ","  ","  ","  ","  ","  ","  ","  ","  ","  ","  ","9D","P9","AD","S9","  ","  ","  ","  ","  ","  ","  ","  ","6D","P6","7D","P7","S1","S8","8D","P8"},
};

 

5.3.根据显示内容进行划分、分组,定义显示功能区域数组

/* Private variables ---------------------------------------------------------*/
const char DISPLAY_DIGIT_TABLE[10][7][3] = 
{
    {"1A", "1B", "1C", "1D", "1E", "1F", "1G"},
    {"2A", "2B", "2C", "2D", "2E", "2F", "2G"},
    {"3A", "3B", "3C", "3D", "3E", "3F", "3G"},
    {"4A", "4B", "4C", "4D", "4E", "4F", "4G"},
    {"5A", "5B", "5C", "5D", "5E", "5F", "5G"},
    {"6A", "6B", "6C", "6D", "6E", "6F", "6G"},
    {"7A", "7B", "7C", "7D", "7E", "7F", "7G"},
    {"8A", "8B", "8C", "8D", "8E", "8F", "8G"},
    {"9A", "9B", "9C", "9D", "9E", "9F", "9G"},
    {"AA", "AB", "AC", "AD", "AE", "AF", "AG"},
};


const char DISPLAY_POINT_TABLE[11][3] = {"P1", "P2", "P3", "P5", "P6", "P7", "P8", "P9", "C1", "C2", "C3"};
const char DISPLAY_BAT_TABLE[5][3]    = {"W1", "W2", "W3", "W4", "W5"};
const char DISPLAY_CSQ_TABLE[4][3]    = {"L1", "L2", "L3", "L4"};
const char DISPLAY_UNIT_TABLE[10][3]  = {"S1", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9", "T1"};

 

5.4.根据真值表内容查询需要操作的COM和SEG位置

/*******************************************************************************
 * @brief * @param       
 * @retval      
 * @attention *******************************************************************************/
void LCD_SearchCS(const char *str, uint8_t *com, uint8_t *seg)
{
    for(uint8_t i = 0; i < 4; i++)          //扫描04个COM段
    {
        for(uint8_t j = 0; j < 44; j++)     //扫描44个SEG段
        {
            if(strcmp(str, LCD_CS_TABLE[j]) == 0)
            {
                *com = i; *seg = j; return;
            }
        }
    }

    *com = 0xFF;
    *seg = 0xFF;
}

 

5.5.根据硬件连线,对LCD液晶驱动模块初始化


/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   
*******************************************************************************/
void LCD_Init(void)
{
    FL_GPIO_InitTypeDef GPIO_InitStruct;
    FL_LCD_InitTypeDef  LCD_InitStruct;

    memset(LCD_DisplayBuffer, 0, sizeof(LCD_DisplayBuffer));

    FL_GPIO_StructInit(&GPIO_InitStruct);
    GPIO_InitStruct.pin        = FL_GPIO_PIN_0 | FL_GPIO_PIN_1 | FL_GPIO_PIN_2 |
                                 FL_GPIO_PIN_3 | FL_GPIO_PIN_8 | FL_GPIO_PIN_9 |
                                 FL_GPIO_PIN_10;
    GPIO_InitStruct.mode       = FL_GPIO_MODE_ANALOG;
    GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
    FL_GPIO_Init(GPIOA, &GPIO_InitStruct);


    FL_GPIO_StructInit(&GPIO_InitStruct);
    GPIO_InitStruct.pin        = FL_GPIO_PIN_4  | FL_GPIO_PIN_5  | FL_GPIO_PIN_6  |
                                 FL_GPIO_PIN_7  | FL_GPIO_PIN_8  | FL_GPIO_PIN_9  |
                                 FL_GPIO_PIN_10 | FL_GPIO_PIN_11 | FL_GPIO_PIN_13 |
                                 FL_GPIO_PIN_14;
    GPIO_InitStruct.mode       = FL_GPIO_MODE_ANALOG;
    GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
    FL_GPIO_Init(GPIOB, &GPIO_InitStruct);


    FL_GPIO_StructInit(&GPIO_InitStruct);
    GPIO_InitStruct.pin        = FL_GPIO_PIN_13 | FL_GPIO_PIN_14 | FL_GPIO_PIN_15;
    GPIO_InitStruct.mode       = FL_GPIO_MODE_ANALOG;
    GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
    FL_GPIO_Init(GPIOC, &GPIO_InitStruct);


    FL_GPIO_StructInit(&GPIO_InitStruct);
    GPIO_InitStruct.pin        = FL_GPIO_PIN_2 | FL_GPIO_PIN_3 | FL_GPIO_PIN_4 |
                                 FL_GPIO_PIN_5;
    GPIO_InitStruct.mode       = FL_GPIO_MODE_ANALOG;
    GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
    FL_GPIO_Init(GPIOD, &GPIO_InitStruct);


    FL_GPIO_StructInit(&GPIO_InitStruct);
    GPIO_InitStruct.pin        = FL_GPIO_PIN_0 | FL_GPIO_PIN_1 | FL_GPIO_PIN_2 |
                                 FL_GPIO_PIN_3 | FL_GPIO_PIN_5;
    GPIO_InitStruct.mode       = FL_GPIO_MODE_ANALOG;
    GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
    FL_GPIO_Init(GPIOE, &GPIO_InitStruct);


    FL_LCD_StructInit(&LCD_InitStruct);
    LCD_InitStruct.biasCurrent = FL_LCD_BIAS_CURRENT_HIGH;
    LCD_InitStruct.biasMode    = FL_LCD_BIAS_MODE_3BIAS;
    LCD_InitStruct.biasVoltage = FL_LCD_BIAS_VOLTAGE_LEVEL7;
    LCD_InitStruct.COMxNum     = FL_LCD_COM_NUM_4COM;
    LCD_InitStruct.waveform    = FL_LCD_WAVEFORM_TYPEA;
    LCD_InitStruct.displayFreq = 64;
    LCD_InitStruct.mode        = FL_LCD_DRIVER_MODE_INNER_RESISTER;
    FL_LCD_Init(LCD, &LCD_InitStruct);


    FL_LCD_EnableCOMEN(LCD, FL_LCD_COMEN_COM0);
    FL_LCD_EnableCOMEN(LCD, FL_LCD_COMEN_COM1);
    FL_LCD_EnableCOMEN(LCD, FL_LCD_COMEN_COM2);
    FL_LCD_EnableCOMEN(LCD, FL_LCD_COMEN_COM3);

    FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG0);
    FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG1);
    FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG2);
    FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG3);
    FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG4);
    FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG5);
    FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG6);
    FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG7);
    FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG8);
    FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG9);
    FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG10);
    FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG11);
    FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG12);

    FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG24);
    FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG25);
    FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG26);
    FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG27);

    FL_LCD_EnableSEGEN1(LCD, FL_LCD_SEGEN1_SEG4);   //SEG36
    FL_LCD_EnableSEGEN1(LCD, FL_LCD_SEGEN1_SEG5);   //SEG37
    FL_LCD_EnableSEGEN1(LCD, FL_LCD_SEGEN1_SEG6);   //SEG38
    FL_LCD_EnableSEGEN1(LCD, FL_LCD_SEGEN1_SEG7);   //SEG39
    FL_LCD_EnableSEGEN1(LCD, FL_LCD_SEGEN1_SEG8);   //SEG40
    FL_LCD_EnableSEGEN1(LCD, FL_LCD_SEGEN1_SEG9);   //SEG41
    FL_LCD_EnableSEGEN1(LCD, FL_LCD_SEGEN1_SEG10);  //SEG42
    FL_LCD_EnableSEGEN1(LCD, FL_LCD_SEGEN1_SEG11);  //SEG43

    FL_LCD_Enable(LCD);

    LCD_DisplayRefresh();

    TASK_Append(TASK_ID_LCD, LCD_DisplayHandler, 100);
}

 

5.6.主要实现功能部分源码,具体的可以下载附件中的源码工程进行阅读


/*******************************************************************************
 * @brief       
 * @param       
 * @retval      
 * @attention   
*******************************************************************************/
void LCD_DisplayHandler(void)
{
    static uint32_t DisplayTick = 0;
    static uint16_t BAT_Index = 0, CSQ_Index = 0, Unit_Index = 0;
    static uint16_t COL_State = 0;

    LCD_DisplayCount();             //100ms

    if((DisplayTick % 2) == 0)      //200ms
    {
        switch(BAT_Index++ % 4)
        {
            case 0 : LCD_DisplayBAT(0x0001); break;
            case 1 : LCD_DisplayBAT(0x0001 | 0x0002); break;
            case 2 : LCD_DisplayBAT(0x0001 | 0x0002 | 0x0004); break;
            case 3 : LCD_DisplayBAT(0x0001 | 0x0002 | 0x0004 | 0x0008); break;
            default: break;
        }

        switch(CSQ_Index++ % 4)
        {
            case 0 : LCD_DisplayCSQ(0x0001); break;
            case 1 : LCD_DisplayCSQ(0x0001 | 0x0002); break;
            case 2 : LCD_DisplayCSQ(0x0001 | 0x0002 | 0x0004); break;
            case 3 : LCD_DisplayCSQ(0x0001 | 0x0002 | 0x0004 | 0x0008); break;
            default: break;
        }

        LCD_DisplayUnit(0x0001 << (Unit_Index++ % 10));
    }


    if((DisplayTick % 5) == 0)      //500ms
    {
        if(COL_State == 0)
        {
            COL_State = 1; LCD_DisplayPoint(POINT_COL2 | POINT_COL3);
        }
        else
        {
            COL_State = 0; LCD_DisplayPoint(0x0000);
        }
    }

    if((DisplayTick % 10) == 0)     //1000ms
    {
        LCD_DisplayClock();
    }

    DisplayTick += 1;
    DisplayTick %= 10000;
}

 

6、运行演示


 

 

7、工程源码

Project_LCD.zip (386.07 KB)
(下载次数: 65, 2021-12-24 22:01 上传)

GDC0689TP-11.pdf (337.42 KB)
(下载次数: 47, 2021-12-24 22:01 上传)

We are a team and we work as a team !

回复评论 (8)

用心了,测评很认真!

点赞  2021-12-25 08:11
引用: lugl4313820 发表于 2021-12-25 08:11 用心了,测评很认真!

谢谢

点赞  2021-12-25 08:24

请问下LCD_DisplayBuffer缓存buff设置为10是什么原因,我这边有点不太理解,希望大佬解决下疑惑,谢谢!

  • image.png
点赞  2022-12-16 17:10
引用: fiee 发表于 2022-12-16 17:10 请问下LCD_DisplayBuffer缓存buff设置为10是什么原因,我这边有点不太理解,希望大佬解决下疑惑,谢谢!

image-20221223171510-1.png  

We are a team and we work as a team !
点赞 (1) 2022-12-23 17:15

麻烦问一下,定义的数组维数为啥用3维的?谢谢!

点赞 (1) 2023-4-19 08:59
引用: 无敌的小狮子 发表于 2023-4-19 08:59 麻烦问一下,定义的数组维数为啥用3维的?谢谢!

你可以把它看成一个二维数组,只是数组中的每一个元素是字符串,所以就需要3维数组来字义了哈……

We are a team and we work as a team !
点赞  2023-4-19 14:05
引用: xld0932 发表于 2023-4-19 14:05 你可以把它看成一个二维数组,只是数组中的每一个元素是字符串,所以就需要3维数组来字义了哈…&he ...

谢谢!

点赞  2023-4-27 11:35

复旦微代理商

点赞  2024-7-19 15:31
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复