谷动谷力

 找回密码
 立即注册
查看: 2133|回复: 0
打印 上一主题 下一主题
收起左侧

灵动微课堂| 使用MM32L0130 SLCD驱动LCD显示

[复制链接]
跳转到指定楼层
楼主
发表于 2022-10-20 16:49:48 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 sunsili 于 2024-1-12 20:47 编辑

【灵动微课堂】使用MM32L0130 SLCD驱动LCD显示


灵动股份推出的MM32L0130系列MCU具有片上SLCD液晶显示控制器,SLCD 驱动器是用于单色无源液晶显示器(SLCD)的数字驱动器,具有多达 8 个公共端和多达 63 个分段端, SLCD 引脚最多为 64 个,因此最多可驱动 240(60x4)或 448(56x8)个段码。驱动段码的最终数量由产品规格书中设备引脚的数目决定。

1SLCD介绍

1.1  SLCD功能框图

SLCD 驱动模块包括以下几个基本的子模块,如下图所示。
显示数据寄存器
SLCD 输出驱动引脚
时钟产生单元,包括时钟预分频器、帧时钟分频器、电荷泵时钟分频器和闪烁时钟分频器
闪烁控制器
内置升压电荷泵和偏置电压生成单元
时序控制和波形发生器
1.2  SLCD主要特征

显示帧率灵活控制
兼容 APB 接口
支持静态、 1/2、 1/3、 1/4、 1/6 和 1/8 占空比
支持 1/2、 1/3 和 1/4 偏置电压设置
为了存储显示数据,内置了 16*32bit 显示数据寄存器
通过软件来调整 SLCD 输出电压,来调节对比度
外围电路简单,不需要模拟器件支持
1)内嵌电容升压器来得到比电源电压更高而且不受其影响的 SLCD 驱动电压。升压器产生的 SLCD驱动电压范围可调,可以匹配支持 3V 或者 5V 的 LCD 屏幕
2)SLCD 驱动电源可以通过软件来选择内部电源或外部电源。
3)可以选择使用内嵌电容分压器对 SLCD 驱动电压进行分压,得到驱动电压的中间值(VLCDrail1,VLCDrail2, VLCDrail3, VLCDrail4)
两种调整显示对比度的方法
1)当采用内部升压器来提供 VLCD 电源时,可以通过软件调节 VLCD 输出电压
2)其它情况下可以在每帧显示之间插入死区时间
支持以下低功耗模式:低功耗运行模式,睡眠模式,低功耗睡眠模式,停止模式,深度停止模式,待机模式;在不需要显示的时候,可以完全关闭 SLCD 驱动以达到降低功耗的目的
支持相位反转模式,降低功耗和 EMI
每一帧显示开始的时候,通过中断信号与软件同步,更新显示数据
闪烁功能
1)可以从所有段码中任意选择 1 到 8 个段码闪烁显示,也可以闪烁显示全部段码
2)在静态、 1/2、 1/3、 1/4 占空比模式下可以闪烁显示任意段码
3)软件选择闪烁频率,支持闪烁频率 0.5Hz, 1Hz, 2Hz 或 4Hz
灵活的引脚复用功能,可以配置任意 LCD 驱动引脚成为 COM 或者 SEG 功能;SLCD 的驱动引脚在没有被配置成 SLCD 功能的时候,可以作为 GPIO 引脚来使用
SLCD 驱动电平(VLCDrail1, VLCDrail2, VLCDrail3, VLCDrail4)的去耦合功能
支持低功耗驱动波形
支持 DMA 传输
支持中断

2功能概述

2.1  显示数据寄存器

为了存储显示数据, SLCD 驱动模块内置了 16 个 32 比特显示数据寄存器。显示数据寄存器中的比特位与 LCD 显示屏上的段码一一对应, 如果要点亮 LCD 显示屏上的某个段码, 则需要把显示数据寄存器中的相对应的比特写为‘1’;反之如果要熄灭某个段码, 则需要把对应的比特写为‘0’, 如下图所示。


