找回密码
 立即注册

只需一步,快速开始

搜索

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

0
回复
3883
查看
[复制链接]

166

主题

343

帖子

3076

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
3076
QQ
2022-1-7 16:28:42 显示全部楼层 |阅读模式
【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液晶显示屏;接口原理图如下所示:



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



2、液晶屏选择

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


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



3、实现功能

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


4、硬件连接及显示效果



5、实现代码

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

  1. /* Private variables ---------------------------------------------------------*/
  2. const DIGITRON_STRUCT DIGITRON_TABLE[38] =
  3. {
  4.     {' ', {0, 0, 0, 0, 0, 0, 0, 0}},
  5.     {'0', {1, 1, 1, 1, 1, 1, 0, 0}},
  6.     {'1', {0, 1, 1, 0, 0, 0, 0, 0}},
  7.     {'2', {1, 1, 0, 1, 1, 0, 1, 0}},
  8.     {'3', {1, 1, 1, 1, 0, 0, 1, 0}},
  9.     {'4', {0, 1, 1, 0, 0, 1, 1, 0}},
  10.     {'5', {1, 0, 1, 1, 0, 1, 1, 0}},
  11.     {'6', {1, 0, 1, 1, 1, 1, 1, 0}},
  12.     {'7', {1, 1, 1, 0, 0, 0, 0, 0}},
  13.     {'8', {1, 1, 1, 1, 1, 1, 1, 0}},
  14.     {'9', {1, 1, 1, 1, 0, 1, 1, 0}},
  15.     {'A', {1, 1, 1, 0, 1, 1, 1, 0}},
  16.     {'b', {0, 0, 1, 1, 1, 1, 1, 0}},
  17.     {'c', {0, 0, 0, 1, 1, 0, 1, 0}},
  18.     {'C', {1, 0, 0, 1, 1, 1, 0, 0}},
  19.     {'d', {0, 1, 1, 1, 1, 0, 1, 0}},
  20.     {'E', {1, 0, 0, 1, 1, 1, 1, 0}},
  21.     {'F', {1, 0, 0, 0, 1, 1, 1, 0}},
  22.     {'g', {1, 1, 1, 1, 0, 1, 1, 0}},
  23.     {'H', {0, 1, 1, 0, 1, 1, 1, 0}},
  24.     {'h', {0, 0, 1, 0, 1, 1, 1, 0}},
  25.     {'i', {0, 0, 1, 0, 0, 0, 0, 0}},
  26.     {'I', {0, 0, 0, 0, 1, 1, 0, 0}},
  27.     {'J', {0, 1, 1, 1, 1, 0, 0, 0}},
  28.     {'l', {0, 0, 0, 0, 1, 1, 0, 0}},
  29.     {'L', {0, 0, 0, 1, 1, 1, 0, 0}},
  30.     {'n', {0, 0, 1, 0, 1, 0, 1, 0}},
  31.     {'o', {0, 0, 1, 1, 1, 0, 1, 0}},
  32.     {'O', {1, 1, 1, 1, 1, 1, 0, 0}},
  33.     {'P', {1, 1, 0, 0, 1, 1, 1, 0}},
  34.     {'q', {1, 1, 1, 0, 0, 1, 1, 0}},
  35.     {'r', {0, 0, 0, 0, 1, 0, 1, 0}},
  36.     {'S', {1, 0, 1, 1, 0, 1, 1, 0}},
  37.     {'t', {0, 0, 0, 1, 1, 1, 1, 0}},
  38.     {'u', {0, 0, 1, 1, 1, 0, 0, 0}},
  39.     {'U', {0, 1, 1, 1, 1, 1, 0, 0}},
  40.     {'y', {0, 1, 1, 1, 0, 1, 1, 0}},
  41.     {'-', {0, 0, 0, 0, 0, 0, 1, 0}},
  42. };
