原创 【灵动微电子 L0136 温控器/遥控器应用】 单色液晶驱动(段式)

2023-1-6 18:12 990 7 7 分类: MCU/ 嵌入式 文集: MM32

目录

一、简介

二、环境搭建

三、SLCD显示


一、简介

1、MM32L0130

MM32L0130 微控制器搭载 Arm Cortex-M0+内核,最高工作频率可达 48MHz 64KB 高速存储器,并集成了丰富的 I/O 端口和外设模块。产品包含 1 12 位的ADC1 比较器、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 ,因此最多可驱动 24060x4)或 44856x8段码。驱动段码的最终数量由产品规格书中设备引脚的数目决定。其技术特征如下所示:

显示帧率灵活控制

兼容 APB 接口

支持静态、1/21/31/41/6 1/8 占空比

支持 1/21/3 1/4 偏置电压设置

为了存储显示数据,内置了 16*32bit 显示数据寄存器

通过软件来调整 SLCD 输出电压,来调节对比度

外围电路简单,不需要模拟器件支持

1)内嵌电容升压器来得到比电源电压更高而且不受其影响的 SLCD 驱动电压。升压器产生的 SLCD 驱动电压范围可调,可以匹配支持 3V 或者 5V LCD 屏幕

2SLCD 驱动电源可以通过软件来选择内部电源或外部电源。

3)可以选择使用内嵌电容分压器对 SLCD 驱动电压进行分压,得到驱动电压的中间值(VLCDrail1VLCDrail2VLCDrail3VLCDrail4)

两种调整显示对比度的方法

1)当采用内部升压器来提供 VLCD 电源时,可以通过软件调节 VLCD 输出电压

2)其它情况下可以在每帧显示之间插入死区时间

支持以下低功耗模式:低功耗运行模式,睡眠模式,低功耗睡眠模式,停止模式,深度停止模式,待机模式;在不需要显示的时候,可以完全关闭 SLCD 驱动以达到降低功耗的目的

支持相位反转模式,降低功耗和 EMI

每一帧显示开始的时候,通过中断信号与软件同步,更新显示数据

闪烁功能

1)可以从所有段码中任意选择 1 8 个段码闪烁显示,也可以闪烁显示全部段码

2)在静态、1/21/31/4 占空比模式下可以闪烁显示任意段码

3)软件选择闪烁频率,支持闪烁频率 0.5Hz, 1Hz, 2Hz 4Hz

灵活的引脚复用功能,可以配置任意 LCD 驱动引脚成为 COM 或者 SEG 功能SLCD 的驱动引脚在没有被配置成 SLCD 功能的时候,可以作为 GPIO 引脚来使用

SLCD 驱动电平(VLCDrail1VLCDrail2VLCDrail3VLCDrail4)的去耦合功能

支持低功耗驱动波形

支持 DMA 传输