在 static, 1/2, 1/3 和1/4 duty模式下,显示数据寄存器被划分为主显示数据寄存器片区(SLCD_DR[7:0])和辅助显示数据寄存器片区( SLCD_DR[15:8]);在 1/6 和 1/8 duty 模式下,显示数据寄存器(SLCD_DR[15:0])全部作为主显示数据寄存器片区使用,没有辅助显示数据寄存器片区的分划。显示数据寄存器的具体结构和详细的片区划分情况见下图:

2.2  主/辅助显示数据寄存器

在 static,1/2,1/3和1/4 duty 模式下,可以通过 SLCD 帧控制寄存器(SLCD_FCR)中的DRSEL比特选择控制将主显示数据寄存器片区(SLCD_DR[7:0])或者辅助显示数据寄存器片区(SLCD_DR[15:8])的数据显示到 LCD 屏幕上,如果DRSEL为‘0’, 显示主显示数据寄存器片区的数据;如果 DRSEL 为‘1’,显示辅助显示数据寄存器片区的数据。SLCD 状态寄存器(SLCD_SR)中的 DRSS 比特可以指示出显示数据当前使用的显示数据寄存器片区, 如果当前使用的是主显示数据寄存器片区的数据, 则 DRSS 比特为‘0’;如果当前使用的是辅助显示数据寄存器片区的数据,则 DRSS 比特为‘1’。将 SLCD 帧控制寄存器(SLCD_FCR)中的 DRLC 比特置‘1’可以清除主显示数据寄存器片区的数据;将 DRHC 比特置‘1’可以清除辅助显示数据寄存器片区的数据。

2.3  COM 和 SEG 引脚配置

SLCD 模块提供公共端(COM)引脚和段(SEG)引脚的驱动。

2.4  SLCD 引脚配置

SLCD 的 SEG 和 COM 引脚是同通用功能 I/O 复用的。在不作为 SLCD 引脚使用时,这些引脚可以配置成通用功能 I/O 引脚。具体配置请参考通用功能 I/O 章节。

2.5  COM 和 SEG 引脚重映射

当作为 SLCD 引脚使用时,每一个 SLCD 引脚都可以被重映射为 COM 或者 SEG 引脚,以简化电路板上的布局布线。SLCD 模块支持从 L0 到 L63 最多 64 个 SLCD 引脚(SLCD 引脚的最终数量由产品规格书中设备引脚的数目决定),每一个引脚可以通过相应的 SLCD_CFGR0 和 SLCD_CFGR1 寄存器来配置,重映射其作为 COM 或者 SEG 功能。

2.6  时钟产生

时钟产生模块为波形发生模块和电荷泵模块提供各自所需的时钟,其结构如下:
时钟产生模块结构图

3 实验

3.1  硬件设计

本次实验使用MM32L0130片上SLCD驱动LCD液晶屏显示。硬件使用灵动股份设计的EVB-L0136开发板,板载LCD接口可以适配GDC0689液晶屏,GDC0689具有半透和反射两种模式,6位8字、6点视角、宽温,适用于工业设备等产品。GDC0689液晶屏全显效果图如下:

EVB-L0136开发板LCD模块原理图如下:

原理图1(LCD部分)
原理图2(MM32F0130部分)

3.2  程序设计

例程主要用到GDC0689液晶屏的数码管部分进行计数显示,以最右边的数码管作为小数部分,其余数码管作为整数部分,从最低位开始累加计数,满十就向前一位进1。
灵动股份设计了MM32F0130 SLCD相关的库函数以及API函数,容易理解和使用,代码较多,这里不再进行赘述,仅对部分主要程序进行分析。

3.21 SLCD测试函数

  1. void slcd_test(void)
  2. {
  3.     slcd_init();
  4.     while(1) {
  5.         LCD_DisplayDataUpdate();
  6.         DELAY_Ms(100);
  7.     }
  8. }
复制代码


3.22 SLCD初始化函数

