nimadi

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

 

 


从上图可以看到,除了分频器和电压泵部分,还有显存.所有液晶屏都会有显存,每个显存控制着对应的引脚,对于STM8L的八位显存,可以控制8个引脚和一个COM引脚,比如STM8L的RAM0控制着COM0对应的S0~S7引脚.
当我们需要驱动一块液晶屏时,首先要拿到这种液晶屏的引脚对应显示段的图纸.如下图,由于STM8L152C6的RAM0控制着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. { 
  55. //------打开LCD/RTC时钟------
  56. CLK_PCKENR2_PCKEN22=1;//打开RTC时钟,LCD刷新频率与此时钟有关
  57. CLK_PCKENR2_PCKEN23=1;//打开LCD时钟,读写LCD寄存器用到此时钟
  58. //---选择LSE作为RTC时钟---
  59. CLK_CRTCR_RTCSEL0=0;
  60. CLK_CRTCR_RTCSEL1=0;
  61. CLK_CRTCR_RTCSEL2=0;
  62. CLK_CRTCR_RTCSEL3=1;
  63. /* 0000: No clock selected
  64.  0001: HSI clock used as RTC clock source
  65.  0010: LSI clock used as RTC clock source
  66.  0100: HSE clock used as RTC clock source
  67.  1000: LSE clock used as RTC clock sourc*/
  68. //----设置RTC时钟分频值----
  69. CLK_CRTCR_RTCDIV0=0;
  70. CLK_CRTCR_RTCDIV1=0;
  71. CLK_CRTCR_RTCDIV2=0;
  72. /*000: RTC clock source/1
  73. 001: RTC clock source /2
  74. 010: RTC clock source /4
  75. 011: RTC clock source /8
  76. 100: RTC clock source /16
  77. 101: RTC clock source /32
  78. 110: RTC clock source /64
  79. 111: RTC clock source /128*/
  80. //----设置LCD预分频值----  
  81. LCD_FRQ_PS0=0;// 2^PS[3:0]
  82. LCD_FRQ_PS1=0;//分频值为1
  83. LCD_FRQ_PS2=0;
  84. LCD_FRQ_PS3=0;
  85. //----设置LCD分频值----  
  86. LCD_FRQ_DIV0=1;//DIV[3:0]+16
  87. LCD_FRQ_DIV1=1;//分频值为15+16=31
  88. LCD_FRQ_DIV2=1;
  89. LCD_FRQ_DIV3=1;  
  90. //以上分频值的设置,最为了得到适合的LCD的刷新频率,如果增大分频值,会导致
  91. //LCD刷新频率变低,会看到LCD显示出现闪烁
  92. //比如,我们将PS[3:0]设置为0011,会看到液晶闪烁  
  93. //----1/4 duty----  
  94. LCD_CR1_DUTY0=1;//1/4 duty
  95. LCD_CR1_DUTY1=1;
  96. /* Duty ratio selection
  97.  00: Static duty
  98.  01: 1/2 duty
  99.  10: 1/3 duty
  100.  11: 1/4 duty      */
  101. //----1/3 bias----     
  102. LCD_CR1_B2=0;//1/3 bias
  103. /* 0: 1/3 bias
  104.  1: 1/2 bias  */
  105. //----内部电压源----   
  106. LCD_CR2_VSEL=0;
  107. //----打开引脚的SEG功能----     
  108. // LCD_PM0=0xFF;//头文件这个地方定义错误,无法直接向LCD_PM0写入数据
  109. // LCD_PM1=0xFF;//PM0寄存器定义错误,导致PM1也无法直接写入
  110. // LCD_PM2=0xFF;//PM0寄存器定义错误,导致PM2也无法直接写入
  111. *((uint8_t *)0x5404)=0xFF;//直接向LCD_PM0寄存器的地址写入数据
  112. *((uint8_t *)0x5405)=0xFF;//直接向LCD_PM1寄存器的地址写入数据
  113. *((uint8_t *)0x5406)=0xFF;//直接向LCD_PM2寄存器的地址写入数据
  114. //----To set contrast to mean value----   
  115. LCD_CR2_CC0=0;//对比度
  116. LCD_CR2_CC1=1;
  117. LCD_CR2_CC2=0;
  118. /*  000: VLCD0  2.6V
  119.   001: VLCD1  2.7V
  120.   010: VLCD2  2.8V
  121.   011: VLCD3  2.9V
  122.   100: VLCD4  3.0V
  123.   101: VLCD5  3.1V
  124.   110: VLCD6  3.2V
  125.   111: VLCD7    */
  126.       
  127. //----Dead time 0----         
  128. LCD_CR3_DEAD0=0;//no dead time
  129. LCD_CR3_DEAD1=0;  
  130. LCD_CR3_DEAD2=0;
  131. //----LCD_PulseOnDuration_1----
  132. LCD_CR2_PON0=1; 
  133. LCD_CR2_PON1=0;  
  134. LCD_CR2_PON2=0;          
  135. /*  000: 0 CLKps pulses
  136.   001: 1 CLKps pulses
  137.   010: 2 CLKps pulses
  138.   011: 3 CLKps pulses
  139.   100: 4 CLKps pulses
  140.   101: 5 CLKps pulses
  141.   110: 6 CLKps pulses
  142.   111: 7 CLKps pulses  */
  143.       
  144. //----Enable LCD peripheral----        
  145. LCD_CR3_LCDEN=1;
  146. }
  147. /******************************************************************************************************
  148. *  名          称:LCD_DisplayNum(uint8_t number)
  149. *  功            能:控制段式液晶屏的数字显示部分
  150. *  入口参数:number:要显示的数字
  151. *  出口参数:无
  152. *  说          明:根据数字的长度,判断要显示的长度,长度大于6位,只显示后六位
  153. *  范          例:无
  154. ******************************************************************************************************/
  155. void LCD_DisplayNum(uint32_t number)
  156. {
  157. uint8_t cnts=0,tmp=0;
  158. if(number<10)cnts=1;
  159. else if(number<100)cnts=2;
  160. else if(number<1000)cnts=3;
  161. else if(number<10000)cnts=4;
  162. else if(number<100000)cnts=5;
  163. else if(number<(uint32_t) 1000000)cnts=6;
  164. else cnts=6;
  165. //判断需要显示数字的长度,确定在LCD屏上需要的位数
  166. switch(cnts)
  167. {
  168.   case 6:
  169.          tmp = LCD_Tab[number%1000000/100000];
  170.          ((tmp&m)==0)?(LCD_RAM0&=~0x02):(LCD_RAM0 |=0x02) ;
  171.          ((tmp&e)==0)?(LCD_RAM0&=~0x01):(LCD_RAM0 |=0x01) ;
  172.          ((tmp&g)==0)?(LCD_RAM2&=~0x80):(LCD_RAM2 |=0x80) ;
  173.          ((tmp&b)==0)?(LCD_RAM2&=~0x40):(LCD_RAM2 |=0x40) ;
  174.          ((tmp&f)==0)?(LCD_RAM6&=~0x08):(LCD_RAM6 |=0x08) ;
  175.          ((tmp&a)==0)?(LCD_RAM6&=~0x04):(LCD_RAM6 |=0x04) ;
  176.          ((tmp&c)==0)?(LCD_RAM3&=~0x20):(LCD_RAM3 |=0x20) ;
  177.          ((tmp&d)==0)?(LCD_RAM3&=~0x10):(LCD_RAM3 |=0x10) ;                      
  178.   case 5:
  179.          tmp = LCD_Tab[number%100000/10000];
  180.          ((tmp&m)==0)?(LCD_RAM0&=~0x08):(LCD_RAM0 |=0x08) ;
  181.          ((tmp&e)==0)?(LCD_RAM0&=~0x04):(LCD_RAM0 |=0x04) ;
  182.          ((tmp&g)==0)?(LCD_RAM2&=~0x20):(LCD_RAM2 |=0x20) ;
  183.          ((tmp&b)==0)?(LCD_RAM2&=~0x10):(LCD_RAM2 |=0x10) ;
  184.          ((tmp&f)==0)?(LCD_RAM6&=~0x02):(LCD_RAM6 |=0x02) ;
  185.          ((tmp&a)==0)?(LCD_RAM6&=~0x01):(LCD_RAM6 |=0x01) ;
  186.          ((tmp&c)==0)?(LCD_RAM3&=~0x80):(LCD_RAM3 |=0x80) ;
  187.          ((tmp&d)==0)?(LCD_RAM3&=~0x40):(LCD_RAM3 |=0x40) ;           
  188.          
  189.   case 4:
  190.          tmp = LCD_Tab[number%10000/1000];
  191.          ((tmp&m)==0)?(LCD_RAM0&=~0x20):(LCD_RAM0 |=0x20) ;
  192.          ((tmp&e)==0)?(LCD_RAM0&=~0x10):(LCD_RAM0 |=0x10) ;
  193.          ((tmp&g)==0)?(LCD_RAM2&=~0x08):(LCD_RAM2 |=0x08) ;
  194.          ((tmp&b)==0)?(LCD_RAM2&=~0x04):(LCD_RAM2 |=0x04) ;
  195.          ((tmp&f)==0)?(LCD_RAM5&=~0x80):(LCD_RAM5 |=0x80) ;
  196.          ((tmp&a)==0)?(LCD_RAM5&=~0x40):(LCD_RAM5 |=0x40) ;
  197.          ((tmp&c)==0)?(LCD_RAM4&=~0x02):(LCD_RAM4 |=0x02) ;
  198.          ((tmp&d)==0)?(LCD_RAM4&=~0x01):(LCD_RAM4 |=0x01) ;           
  199.   case 3:
  200.          tmp = LCD_Tab[number%1000/100];
  201.          ((tmp&m)==0)?(LCD_RAM0&=~0x80):(LCD_RAM0 |=0x80) ;
  202.          ((tmp&e)==0)?(LCD_RAM0&=~0x40):(LCD_RAM0 |=0x40) ;
  203.          ((tmp&g)==0)?(LCD_RAM2&=~0x02):(LCD_RAM2 |=0x02) ;
  204.          ((tmp&b)==0)?(LCD_RAM2&=~0x01):(LCD_RAM2 |=0x01) ;
  205.          ((tmp&f)==0)?(LCD_RAM5&=~0x20):(LCD_RAM5 |=0x20) ;
  206.          ((tmp&a)==0)?(LCD_RAM5&=~0x10):(LCD_RAM5 |=0x10) ;
  207.          ((tmp&c)==0)?(LCD_RAM4&=~0x08):(LCD_RAM4 |=0x08) ;
  208.          ((tmp&d)==0)?(LCD_RAM4&=~0x04):(LCD_RAM4 |=0x04) ;
  209.  case 2:
  210.          tmp = LCD_Tab[number%100/10];
  211.          ((tmp&m)==0)?(LCD_RAM1&=~0x02):(LCD_RAM1 |=0x02) ;
  212.          ((tmp&e)==0)?(LCD_RAM1&=~0x01):(LCD_RAM1 |=0x01) ;
  213.          ((tmp&g)==0)?(LCD_RAM1&=~0x80):(LCD_RAM1 |=0x80) ;
  214.          ((tmp&b)==0)?(LCD_RAM1&=~0x40):(LCD_RAM1 |=0x40) ;
  215.          ((tmp&f)==0)?(LCD_RAM5&=~0x08):(LCD_RAM5 |=0x08) ;
  216.          ((tmp&a)==0)?(LCD_RAM5&=~0x04):(LCD_RAM5 |=0x04) ;
  217.          ((tmp&c)==0)?(LCD_RAM4&=~0x20):(LCD_RAM4 |=0x20) ;
  218.          ((tmp&d)==0)?(LCD_RAM4&=~0x10):(LCD_RAM4 |=0x10) ;
  219.  case 1: 
  220.          tmp = LCD_Tab[number%10];
  221.          ((tmp&m)==0)?(LCD_RAM1&=~0x08):(LCD_RAM1 |=0x08) ;
  222.          ((tmp&e)==0)?(LCD_RAM1&=~0x04):(LCD_RAM1 |=0x04) ;
  223.          ((tmp&g)==0)?(LCD_RAM1&=~0x20):(LCD_RAM1 |=0x20) ;
  224.          ((tmp&b)==0)?(LCD_RAM1&=~0x10):(LCD_RAM1 |=0x10) ;
  225.          ((tmp&f)==0)?(LCD_RAM5&=~0x02):(LCD_RAM5 |=0x02) ;
  226.          ((tmp&a)==0)?(LCD_RAM5&=~0x01):(LCD_RAM5 |=0x01) ;
  227.          ((tmp&c)==0)?(LCD_RAM4&=~0x80):(LCD_RAM4 |=0x80) ;
  228.          ((tmp&d)==0)?(LCD_RAM4&=~0x40):(LCD_RAM4 |=0x40) ;
  229.   break;
  230.   default:break;
  231. }
  232. }
  233. void main(void)
  234. {
  235. LCD_Config();
  236. LCD_DisplayNum(201609);
  237. //  asm("rim");               //enable interrupts
  238. while(1)
  239. {
  240.   asm("wfi");
  241. }
  242. }

复制代码

分类:

技术点:

相关文章:

  • 2021-11-30
  • 2021-10-30
  • 2021-08-01
  • 2021-06-12
  • 2022-01-22
  • 2021-09-11
  • 2022-12-23
  • 2021-04-20
猜你喜欢
  • 2021-08-30
  • 2021-06-03
  • 2021-12-13
  • 2021-09-30
  • 2021-08-31
  • 2022-12-23
  • 2021-04-19
相关资源
相似解决方案