支持中断帧结束中断(End of frame闪烁周期中断(Blink cycle


二、环境搭建

本次评测EVB-L0136开发板上板载的MCU为MM32L0136C7P为了测试MM32L0136的SLCD液晶驱动器。本次测试使用的开发环境为MDK-ARM Keil 5.34。搭建的步骤如下:

资料下载;

MM32L0130资料链接:https://www.mindmotion.com.cn/products/mm32mcu/mm32l/new_mm32l0/mm32l0130/

EV Board (MM32L0136C7P)资料链接:https://www.mindmotion.com.cn/support/development_tools/evaluation_boards/evboard/mm32l0136c7p/

Keil Pack 支持包链接:

https://www.mindmotion.com.cn/support/software/keil_pack/

注:Jlink无法识别MM32L0130,在设备支持包内有驱动(MM32_PACKAGE_Segger.exe),需要自行安装。

搭建工程

本次工程直接在MM32 SDK 软件库中的SLCD例程的基础上进行修改。

其工程配置如下图所示:

SLCD显示

1、硬件连接

EVB-L0136SLCD引脚连接原理图如下图:

由图可知,段式液晶的10、11、23引脚并未与MCU连接,因此对应的有段式液晶的S5-S8、L1-L4、W2-W5段码无法点亮,注意使用时应将开发板中SW1、SW2、SW3、SW4开关全部拨于左侧

 

2、SLCD驱动器

SLCD 驱动模块包括以下几个基本的子模块SLCD 输出驱动引脚时钟产生单元内置升压电荷泵偏置电压生成单元时序控制和波形发生器,如下图所示。

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

并且在不同的工作模式下,还可以划分为主/辅显示寄存器为了避免在写入显示数据寄存器的时候影响 LCD 屏幕的显示,其主要对应关系如下:

   模式     

       SLCD_DR[15:8]

                  SLCD_DR[7:0]片区

static1/21/3 1/4 duty模式

   辅助显示寄存器

    主显示寄存器

1/6 1/8 duty 模式

  主显示寄存器

    主显示寄存器

还有闪烁显示数据寄存器等寄存器,请读者参考数据手册。


3、驱动程序

根据上图SLCD的段码与引脚对应关系可以得出,SEG1-SEG4、SEG5-SEG10对应的数字的段码分别为:

  1.  </p><p style="text-align: left; margin-top: 0; margin-bottom: 0;">                                                                   /* 0     1       2       3     4       5       6      7       8     9       -       NULL*/
  2. const uint8_t slcd_up_seg_number_map[16] = {0XEB,0X60,0XC7,0XE5,0X6C,0XAD,0XAF,0XE0,0XEF,0XED,0X40,0x00};
  3.                                                                       /* 0     1       2       3     4       5       6      7       8     9       -       NULL*/
  4. const uint8_t slcd_main_seg_number_map[16] = {0X7D,0X60,0X3E,0X7A,0X63,0X5B,0X5F,0X70,0X7F,0X7B,0X20,0x00};

建立一个结构体,用结构体存放每一个段码的信息(可以直接修改结构体的内容从而显示屏幕的信息),结构体如下所示:

  1. typedef struct
  2. {
  3. union {
  4. struct
  5. {
  6. uint8_t dp1_flag:1;
  7. uint8_t dp2_flag:1;
  8. uint8_t dp3_flag:1;
  9. uint8_t dp5_flag:1;
  10. uint8_t dp6_flag:1;
  11. uint8_t dp7_flag:1;
  12. uint8_t dp8_flag:1;
  13. uint8_t dp9_flag:1;
  14. } slcd_dp_bit;
  15. uint8_t data;
  16. } un_slcd_dp;
  17. union {
  18. struct
  19. {
  20. uint8_t s1_flag:1;
  21. uint8_t s2_flag:1;
  22. uint8_t s3_flag:1;
  23. uint8_t s4_flag:1;
  24. uint8_t s5_flag:1; // HardWare DisAble
  25. uint8_t s6_flag:1; // HardWare DisAble
  26. uint8_t s7_flag:1; // HardWare DisAble
  27. uint8_t s8_flag:1; // HardWare DisAble
  28. } slcd_s_bit;
  29. uint8_t data;
  30. } un_slcd_s;
  31. union {
  32. struct
  33. {
  34. uint16_t l1_flag:1; // HardWare DisAble
  35. uint16_t l2_flag:1; // HardWare DisAble
  36. uint16_t l3_flag:1; // HardWare DisAble
  37. uint16_t l4_flag:1; // HardWare DisAble
  38. uint16_t w1_flag:1;
  39. uint16_t w2_flag:1; // HardWare DisAble
  40. uint16_t w3_flag:1; // HardWare DisAble
  41. uint16_t w4_flag:1; // HardWare DisAble
  42. uint16_t w5_flag:1; // HardWare DisAble
  43. uint16_t t1_flag:1;
  44. uint16_t col1_flag:1;
  45. uint16_t col2_flag:1;
  46. uint16_t col3_flag:1;
  47. uint16_t s9_flag:1;
  48. uint16_t nouse_flag:2;
  49. } slcd_col_w_l_s9_bit;
  50. uint16_t data;
  51. } un_slcd_col_w_l_s9;
  52. uint8_t slcd_up_seg_buffer[4];
  53. uint8_t slcd_main_seg_buffer[6];
  54. } str_slcd_buffer;

显示时候,需要将每一个COM口对应的段码所对应的位置依次存放如对应的比特位。

首先建立一个display_buffer[22],每个数据中存入4个比特的数据,在显示的时候移入数据显示寄存器。其驱动代码如下所示:

  1. void slcd_refresh(void)
  2. {
  3. uint8_t seg_y = 0u,i = 0u;
  4. uint8_t display_buffer[22];
  5. uint32_t com_x;
  6. SLCD_ClearAllSegBits(BOARD_SLCD_PORT);
  7. for(i = 0 ; i<4; i++)
  8. {
  9. display_buffer[i*2] = slcd_up_seg_number_map[slcd_buffer.slcd_up_seg_buffer[i]]&0X0F;
  10. display_buffer[i*2+1] = (slcd_up_seg_number_map[slcd_buffer.slcd_up_seg_buffer[i]]>>4) &0X0F;
  11. }
  12. // dot flag driver
  13. display_buffer[1] |= slcd_buffer.un_slcd_dp.slcd_dp_bit.dp1_flag ;
  14. display_buffer[3] |= slcd_buffer.un_slcd_dp.slcd_dp_bit.dp2_flag ;
  15. display_buffer[5] |= slcd_buffer.un_slcd_dp.slcd_dp_bit.dp3_flag ;
  16. display_buffer[7] |= slcd_buffer.un_slcd_col_w_l_s9.slcd_col_w_l_s9_bit.col1_flag ;
  17. for(i = 0 ; i<3; i++)
  18. {
  19. display_buffer[9 + i*2] = slcd_main_seg_number_map[slcd_buffer.slcd_main_seg_buffer[i]]&0X0F;
  20. display_buffer[9 + i*2+1] = (slcd_main_seg_number_map[slcd_buffer.slcd_main_seg_buffer[i]]>>4) &0X0F;
  21. }
  22. for(i = 3 ; i<6; i++)
  23. {
  24. display_buffer[16 + (i-3)*2] = slcd_main_seg_number_map[slcd_buffer.slcd_main_seg_buffer[i]]&0X0F;
  25. display_buffer[16 + (i-3)*2+1] = (slcd_main_seg_number_map[slcd_buffer.slcd_main_seg_buffer[i]]>>4) &0X0F;
  26. }
  27. // dot flag driver
  28. display_buffer[10] |= slcd_buffer.un_slcd_dp.slcd_dp_bit.dp5_flag<<3 ;
  29. display_buffer[12] |= slcd_buffer.un_slcd_dp.slcd_dp_bit.dp6_flag<<3 ;
  30. display_buffer[14] |= slcd_buffer.un_slcd_dp.slcd_dp_bit.dp7_flag<<3 ;
  31. display_buffer[17] |= slcd_buffer.un_slcd_dp.slcd_dp_bit.dp8_flag<<3 ;
  32. display_buffer[19] |= slcd_buffer.un_slcd_dp.slcd_dp_bit.dp9_flag<<3 ;
  33. display_buffer[21] |= slcd_buffer.un_slcd_col_w_l_s9.slcd_col_w_l_s9_bit.s9_flag<<3 ;
  34. 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)|
  35. (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);
  36. 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)|
  37. (slcd_buffer.un_slcd_s.slcd_s_bit.s3_flag<<1)|(slcd_buffer.un_slcd_s.slcd_s_bit.s4_flag);
  38. for (com_x = 0u; com_x < BOARD_SLCD_COM_NUM; com_x++)
  39. {
  40. slcd_seg_bits[0u] = 0u;
  41. slcd_seg_bits[1u] = 0u;
  42. for (seg_y = 0u; seg_y < 22u; seg_y++)
  43. {
  44. if (slcd_seg_pin_buff[seg_y] < 32u)
  45. {
  46. slcd_seg_bits[0u] |= (((display_buffer[seg_y]>>com_x)&0x01) << slcd_seg_pin_buff[seg_y] ); /* Segment 0 ~ 31 bit mask. */
  47. }
  48. else
  49. {
  50. slcd_seg_bits[1u] |= (((display_buffer[seg_y]>>com_x)&0x01) << (slcd_seg_pin_buff[seg_y] - 32u) ); /* Segment 32 ~ 63 bit mask. */
  51. }
  52. }
  53. /* Set COMx segment bits to display. */
  54. SLCD_SetCOMxSegBits(BOARD_SLCD_PORT, com_x, (uint32_t * )slcd_seg_bits);
  55. }
  56. }


4、显示效果

显示效果如下所示:

 http:// 


以上的Demo:https://mbb.eet-china.com/download/299510.html


 

 

作者: 腾辉, 来源:面包板社区

链接: https://mbb.eet-china.com/blog/uid-me-3933667.html

版权声明:本文为博主原创,未经本人允许,禁止转载!

文章评论0条评论)

登录后参与讨论
我要评论
0
7
关闭 站长推荐上一条 /2 下一条