void slcd_init()函数主要代码:
使能PWR、BKP时钟
  1.     RCC_APB1PeriphClockCmd(RCC_APB1ENR_PWR, ENABLE);
  2.     RCC_APB1PeriphClockCmd(RCC_APB1ENR_BKP, ENABLE);
复制代码

使能SLCD时钟,软件复位SLCD
  1.     RCC_SLCD_ClockCmd(SLCD, ENABLE);
  2.     SLCD_DeInit();
复制代码


SLCD的时钟源选择LSI,配置LSI时钟频率为40KHZ。
  1.   RCC_LSICLKConfig(RCC_LSICLKSource_40KHz);
  2.     RCC_LSICmd(ENABLE);
  3.     RCC_SLCDCLKConfig(RCC_SLCDCLKSource_LSI);
复制代码

LSI作为SLCD时钟源,对应时钟预分频系数为4,分频系数为16
  1.     else if(slcd_clk_source_freq <= LSI_VALUE) {
  2.         pre_value = SLCD_Prescaler_4;
  3.         div_value = SLCD_Divider_16;
  4.     }
复制代码


初始化SLCD结构体,配置1/4偏置、1/3占空比,VDD作为SLCD电源使能
  1.   slcd_struct.SLCD_Divider = div_value;
  2.     slcd_struct.SLCD_Duty = SLCD_Duty_1_4;
  3.     slcd_struct.SLCD_Bias = SLCD_Bias_1_3;
  4.     slcd_struct.SLCD_VoltageSource = SLCD_VoltSrcCapCharggDownVdd;
  5.     SLCD_Init(&slcd_struct);
复制代码


SLCD pin对应的GPIO配置为SEG或COM,并使能
  1. SLCD_IO_Config(&(SEGorCOM[0])); //must call after SLCD_init
复制代码


配合SLCD COM索引寄存器
  1. SLCD_COM_IndexInit(&(SCLD_COM_Index[0]));
复制代码


配置电荷泵时钟分频为1024
  1. SLCD_ChargePumpClockDivConfig(SLCD_ChargePumpClock_Div1024);
复制代码

正常驱动波形
  1. SLCD_LowPowerDriveCmd(DISABLE);
复制代码

配置无死区插入,当在两帧之间插入死区时,SEG和COM信号电压为零
  1. SLCD_DeadTimeConfig(SLCD_DeadTime_0);
复制代码

清除显示数据寄存器
  1. LCD_Clear();
复制代码

关闭SLCD闪烁模式,闪烁时钟分频系数为512
  1. SLCD_BlinkConfig(SLCD_BlinkMode_Off, SLCD_BlinkFrequency_Div512);
复制代码

配置SLCD闪烁索引
  1. SLCD_BLINK_IndexInit(SCLD_BLINK_Index);
复制代码

3.23 LCD更新显示数据函数
LCD_DisplayDataUpdate()函数主要代码:
   
  1. Number1 = (Number1 + 1) % 1000000;

  2.     if(Number1 < 10) {
  3.         LCD_DisplayNumber1(0, ' ', 0);
  4.         LCD_DisplayNumber1(1, ' ', 0);
  5.         LCD_DisplayNumber1(2, ' ', 0);
  6.         LCD_DisplayNumber1(3, ' ', 0);
  7.         LCD_DisplayNumber1(4, '0', 1);
  8.         LCD_DisplayNumber1(5, '0' + Number1, 0);
  9.     }
  10.     else if(Number1 < 100) {
  11.         LCD_DisplayNumber1(0, ' ', 0);
  12.         LCD_DisplayNumber1(1, ' ', 0);
  13.         LCD_DisplayNumber1(2, ' ', 0);
  14.         LCD_DisplayNumber1(3, ' ', 0);
  15.         LCD_DisplayNumber1(4, '0' + ((Number1 / 10) % 10), 1);
  16.         LCD_DisplayNumber1(5, '0' + ((Number1 / 1 ) % 10), 0);
  17.     }
  18.     ......(省略余下代码)
