目录
一、简介
二、环境搭建
三、SLCD显示
一、简介
1、MM32L0130
MM32L0130 微控制器搭载 Arm Cortex-M0+内核,最高工作频率可达 48MHz。内置 64KB 高速存储器,并集成了丰富的 I/O 端口和外设模块。该产品包含 1 个 12 位的ADC、1 个比较器、2 个 16 位通用定时器、2 个 16 位基本定时器、1 个低功耗定和1 个 RTC 计数器,还包含标准的通信接口:2 个 UART 接口、1 个低功耗UART 接口、2 个 SPI 接 口、2 个 I2S 接口和 1 个 I2C 接口。此外,本产品还内置了段码式液晶驱动模块(SLCD)和红外信号调制模块(IRM)。
2、SLCD
MM32L0130 微控制器中搭载的SLCD 驱动器是用于单色无源液晶显示器(SLCD)的数字驱动器,具有多达 8 个公共端和多达 63 个分段端,SLCD 引脚最多为 64 个,因此最多可驱动 240(60x4)或 448(56x8)个段码。驱动段码的最终数量由产品规格书中设备引脚的数目决定。其技术特征如下所示:
显示帧率灵活控制;
兼容 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 传输 ;
支持中断(帧结束中断(End of frame)、闪烁周期中断(Blink cycle));
二、环境搭建
本次评测的EVB-L0136开发板上板载的MCU为MM32L0136C7P,为了测试MM32L0136的SLCD液晶驱动器。本次测试使用的开发环境为MDK-ARM Keil 5.34。搭建的步骤如下:
资料下载;
EV Board (MM32L0136C7P)资料链接:https://www.mindmotion.com.cn/support/development_tools/evaluation_boards/evboard/mm32l0136c7p/
Keil Pack 支持包链接:
注:Jlink无法识别MM32L0130,在设备支持包内有驱动(MM32_PACKAGE_Segger.exe),需要自行安装。
搭建工程
本次工程直接在MM32 SDK 软件库中的SLCD例程的基础上进行修改。
其工程配置如下图所示:
三、SLCD显示
1、硬件连接
EVB-L0136的SLCD引脚连接原理图如下图:
由图可知,段式液晶的10、11、23引脚并未与MCU连接,因此对应的有段式液晶的S5-S8、L1-L4、W2-W5段码无法点亮,注意使用时应将开发板中SW1、SW2、SW3、SW4开关全部拨于左侧。
2、SLCD驱动器
SLCD 驱动模块包括以下几个基本的子模块(SLCD 输出驱动引脚、时钟产生单元、内置升压电荷泵、偏置电压生成单元、时序控制和波形发生器),如下图所示。
在MM32L0136中SLCD 驱动模块内置了 16 个32比特显示数据寄存器。显示数据寄存器中的比特位与 LCD 显示屏上的段码一一对应,如果要点亮 LCD 显示屏上的某个段码,则需要把显示数据寄存器中的相对应的比特写为‘1’;反之如果要熄灭某个段码,则需要把对应的比特写为‘0’,如下图所示。
并且在不同的工作模式下,还可以划分为主/辅显示寄存器(为了避免在写入显示数据寄存器的时候影响 LCD 屏幕的显示),其主要对应关系如下:
模式 | SLCD_DR[15:8] | SLCD_DR[7:0]片区 |
static、1/2、1/3 和1/4 duty模式 | 辅助显示寄存器 | 主显示寄存器 |
1/6 和 1/8 duty 模式 | 主显示寄存器 | 主显示寄存器 |
还有闪烁显示数据寄存器等寄存器,请读者参考数据手册。
3、驱动程序
根据上图SLCD的段码与引脚对应关系可以得出,SEG1-SEG4、SEG5-SEG10对应的数字的段码分别为:
- /* 0 1 2 3 4 5 6 7 8 9 - NULL*/
- const uint8_t slcd_up_seg_number_map[16] = {0XEB,0X60,0XC7,0XE5,0X6C,0XAD,0XAF,0XE0,0XEF,0XED,0X40,0x00};
- /* 0 1 2 3 4 5 6 7 8 9 - NULL*/
- const uint8_t slcd_main_seg_number_map[16] = {0X7D,0X60,0X3E,0X7A,0X63,0X5B,0X5F,0X70,0X7F,0X7B,0X20,0x00};
- typedef struct
- {
- union {
- struct
- {
- uint8_t dp1_flag:1;
- uint8_t dp2_flag:1;
- uint8_t dp3_flag:1;
- uint8_t dp5_flag:1;
- uint8_t dp6_flag:1;
- uint8_t dp7_flag:1;
- uint8_t dp8_flag:1;
- uint8_t dp9_flag:1;
- } slcd_dp_bit;
- uint8_t data;
- } un_slcd_dp;
- union {
- struct
- {
- uint8_t s1_flag:1;
- uint8_t s2_flag:1;
- uint8_t s3_flag:1;
- uint8_t s4_flag:1;
- uint8_t s5_flag:1; // HardWare DisAble
- uint8_t s6_flag:1; // HardWare DisAble
- uint8_t s7_flag:1; // HardWare DisAble
- uint8_t s8_flag:1; // HardWare DisAble
- } slcd_s_bit;
- uint8_t data;
- } un_slcd_s;
- union {
- struct
- {
- uint16_t l1_flag:1; // HardWare DisAble
- uint16_t l2_flag:1; // HardWare DisAble
- uint16_t l3_flag:1; // HardWare DisAble
- uint16_t l4_flag:1; // HardWare DisAble
- uint16_t w1_flag:1;
- uint16_t w2_flag:1; // HardWare DisAble
- uint16_t w3_flag:1; // HardWare DisAble
- uint16_t w4_flag:1; // HardWare DisAble
- uint16_t w5_flag:1; // HardWare DisAble
- uint16_t t1_flag:1;
- uint16_t col1_flag:1;
- uint16_t col2_flag:1;
- uint16_t col3_flag:1;
- uint16_t s9_flag:1;
- uint16_t nouse_flag:2;
- } slcd_col_w_l_s9_bit;
- uint16_t data;
- } un_slcd_col_w_l_s9;
- uint8_t slcd_up_seg_buffer[4];
- uint8_t slcd_main_seg_buffer[6];
- } str_slcd_buffer;
显示时候,需要将每一个COM口对应的段码所对应的位置依次存放如对应的比特位。
首先建立一个display_buffer[22],每个数据中存入4个比特的数据,在显示的时候移入数据显示寄存器。其驱动代码如下所示:
- void slcd_refresh(void)
- {
- uint8_t seg_y = 0u,i = 0u;
- uint8_t display_buffer[22];
- uint32_t com_x;
- SLCD_ClearAllSegBits(BOARD_SLCD_PORT);
- for(i = 0 ; i<4; i++)
- {
- display_buffer[i*2] = slcd_up_seg_number_map[slcd_buffer.slcd_up_seg_buffer[i]]&0X0F;
- display_buffer[i*2+1] = (slcd_up_seg_number_map[slcd_buffer.slcd_up_seg_buffer[i]]>>4) &0X0F;
- }
- // dot flag driver
- display_buffer[1] |= slcd_buffer.un_slcd_dp.slcd_dp_bit.dp1_flag ;
- display_buffer[3] |= slcd_buffer.un_slcd_dp.slcd_dp_bit.dp2_flag ;
- display_buffer[5] |= slcd_buffer.un_slcd_dp.slcd_dp_bit.dp3_flag ;
- display_buffer[7] |= slcd_buffer.un_slcd_col_w_l_s9.slcd_col_w_l_s9_bit.col1_flag ;
- for(i = 0 ; i<3; i++)
- {
- display_buffer[9 + i*2] = slcd_main_seg_number_map[slcd_buffer.slcd_main_seg_buffer[i]]&0X0F;
- display_buffer[9 + i*2+1] = (slcd_main_seg_number_map[slcd_buffer.slcd_main_seg_buffer[i]]>>4) &0X0F;
- }
- for(i = 3 ; i<6; i++)
- {
- display_buffer[16 + (i-3)*2] = slcd_main_seg_number_map[slcd_buffer.slcd_main_seg_buffer[i]]&0X0F;
- display_buffer[16 + (i-3)*2+1] = (slcd_main_seg_number_map[slcd_buffer.slcd_main_seg_buffer[i]]>>4) &0X0F;
- }
- // dot flag driver
- display_buffer[10] |= slcd_buffer.un_slcd_dp.slcd_dp_bit.dp5_flag<<3 ;
- display_buffer[12] |= slcd_buffer.un_slcd_dp.slcd_dp_bit.dp6_flag<<3 ;
- display_buffer[14] |= slcd_buffer.un_slcd_dp.slcd_dp_bit.dp7_flag<<3 ;
- display_buffer[17] |= slcd_buffer.un_slcd_dp.slcd_dp_bit.dp8_flag<<3 ;
- display_buffer[19] |= slcd_buffer.un_slcd_dp.slcd_dp_bit.dp9_flag<<3 ;
- display_buffer[21] |= slcd_buffer.un_slcd_col_w_l_s9.slcd_col_w_l_s9_bit.s9_flag<<3 ;
- display_buffer[8] = (slcd_buffer.un_slcd_col_w_l_s9.slcd_col_w_l_s9_bit.w1_flag<<3)|(slcd_buffer.un_slcd_col_w_l_s9.slcd_col_w_l_s9_bit.t1_flag<<2)|
- (slcd_buffer.un_slcd_col_w_l_s9.slcd_col_w_l_s9_bit.col2_flag<<1)|(slcd_buffer.un_slcd_col_w_l_s9.slcd_col_w_l_s9_bit.col3_flag);
- display_buffer[15] = (slcd_buffer.un_slcd_s.slcd_s_bit.s1_flag<<3)|(slcd_buffer.un_slcd_s.slcd_s_bit.s2_flag<<2)|
- (slcd_buffer.un_slcd_s.slcd_s_bit.s3_flag<<1)|(slcd_buffer.un_slcd_s.slcd_s_bit.s4_flag);
- for (com_x = 0u; com_x < BOARD_SLCD_COM_NUM; com_x++)
- {
- slcd_seg_bits[0u] = 0u;
- slcd_seg_bits[1u] = 0u;
- for (seg_y = 0u; seg_y < 22u; seg_y++)
- {
- if (slcd_seg_pin_buff[seg_y] < 32u)
- {
- slcd_seg_bits[0u] |= (((display_buffer[seg_y]>>com_x)&0x01) << slcd_seg_pin_buff[seg_y] ); /* Segment 0 ~ 31 bit mask. */
- }
- else
- {
- slcd_seg_bits[1u] |= (((display_buffer[seg_y]>>com_x)&0x01) << (slcd_seg_pin_buff[seg_y] - 32u) ); /* Segment 32 ~ 63 bit mask. */
- }
- }
- /* Set COMx segment bits to display. */
- SLCD_SetCOMxSegBits(BOARD_SLCD_PORT, com_x, (uint32_t * )slcd_seg_bits);
- }
- }
4、显示效果
显示效果如下所示:
以上测评的Demo 链接:https://mbb.eet-china.com/download/299510.html
或者 链接:https://pan.baidu.com/s/1VVoQNMZUeOWQCV86vKxYGQ
提取码:n2co