复制代码

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

  1. /* Private variables ---------------------------------------------------------*/
  2. const char LCD_CS_TABLE[4][44][3] =
  3. {
  4. /*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*/
  5. /*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"},
  6. /*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"},
  7. /*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"},
  8. /*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"},
  9. };
复制代码

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

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


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

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

  1. /*******************************************************************************
  2. * @brief * @param      
  3. * @retval      
  4. * @attention *******************************************************************************/
  5. void LCD_SearchCS(const char *str, uint8_t *com, uint8_t *seg)
  6. {
  7.     for(uint8_t i = 0; i < 4; i++)          //扫描04个COM段
  8.     {
  9.         for(uint8_t j = 0; j < 44; j++)     //扫描44个SEG段
  10.         {
  11.             if(strcmp(str, LCD_CS_TABLE[j]) == 0)
  12.             {
  13.                 *com = i; *seg = j; return;
  14.             }
  15.         }
  16.     }

  17.     *com = 0xFF;
  18.     *seg = 0xFF;
  19. }
复制代码

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

  1. /*******************************************************************************
  2. * @brief      
  3. * @param      
  4. * @retval      
  5. * @attention   
  6. *******************************************************************************/
  7. void LCD_Init(void)
  8. {
  9.     FL_GPIO_InitTypeDef GPIO_InitStruct;
  10.     FL_LCD_InitTypeDef  LCD_InitStruct;

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

  12.     FL_GPIO_StructInit(&GPIO_InitStruct);
  13.     GPIO_InitStruct.pin        = FL_GPIO_PIN_0 | FL_GPIO_PIN_1 | FL_GPIO_PIN_2 |
  14.                                  FL_GPIO_PIN_3 | FL_GPIO_PIN_8 | FL_GPIO_PIN_9 |
  15.                                  FL_GPIO_PIN_10;
  16.     GPIO_InitStruct.mode       = FL_GPIO_MODE_ANALOG;
  17.     GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
  18.     FL_GPIO_Init(GPIOA, &GPIO_InitStruct);


  19.     FL_GPIO_StructInit(&GPIO_InitStruct);
  20.     GPIO_InitStruct.pin        = FL_GPIO_PIN_4  | FL_GPIO_PIN_5  | FL_GPIO_PIN_6  |
  21.                                  FL_GPIO_PIN_7  | FL_GPIO_PIN_8  | FL_GPIO_PIN_9  |
  22.                                  FL_GPIO_PIN_10 | FL_GPIO_PIN_11 | FL_GPIO_PIN_13 |
  23.                                  FL_GPIO_PIN_14;
  24.     GPIO_InitStruct.mode       = FL_GPIO_MODE_ANALOG;
  25.     GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
  26.     FL_GPIO_Init(GPIOB, &GPIO_InitStruct);


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


  32.     FL_GPIO_StructInit(&GPIO_InitStruct);
  33.     GPIO_InitStruct.pin        = FL_GPIO_PIN_2 | FL_GPIO_PIN_3 | FL_GPIO_PIN_4 |
  34.                                  FL_GPIO_PIN_5;
  35.     GPIO_InitStruct.mode       = FL_GPIO_MODE_ANALOG;
  36.     GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
  37.     FL_GPIO_Init(GPIOD, &GPIO_InitStruct);


  38.     FL_GPIO_StructInit(&GPIO_InitStruct);
  39.     GPIO_InitStruct.pin        = FL_GPIO_PIN_0 | FL_GPIO_PIN_1 | FL_GPIO_PIN_2 |
  40.                                  FL_GPIO_PIN_3 | FL_GPIO_PIN_5;
  41.     GPIO_InitStruct.mode       = FL_GPIO_MODE_ANALOG;
  42.     GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
  43.     FL_GPIO_Init(GPIOE, &GPIO_InitStruct);


  44.     FL_LCD_StructInit(&LCD_InitStruct);
  45.     LCD_InitStruct.biasCurrent = FL_LCD_BIAS_CURRENT_HIGH;
  46.     LCD_InitStruct.biasMode    = FL_LCD_BIAS_MODE_3BIAS;
  47.     LCD_InitStruct.biasVoltage = FL_LCD_BIAS_VOLTAGE_LEVEL7;
  48.     LCD_InitStruct.COMxNum     = FL_LCD_COM_NUM_4COM;
  49.     LCD_InitStruct.waveform    = FL_LCD_WAVEFORM_TYPEA;
  50.     LCD_InitStruct.displayFreq = 64;
  51.     LCD_InitStruct.mode        = FL_LCD_DRIVER_MODE_INNER_RESISTER;
  52.     FL_LCD_Init(LCD, &LCD_InitStruct);


  53.     FL_LCD_EnableCOMEN(LCD, FL_LCD_COMEN_COM0);
  54.     FL_LCD_EnableCOMEN(LCD, FL_LCD_COMEN_COM1);
  55.     FL_LCD_EnableCOMEN(LCD, FL_LCD_COMEN_COM2);
  56.     FL_LCD_EnableCOMEN(LCD, FL_LCD_COMEN_COM3);

  57.     FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG0);
  58.     FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG1);
  59.     FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG2);
  60.     FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG3);
  61.     FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG4);
  62.     FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG5);
  63.     FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG6);
  64.     FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG7);
  65.     FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG8);
  66.     FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG9);
  67.     FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG10);
  68.     FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG11);
  69.     FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG12);

  70.     FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG24);
  71.     FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG25);
  72.     FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG26);
  73.     FL_LCD_EnableSEGEN0(LCD, FL_LCD_SEGEN0_SEG27);

  74.     FL_LCD_EnableSEGEN1(LCD, FL_LCD_SEGEN1_SEG4);   //SEG36
  75.     FL_LCD_EnableSEGEN1(LCD, FL_LCD_SEGEN1_SEG5);   //SEG37
  76.     FL_LCD_EnableSEGEN1(LCD, FL_LCD_SEGEN1_SEG6);   //SEG38
  77.     FL_LCD_EnableSEGEN1(LCD, FL_LCD_SEGEN1_SEG7);   //SEG39
  78.     FL_LCD_EnableSEGEN1(LCD, FL_LCD_SEGEN1_SEG8);   //SEG40
  79.     FL_LCD_EnableSEGEN1(LCD, FL_LCD_SEGEN1_SEG9);   //SEG41
  80.     FL_LCD_EnableSEGEN1(LCD, FL_LCD_SEGEN1_SEG10);  //SEG42
  81.     FL_LCD_EnableSEGEN1(LCD, FL_LCD_SEGEN1_SEG11);  //SEG43

  82.     FL_LCD_Enable(LCD);

  83.     LCD_DisplayRefresh();

  84.     TASK_Append(TASK_ID_LCD, LCD_DisplayHandler, 100);
  85. }