复制代码

其中LCD显示函数 void LCD_DisplayNumber1(u8 Index, char ch, u8 Point)用于配置数码管显示,函数的3个形参含义如下:
Index表示选中的数码管索引,对应6个数码管,可选值为0,1,2,3,4,5
ch表示要显示的数字,为char类型
Point表示该数码管是否显示Dp字段,显示则为1,否则为0
举例:代码中LCD_DisplayNumber1(5, '0' + Number1, 0)表示选中第5个数码管(最右),显示内容是Number的值,不显示Dp字段。

3.24 LCD显示函数

LCD_DisplayNumber1()函数主要代码:
  1. void LCD_DisplayNumber1(u8 Index, char ch, u8 Point)
  2. {
  3.     u8 i;
  4.     char TAB[6][8][4] =  {   // (1)
  5.         {"5A ", "5B ", "5C ", "5D ", "5E ", "5F ", "5G ", "DP5"},
  6.         {"6A ", "6B ", "6C ", "6D ", "6E ", "6F ", "6G ", "DP6"},
  7.         {"7A ", "7B ", "7C ", "7D ", "7E ", "7F ", "7G ", "DP7"},
  8.         {"8A ", "8B ", "8C ", "8D ", "8E ", "8F ", "8G ", "DP8"},
  9.         {"9A ", "9B ", "9C ", "9D ", "9E ", "9F ", "9G ", "DP9"},
  10.         {"10A", "10B", "10C", "10D", "10E", "10F", "10G", "   "},
  11.     };

  12.     u8 COMn = 0xFF, SEGn = 0xFF;

  13.     u8 Code = LCD_SearchCode(ch);   // (2)

  14.     if(Code != 0xFF) {
  15.         for(i = 0; i < 7; i++) {
  16.             LCD_SearchName(TAB[Index], &COMn, &SEGn);   // (3)

  17.             if((COMn != 0xFF) && (SEGn != 0xFF)) {
  18.                 LCD_WriteBit(COMn, LCD_SEG_Table[SEGn][0], LCD_SEG_Table[SEGn][1], (Code >> i) & 0x01);   // (4)
  19.             }
  20.         }

  21.         LCD_SearchName(TAB[Index][7], &COMn, &SEGn); // (5)

  22.         if((COMn != 0xFF) && (SEGn != 0xFF)) {
  23.             LCD_WriteBit(COMn, LCD_SEG_Table[SEGn][0], LCD_SEG_Table[SEGn][1], Point);   // (6)
  24.         }
  25.     }
  26. }
复制代码

1 定义三维字符数组TAB[6][8][4],其中[6]对应6位“8”字,[8]对应“8”字的8段(含DP段),[4]表示元素的长度,对应各段的名称。
2 形参ch表示要显示的数字,为char类型,LCD_SearchCode(char ch)函数用来遍历LCD_CODE_Table[38],如果传入的参数ch和LCD_CODE_Table.ch相等,则返回LCD_CODE_Table.Data,即该数字对应的段选信号。
3 LCD_SearchName(TAB[Index], &COMn, &SEGn)函数遍历所有COM口(4)和SEG口(22),如果TAB[Index]和LCD_NAME_Table[j]相等,则获取COMn和SEGn的值,然后返回。
4 获取COMn对应的显示数据寄存器索引,根据段选信号,给显示数据寄存器赋值。
5 获取Dp段对应的COMn和SEGn的值,然后返回。
6 获取COMn对应的显示数据寄存器索引,根据Dp段选信号,给显示数据寄存器赋值。
+10
回复

使用道具 举报

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

本版积分规则

QQ|Archiver|手机版|深圳市光明谷科技有限公司|光明谷商城|Sunshine Silicon Corpporation ( 粤ICP备14060730号|Sitemap

GMT+8, 2024-12-27 13:48 , Processed in 0.095237 second(s), 42 queries .

Powered by Discuz! X3.2 Licensed

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表