zoukankan      html  css  js  c++  java
  • STM8L段式液晶驱动器

    STM8L部分型号集成了段式液晶驱动器,可以驱动4*28=112个液晶段.段式液晶屏为低功耗显示器件,功耗根据屏的大小和显示段数会有所不同,通常功耗在10ua左右.生活中,数字电子表,数字万用表,数显温度计等,使用的都是段式液晶屏,通常一颗纽扣电池可以保证设备间隔不断显示数字两年或更久.
    大家比较熟悉的液晶屏1602模块其实也是段式液晶,是一个有很多段的点组成的,由于点比较多,所以1602模块集成了驱动芯片,我们只需给1602送数据,就可以控制1602进行显示了.液晶本身不会发光,1602之所以会发光是因为使用了LED背光板.
    段式液晶驱动器,通常会含有一个电压泵,一个频率分频器.电压泵用来提供驱动液晶段的电压,电压的高低决定着显示的清晰度,也就是决定着液晶的对比度.提供给LCD驱动器的频率决定着,刷新段式液晶的频率,如果提供给LCD的频率太低,会看到显示时的频闪.


    从上图可以看到,除了分频器和电压泵部分,还有显存.所有液晶屏都会有显存,每个显存控制着对应的引脚,对于STM8L的八位显存,可以控制8个引脚和一个COM引脚,比如STM8LRAM0控制着COM0对应的S0~S7引脚.
    当我们需要驱动一块液晶屏时,首先要拿到这种液晶屏的引脚对应显示段的图纸.如下图,由于STM8L152C6RAM0控制着COM0对应的S0~S7引脚,如果要显示下图的"",那么我们只需要向RAM0写入数据0x01.
    本例程的硬件平台仍然是ST官方的开发板STM8L-DISCOVERY.ST官网的编号为UM0970这份文档中,有对开发板上液晶屏的介绍.


    这份资料,并不是十分直观.找到显存对应的液晶屏上的段,对写程序来说很重要.



    本例程,参考ST提供的例程,根据自己的理解,编写了LCD驱动程序,提供一个可以在液晶屏上最多显示六位数字的接口的程序,读者可以调用此程序,显示任意六位以内的数字.

    1. /****************************************************************************************
    2. *开发环境:IAR for stm8 v6.5.3
    3. *硬件平台:STM8L-DISCOVERY
    4. *功能说明:使用STM8L-DISCOVERY液晶屏显示一串6位数字
    5. *    者:茗风
    6. ****************************************************************************************/
    7. #include"iostm8l152c6.h"
    8. #include"stdint.h"
    9. /*  =========================================================================
    10.                                LCD MAPPING
    11.   =========================================================================
    12.           A
    13.    _  ----------
    14. COL |_| |   |J  /|
    15.      F| H  |  K |B
    16.    _  |   | /  |
    17. COL |_| --G-- --M--
    18.       |   /|   |
    19.      E|  Q |  N |C
    20.    _  | /  |P  |   
    21. DP  |_| -----------  
    22.           D      
    23. */
    24. #define a 0x01
    25. #define b 0x02
    26. #define c 0x04
    27. #define d 0x08
    28. #define e 0x10
    29. #define f 0x20
    30. #define g 0x40
    31. #define m 0x80
    32. const uint8_t LCD_Tab[10] = {
    33.               a + b + c + d + e + f,                        // Displays "0"
    34.               b + c,                                        // Displays "1"
    35.               a + b + m + g + e + d,                        // Displays "2"
    36.               a + b + m + g + c + d,                        // Displays "3"
    37.               f + g + m + b + c,                        // Displays "4"
    38.               a + f + g + m + c +d,                        // Displays "5"
    39.               a + f + e + d + c + g + m ,                // Displays "6"
    40.               a + b + c,                                // Displays "7"
    41.               a + b + c + d + e + f + g + m,                // Displays "8"
    42.               a + b + c + d + f + g + m                // Displays "9"
    43. };
    44. /******************************************************************************************************
    45. *      称:void LCD_Config(void)
    46. *      能:配置DAC,禁用DMA,不使用TIM4触发,也不用软件触发,写入DHR的数据被立即送入DOR寄存器,
    47. *            立即输出对应电压
    48. *  入口参数:无
    49. *  出口参数:无
    50. *      明:STM8L152C6属于中等容量MCU,只有一路DAC输出,输出引脚为PF0
    51. *      例:无
    52. ******************************************************************************************************/
    53. void LCD_Config(void)
    54. //------打开LCD/RTC时钟------
    55. CLK_PCKENR2_PCKEN22=1;//打开RTC时钟,LCD刷新频率与此时钟有关
    56. CLK_PCKENR2_PCKEN23=1;//打开LCD时钟,读写LCD寄存器用到此时钟
    57. //---选择LSE作为RTC时钟---
    58. CLK_CRTCR_RTCSEL0=0;
    59. CLK_CRTCR_RTCSEL1=0;
    60. CLK_CRTCR_RTCSEL2=0;
    61. CLK_CRTCR_RTCSEL3=1;
    62. /* 0000: No clock selected
    63.  0001: HSI clock used as RTC clock source
    64.  0010: LSI clock used as RTC clock source
    65.  0100: HSE clock used as RTC clock source
    66.  1000: LSE clock used as RTC clock sourc*/
    67. //----设置RTC时钟分频值----
    68. CLK_CRTCR_RTCDIV0=0;
    69. CLK_CRTCR_RTCDIV1=0;
    70. CLK_CRTCR_RTCDIV2=0;
    71. /*000: RTC clock source/1
    72. 001: RTC clock source /2
    73. 010: RTC clock source /4
    74. 011: RTC clock source /8
    75. 100: RTC clock source /16
    76. 101: RTC clock source /32
    77. 110: RTC clock source /64
    78. 111: RTC clock source /128*/
    79. //----设置LCD预分频值----  
    80. LCD_FRQ_PS0=0;// 2^PS[3:0]
    81. LCD_FRQ_PS1=0;//分频值为1
    82. LCD_FRQ_PS2=0;
    83. LCD_FRQ_PS3=0;
    84. //----设置LCD分频值----  
    85. LCD_FRQ_DIV0=1;//DIV[3:0]+16
    86. LCD_FRQ_DIV1=1;//分频值为15+16=31
    87. LCD_FRQ_DIV2=1;
    88. LCD_FRQ_DIV3=1;  
    89. //以上分频值的设置,最为了得到适合的LCD的刷新频率,如果增大分频值,会导致
    90. //LCD刷新频率变低,会看到LCD显示出现闪烁
    91. //比如,我们将PS[3:0]设置为0011,会看到液晶闪烁  
    92. //----1/4 duty----  
    93. LCD_CR1_DUTY0=1;//1/4 duty
    94. LCD_CR1_DUTY1=1;
    95. /* Duty ratio selection
    96.  00: Static duty
    97.  01: 1/2 duty
    98.  10: 1/3 duty
    99.  11: 1/4 duty      */
    100. //----1/3 bias----     
    101. LCD_CR1_B2=0;//1/3 bias
    102. /* 0: 1/3 bias
    103.  1: 1/2 bias  */
    104. //----内部电压源----   
    105. LCD_CR2_VSEL=0;
    106. //----打开引脚的SEG功能----     
    107. // LCD_PM0=0xFF;//头文件这个地方定义错误,无法直接向LCD_PM0写入数据
    108. // LCD_PM1=0xFF;//PM0寄存器定义错误,导致PM1也无法直接写入
    109. // LCD_PM2=0xFF;//PM0寄存器定义错误,导致PM2也无法直接写入
    110. *((uint8_t *)0x5404)=0xFF;//直接向LCD_PM0寄存器的地址写入数据
    111. *((uint8_t *)0x5405)=0xFF;//直接向LCD_PM1寄存器的地址写入数据
    112. *((uint8_t *)0x5406)=0xFF;//直接向LCD_PM2寄存器的地址写入数据
    113. //----To set contrast to mean value----   
    114. LCD_CR2_CC0=0;//对比度
    115. LCD_CR2_CC1=1;
    116. LCD_CR2_CC2=0;
    117. /*  000: VLCD0  2.6V
    118.   001: VLCD1  2.7V
    119.   010: VLCD2  2.8V
    120.   011: VLCD3  2.9V
    121.   100: VLCD4  3.0V
    122.   101: VLCD5  3.1V
    123.   110: VLCD6  3.2V
    124.   111: VLCD7    */
    125.       
    126. //----Dead time 0----         
    127. LCD_CR3_DEAD0=0;//no dead time
    128. LCD_CR3_DEAD1=0;  
    129. LCD_CR3_DEAD2=0;
    130. //----LCD_PulseOnDuration_1----
    131. LCD_CR2_PON0=1; 
    132. LCD_CR2_PON1=0;  
    133. LCD_CR2_PON2=0;          
    134. /*  000: 0 CLKps pulses
    135.   001: 1 CLKps pulses
    136.   010: 2 CLKps pulses
    137.   011: 3 CLKps pulses
    138.   100: 4 CLKps pulses
    139.   101: 5 CLKps pulses
    140.   110: 6 CLKps pulses
    141.   111: 7 CLKps pulses  */
    142.       
    143. //----Enable LCD peripheral----        
    144. LCD_CR3_LCDEN=1;
    145. }
    146. /******************************************************************************************************
    147. *            称:LCD_DisplayNum(uint8_t number)
    148. *              能:控制段式液晶屏的数字显示部分
    149. *  入口参数:number:要显示的数字
    150. *  出口参数:无
    151. *            明:根据数字的长度,判断要显示的长度,长度大于6,只显示后六位
    152. *            例:无
    153. ******************************************************************************************************/
    154. void LCD_DisplayNum(uint32_t number)
    155. {
    156. uint8_t cnts=0,tmp=0;
    157. if(number<10)cnts=1;
    158. else if(number<100)cnts=2;
    159. else if(number<1000)cnts=3;
    160. else if(number<10000)cnts=4;
    161. else if(number<100000)cnts=5;
    162. else if(number<(uint32_t) 1000000)cnts=6;
    163. else cnts=6;
    164. //判断需要显示数字的长度,确定在LCD屏上需要的位数
    165. switch(cnts)
    166. {
    167.   case 6:
    168.          tmp = LCD_Tab[number%1000000/100000];
    169.          ((tmp&m)==0)?(LCD_RAM0&=~0x02):(LCD_RAM0 |=0x02) ;
    170.          ((tmp&e)==0)?(LCD_RAM0&=~0x01):(LCD_RAM0 |=0x01) ;
    171.          ((tmp&g)==0)?(LCD_RAM2&=~0x80):(LCD_RAM2 |=0x80) ;
    172.          ((tmp&b)==0)?(LCD_RAM2&=~0x40):(LCD_RAM2 |=0x40) ;
    173.          ((tmp&f)==0)?(LCD_RAM6&=~0x08):(LCD_RAM6 |=0x08) ;
    174.          ((tmp&a)==0)?(LCD_RAM6&=~0x04):(LCD_RAM6 |=0x04) ;
    175.          ((tmp&c)==0)?(LCD_RAM3&=~0x20):(LCD_RAM3 |=0x20) ;
    176.          ((tmp&d)==0)?(LCD_RAM3&=~0x10):(LCD_RAM3 |=0x10) ;                      
    177.   case 5:
    178.          tmp = LCD_Tab[number%100000/10000];
    179.          ((tmp&m)==0)?(LCD_RAM0&=~0x08):(LCD_RAM0 |=0x08) ;
    180.          ((tmp&e)==0)?(LCD_RAM0&=~0x04):(LCD_RAM0 |=0x04) ;
    181.          ((tmp&g)==0)?(LCD_RAM2&=~0x20):(LCD_RAM2 |=0x20) ;
    182.          ((tmp&b)==0)?(LCD_RAM2&=~0x10):(LCD_RAM2 |=0x10) ;
    183.          ((tmp&f)==0)?(LCD_RAM6&=~0x02):(LCD_RAM6 |=0x02) ;
    184.          ((tmp&a)==0)?(LCD_RAM6&=~0x01):(LCD_RAM6 |=0x01) ;
    185.          ((tmp&c)==0)?(LCD_RAM3&=~0x80):(LCD_RAM3 |=0x80) ;
    186.          ((tmp&d)==0)?(LCD_RAM3&=~0x40):(LCD_RAM3 |=0x40) ;           
    187.          
    188.   case 4:
    189.          tmp = LCD_Tab[number%10000/1000];
    190.          ((tmp&m)==0)?(LCD_RAM0&=~0x20):(LCD_RAM0 |=0x20) ;
    191.          ((tmp&e)==0)?(LCD_RAM0&=~0x10):(LCD_RAM0 |=0x10) ;
    192.          ((tmp&g)==0)?(LCD_RAM2&=~0x08):(LCD_RAM2 |=0x08) ;
    193.          ((tmp&b)==0)?(LCD_RAM2&=~0x04):(LCD_RAM2 |=0x04) ;
    194.          ((tmp&f)==0)?(LCD_RAM5&=~0x80):(LCD_RAM5 |=0x80) ;
    195.          ((tmp&a)==0)?(LCD_RAM5&=~0x40):(LCD_RAM5 |=0x40) ;
    196.          ((tmp&c)==0)?(LCD_RAM4&=~0x02):(LCD_RAM4 |=0x02) ;
    197.          ((tmp&d)==0)?(LCD_RAM4&=~0x01):(LCD_RAM4 |=0x01) ;           
    198.   case 3:
    199.          tmp = LCD_Tab[number%1000/100];
    200.          ((tmp&m)==0)?(LCD_RAM0&=~0x80):(LCD_RAM0 |=0x80) ;
    201.          ((tmp&e)==0)?(LCD_RAM0&=~0x40):(LCD_RAM0 |=0x40) ;
    202.          ((tmp&g)==0)?(LCD_RAM2&=~0x02):(LCD_RAM2 |=0x02) ;
    203.          ((tmp&b)==0)?(LCD_RAM2&=~0x01):(LCD_RAM2 |=0x01) ;
    204.          ((tmp&f)==0)?(LCD_RAM5&=~0x20):(LCD_RAM5 |=0x20) ;
    205.          ((tmp&a)==0)?(LCD_RAM5&=~0x10):(LCD_RAM5 |=0x10) ;
    206.          ((tmp&c)==0)?(LCD_RAM4&=~0x08):(LCD_RAM4 |=0x08) ;
    207.          ((tmp&d)==0)?(LCD_RAM4&=~0x04):(LCD_RAM4 |=0x04) ;
    208.  case 2:
    209.          tmp = LCD_Tab[number%100/10];
    210.          ((tmp&m)==0)?(LCD_RAM1&=~0x02):(LCD_RAM1 |=0x02) ;
    211.          ((tmp&e)==0)?(LCD_RAM1&=~0x01):(LCD_RAM1 |=0x01) ;
    212.          ((tmp&g)==0)?(LCD_RAM1&=~0x80):(LCD_RAM1 |=0x80) ;
    213.          ((tmp&b)==0)?(LCD_RAM1&=~0x40):(LCD_RAM1 |=0x40) ;
    214.          ((tmp&f)==0)?(LCD_RAM5&=~0x08):(LCD_RAM5 |=0x08) ;
    215.          ((tmp&a)==0)?(LCD_RAM5&=~0x04):(LCD_RAM5 |=0x04) ;
    216.          ((tmp&c)==0)?(LCD_RAM4&=~0x20):(LCD_RAM4 |=0x20) ;
    217.          ((tmp&d)==0)?(LCD_RAM4&=~0x10):(LCD_RAM4 |=0x10) ;
    218.  case 1: 
    219.          tmp = LCD_Tab[number%10];
    220.          ((tmp&m)==0)?(LCD_RAM1&=~0x08):(LCD_RAM1 |=0x08) ;
    221.          ((tmp&e)==0)?(LCD_RAM1&=~0x04):(LCD_RAM1 |=0x04) ;
    222.          ((tmp&g)==0)?(LCD_RAM1&=~0x20):(LCD_RAM1 |=0x20) ;
    223.          ((tmp&b)==0)?(LCD_RAM1&=~0x10):(LCD_RAM1 |=0x10) ;
    224.          ((tmp&f)==0)?(LCD_RAM5&=~0x02):(LCD_RAM5 |=0x02) ;
    225.          ((tmp&a)==0)?(LCD_RAM5&=~0x01):(LCD_RAM5 |=0x01) ;
    226.          ((tmp&c)==0)?(LCD_RAM4&=~0x80):(LCD_RAM4 |=0x80) ;
    227.          ((tmp&d)==0)?(LCD_RAM4&=~0x40):(LCD_RAM4 |=0x40) ;
    228.   break;
    229.   default:break;
    230. }
    231. }
    232. void main(void)
    233. {
    234. LCD_Config();
    235. LCD_DisplayNum(201609);
    236. //  asm("rim");               //enable interrupts
    237. while(1)
    238. {
    239.   asm("wfi");
    240. }
    241. }

    复制代码

  • 相关阅读:
    HDOJ 4747 Mex
    HDU 1203 I NEED A OFFER!
    HDU 2616 Kill the monster
    HDU 3496 Watch The Movie
    Codeforces 347A A. Difference Row
    Codeforces 347B B. Fixed Points
    Codeforces 372B B. Hungry Sequence
    HDU 1476 Sudoku Killer
    HDU 1987 How many ways
    HDU 2564 词组缩写
  • 原文地址:https://www.cnblogs.com/nimadi/p/12204800.html
Copyright © 2011-2022 走看看