复制代码

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

  1. /*******************************************************************************
  2. * @brief      
  3. * @param      
  4. * @retval      
  5. * @attention   
  6. *******************************************************************************/
  7. void LCD_DisplayHandler(void)
  8. {
  9.     static uint32_t DisplayTick = 0;
  10.     static uint16_t BAT_Index = 0, CSQ_Index = 0, Unit_Index = 0;
  11.     static uint16_t COL_State = 0;

  12.     LCD_DisplayCount();             //100ms

  13.     if((DisplayTick % 2) == 0)      //200ms
  14.     {
  15.         switch(BAT_Index++ % 4)
  16.         {
  17.             case 0 : LCD_DisplayBAT(0x0001); break;
  18.             case 1 : LCD_DisplayBAT(0x0001 | 0x0002); break;
  19.             case 2 : LCD_DisplayBAT(0x0001 | 0x0002 | 0x0004); break;
  20.             case 3 : LCD_DisplayBAT(0x0001 | 0x0002 | 0x0004 | 0x0008); break;
  21.             default: break;
  22.         }

  23.         switch(CSQ_Index++ % 4)
  24.         {
  25.             case 0 : LCD_DisplayCSQ(0x0001); break;
  26.             case 1 : LCD_DisplayCSQ(0x0001 | 0x0002); break;
  27.             case 2 : LCD_DisplayCSQ(0x0001 | 0x0002 | 0x0004); break;
  28.             case 3 : LCD_DisplayCSQ(0x0001 | 0x0002 | 0x0004 | 0x0008); break;
  29.             default: break;
  30.         }

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


  33.     if((DisplayTick % 5) == 0)      //500ms
  34.     {
  35.         if(COL_State == 0)
  36.         {
  37.             COL_State = 1; LCD_DisplayPoint(POINT_COL2 | POINT_COL3);
  38.         }
  39.         else
  40.         {
  41.             COL_State = 0; LCD_DisplayPoint(0x0000);
  42.         }
  43.     }

  44.     if((DisplayTick % 10) == 0)     //1000ms
  45.     {
  46.         LCD_DisplayClock();
  47.     }

  48.     DisplayTick += 1;
  49.     DisplayTick %= 10000;
  50. }
复制代码

6、运行演示

查看原帖

7、工程源码

Project_LCD.zip (386.07 KB, 下载次数: 203)

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

返回顶部