wangpeng 发表于 2022-1-7 16:28:42

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

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

原帖地址:【FM33LG0系列开发板测评】07.LCD & 段码显示软件实现框架 - 国产芯片交流 - 电子工程世界-论坛 (eeworld.com.cn)
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液晶显示屏;接口原理图如下所示:http://bbs.eeworld.com.cn/data/attachment/forum/202112/24/215806yevq33oqqq33jce0.png.thumb.jpg

但有一点需要注意的是,J14的COM0~COM7、SEG0~SEG12与MCU端口引脚的功能定义相一致,其余的则连接到其它的SEG端口引脚上了,具体的连接对照表如下图所示:http://bbs.eeworld.com.cn/data/attachment/forum/202112/24/215807otxf1gonmlnojoxi.png.thumb.jpg

2、液晶屏选择我们在网上选购了一块显示段数相对较多的液晶屏,带有4个COM端口和25个SEG端口,全显示效果如下所示:http://bbs.eeworld.com.cn/data/attachment/forum/202112/24/215807j0rylhj1y0jgjtyz.png.thumb.jpg
为了显示全部的内容,J14的SEG端口不够用了,正好我们将SPI1接口也扩展成SEG端口使用,这样正好满足SEG端口数要求,可以从第1小节的表格中看出接线线序。LCD的真值表如下图所示:http://bbs.eeworld.com.cn/data/attachment/forum/202112/24/215811pey78atzzsbbt8qs.png.thumb.jpg

3、实现功能通过FM33LG048自带的LCD液晶驱动模块,实现对LCD的驱动及显示,完成动态显示效果;结合自编写的段码显示软件实现框架,能够快速实现应用显示软件开发,进行快速产品迭代;这一软件框架不仅 适用于自带LCD液晶驱动模块的MCU,也适用于使用外部LCD液晶驱动芯片的形式,还适用于数码管的驱动显示。
4、硬件连接及显示效果http://bbs.eeworld.com.cn/data/attachment/forum/202112/24/215806s5a68a566t614a5o.jpg.thumb.jpg

5、实现代码5.1.定义段码显示常用的字符/* Private variables ---------------------------------------------------------*/
const DIGITRON_STRUCT DIGITRON_TABLE =
{
    {' ', {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 =
{
/*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 =
{
    {"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 = {"P1", "P2", "P3", "P5", "P6", "P7", "P8", "P9", "C1", "C2", "C3"};
const char DISPLAY_BAT_TABLE    = {"W1", "W2", "W3", "W4", "W5"};
const char DISPLAY_CSQ_TABLE    = {"L1", "L2", "L3", "L4"};
const char DISPLAY_UNIT_TABLE= {"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) == 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_InitTypeDefLCD_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、工程源码
页: [1]
查看完整版本: 【FM33LG0系列开发板测评】LCD & 段码显示软件实现框架