STM8L的LCD接口詳解及驅動程序

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驅動程序,提供一個能夠在液晶屏上最多顯示六位數字的接口的程序,讀者能夠調用此程序,顯示任意六位之內的數字.

ios

  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.   
  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.   
  69. //----設置RTC時鐘分頻值----
  70.   CLK_CRTCR_RTCDIV0=0;
  71.   CLK_CRTCR_RTCDIV1=0;
  72.   CLK_CRTCR_RTCDIV2=0;
  73. /*000: RTC clock source/1
  74.   001: RTC clock source /2
  75.   010: RTC clock source /4
  76.   011: RTC clock source /8
  77.   100: RTC clock source /16
  78.   101: RTC clock source /32
  79.   110: RTC clock source /64
  80.   111: RTC clock source /128*/
  81.   
  82. //----設置LCD預分頻值----  
  83.   LCD_FRQ_PS0=0;// 2^PS[3:0]
  84.   LCD_FRQ_PS1=0;//分頻值爲1
  85.   LCD_FRQ_PS2=0;
  86.   LCD_FRQ_PS3=0;
  87.   
  88. //----設置LCD分頻值----  
  89.   LCD_FRQ_DIV0=1;//DIV[3:0]+16
  90.   LCD_FRQ_DIV1=1;//分頻值爲15+16=31
  91.   LCD_FRQ_DIV2=1;
  92.   LCD_FRQ_DIV3=1;  
  93. //以上分頻值的設置,最爲了獲得適合的LCD的刷新頻率,若是增大分頻值,會致使
  94. //LCD刷新頻率變低,會看到LCD顯示出現閃爍
  95. //好比,咱們將PS[3:0]設置爲0011,會看到液晶閃爍  
  96.   
  97. //----1/4 duty----  
  98.   LCD_CR1_DUTY0=1;//1/4 duty
  99.   LCD_CR1_DUTY1=1;
  100. /* Duty ratio selection
  101.    00: Static duty
  102.    01: 1/2 duty
  103.    10: 1/3 duty
  104.    11: 1/4 duty      */
  105. //----1/3 bias----     
  106.   LCD_CR1_B2=0;//1/3 bias
  107. /* 0: 1/3 bias
  108.    1: 1/2 bias  */
  109. //----內部電壓源----   
  110.   LCD_CR2_VSEL=0;
  111.   
  112. //----打開引腳的SEG功能----     
  113. // LCD_PM0=0xFF;//頭文件這個地方定義錯誤,沒法直接向LCD_PM0寫入數據
  114. // LCD_PM1=0xFF;//PM0寄存器定義錯誤,致使PM1也沒法直接寫入
  115. // LCD_PM2=0xFF;//PM0寄存器定義錯誤,致使PM2也沒法直接寫入
  116.   *((uint8_t *)0x5404)=0xFF;//直接向LCD_PM0寄存器的地址寫入數據
  117.   *((uint8_t *)0x5405)=0xFF;//直接向LCD_PM1寄存器的地址寫入數據
  118.   *((uint8_t *)0x5406)=0xFF;//直接向LCD_PM2寄存器的地址寫入數據
  119.   
  120. //----To set contrast to mean value----   
  121.   LCD_CR2_CC0=0;//對比度
  122.   LCD_CR2_CC1=1;
  123.   LCD_CR2_CC2=0;
  124. /*  000: VLCD0  2.6V
  125.     001: VLCD1  2.7V
  126.     010: VLCD2  2.8V
  127.     011: VLCD3  2.9V
  128.     100: VLCD4  3.0V
  129.     101: VLCD5  3.1V
  130.     110: VLCD6  3.2V
  131.     111: VLCD7    */
  132.         
  133. //----Dead time 0----         
  134.   LCD_CR3_DEAD0=0;//no dead time
  135.   LCD_CR3_DEAD1=0;  
  136.   LCD_CR3_DEAD2=0;
  137. //----LCD_PulseOnDuration_1----
  138.   LCD_CR2_PON0=1; 
  139.   LCD_CR2_PON1=0;  
  140.   LCD_CR2_PON2=0;          
  141. /*  000: 0 CLKps pulses
  142.     001: 1 CLKps pulses
  143.     010: 2 CLKps pulses
  144.     011: 3 CLKps pulses
  145.     100: 4 CLKps pulses
  146.     101: 5 CLKps pulses
  147.     110: 6 CLKps pulses
  148.     111: 7 CLKps pulses  */
  149.         
  150. //----Enable LCD peripheral----        
  151.   LCD_CR3_LCDEN=1;
  152. }
  153. /******************************************************************************************************
  154. *  名          稱:LCD_DisplayNum(uint8_t number)
  155. *  功            能:控制段式液晶屏的數字顯示部分
  156. *  入口參數:number:要顯示的數字
  157. *  出口參數:無
  158. *  說          明:根據數字的長度,判斷要顯示的長度,長度大於6位,只顯示後六位
  159. *  範          例:無
  160. ******************************************************************************************************/
  161. void LCD_DisplayNum(uint32_t number)
  162. {
  163.   uint8_t cnts=0,tmp=0;
  164.   
  165.   if(number<10)cnts=1;
  166.   else if(number<100)cnts=2;
  167.   else if(number<1000)cnts=3;
  168.   else if(number<10000)cnts=4;
  169.   else if(number<100000)cnts=5;
  170.   else if(number<(uint32_t) 1000000)cnts=6;
  171.   else cnts=6;
  172.   //判斷須要顯示數字的長度,肯定在LCD屏上須要的位數
  173.   switch(cnts)
  174.   {
  175.     case 6:
  176.            tmp = LCD_Tab[number%1000000/100000];
  177.            ((tmp&m)==0)?(LCD_RAM0&=~0x02):(LCD_RAM0 |=0x02) ;
  178.            ((tmp&e)==0)?(LCD_RAM0&=~0x01):(LCD_RAM0 |=0x01) ;
  179.            ((tmp&g)==0)?(LCD_RAM2&=~0x80):(LCD_RAM2 |=0x80) ;
  180.            ((tmp&b)==0)?(LCD_RAM2&=~0x40):(LCD_RAM2 |=0x40) ;
  181.            ((tmp&f)==0)?(LCD_RAM6&=~0x08):(LCD_RAM6 |=0x08) ;
  182.            ((tmp&a)==0)?(LCD_RAM6&=~0x04):(LCD_RAM6 |=0x04) ;
  183.            ((tmp&c)==0)?(LCD_RAM3&=~0x20):(LCD_RAM3 |=0x20) ;
  184.            ((tmp&d)==0)?(LCD_RAM3&=~0x10):(LCD_RAM3 |=0x10) ;                      
  185.     case 5:
  186.            tmp = LCD_Tab[number%100000/10000];
  187.            ((tmp&m)==0)?(LCD_RAM0&=~0x08):(LCD_RAM0 |=0x08) ;
  188.            ((tmp&e)==0)?(LCD_RAM0&=~0x04):(LCD_RAM0 |=0x04) ;
  189.            ((tmp&g)==0)?(LCD_RAM2&=~0x20):(LCD_RAM2 |=0x20) ;
  190.            ((tmp&b)==0)?(LCD_RAM2&=~0x10):(LCD_RAM2 |=0x10) ;
  191.            ((tmp&f)==0)?(LCD_RAM6&=~0x02):(LCD_RAM6 |=0x02) ;
  192.            ((tmp&a)==0)?(LCD_RAM6&=~0x01):(LCD_RAM6 |=0x01) ;
  193.            ((tmp&c)==0)?(LCD_RAM3&=~0x80):(LCD_RAM3 |=0x80) ;
  194.            ((tmp&d)==0)?(LCD_RAM3&=~0x40):(LCD_RAM3 |=0x40) ;           
  195.            
  196.     case 4:
  197.            tmp = LCD_Tab[number%10000/1000];
  198.            ((tmp&m)==0)?(LCD_RAM0&=~0x20):(LCD_RAM0 |=0x20) ;
  199.            ((tmp&e)==0)?(LCD_RAM0&=~0x10):(LCD_RAM0 |=0x10) ;
  200.            ((tmp&g)==0)?(LCD_RAM2&=~0x08):(LCD_RAM2 |=0x08) ;
  201.            ((tmp&b)==0)?(LCD_RAM2&=~0x04):(LCD_RAM2 |=0x04) ;
  202.            ((tmp&f)==0)?(LCD_RAM5&=~0x80):(LCD_RAM5 |=0x80) ;
  203.            ((tmp&a)==0)?(LCD_RAM5&=~0x40):(LCD_RAM5 |=0x40) ;
  204.            ((tmp&c)==0)?(LCD_RAM4&=~0x02):(LCD_RAM4 |=0x02) ;
  205.            ((tmp&d)==0)?(LCD_RAM4&=~0x01):(LCD_RAM4 |=0x01) ;           
  206.     case 3:
  207.            tmp = LCD_Tab[number%1000/100];
  208.            ((tmp&m)==0)?(LCD_RAM0&=~0x80):(LCD_RAM0 |=0x80) ;
  209.            ((tmp&e)==0)?(LCD_RAM0&=~0x40):(LCD_RAM0 |=0x40) ;
  210.            ((tmp&g)==0)?(LCD_RAM2&=~0x02):(LCD_RAM2 |=0x02) ;
  211.            ((tmp&b)==0)?(LCD_RAM2&=~0x01):(LCD_RAM2 |=0x01) ;
  212.            ((tmp&f)==0)?(LCD_RAM5&=~0x20):(LCD_RAM5 |=0x20) ;
  213.            ((tmp&a)==0)?(LCD_RAM5&=~0x10):(LCD_RAM5 |=0x10) ;
  214.            ((tmp&c)==0)?(LCD_RAM4&=~0x08):(LCD_RAM4 |=0x08) ;
  215.            ((tmp&d)==0)?(LCD_RAM4&=~0x04):(LCD_RAM4 |=0x04) ;
  216.    case 2:
  217.            tmp = LCD_Tab[number%100/10];
  218.            ((tmp&m)==0)?(LCD_RAM1&=~0x02):(LCD_RAM1 |=0x02) ;
  219.            ((tmp&e)==0)?(LCD_RAM1&=~0x01):(LCD_RAM1 |=0x01) ;
  220.            ((tmp&g)==0)?(LCD_RAM1&=~0x80):(LCD_RAM1 |=0x80) ;
  221.            ((tmp&b)==0)?(LCD_RAM1&=~0x40):(LCD_RAM1 |=0x40) ;
  222.            ((tmp&f)==0)?(LCD_RAM5&=~0x08):(LCD_RAM5 |=0x08) ;
  223.            ((tmp&a)==0)?(LCD_RAM5&=~0x04):(LCD_RAM5 |=0x04) ;
  224.            ((tmp&c)==0)?(LCD_RAM4&=~0x20):(LCD_RAM4 |=0x20) ;
  225.            ((tmp&d)==0)?(LCD_RAM4&=~0x10):(LCD_RAM4 |=0x10) ;
  226.    case 1: 
  227.            tmp = LCD_Tab[number%10];
  228.            ((tmp&m)==0)?(LCD_RAM1&=~0x08):(LCD_RAM1 |=0x08) ;
  229.            ((tmp&e)==0)?(LCD_RAM1&=~0x04):(LCD_RAM1 |=0x04) ;
  230.            ((tmp&g)==0)?(LCD_RAM1&=~0x20):(LCD_RAM1 |=0x20) ;
  231.            ((tmp&b)==0)?(LCD_RAM1&=~0x10):(LCD_RAM1 |=0x10) ;
  232.            ((tmp&f)==0)?(LCD_RAM5&=~0x02):(LCD_RAM5 |=0x02) ;
  233.            ((tmp&a)==0)?(LCD_RAM5&=~0x01):(LCD_RAM5 |=0x01) ;
  234.            ((tmp&c)==0)?(LCD_RAM4&=~0x80):(LCD_RAM4 |=0x80) ;
  235.            ((tmp&d)==0)?(LCD_RAM4&=~0x40):(LCD_RAM4 |=0x40) ;
  236.     break;
  237.     default:break;
  238.   }
  239. }
  240. void main(void)
  241. {
  242.   LCD_Config();
  243.   LCD_DisplayNum(201609);
  244. //  asm("rim");               //enable interrupts
  245.   while(1)
  246.   {
  247.     asm("wfi");
  248.   }
  249. }
複製代碼
相關文章
相關標籤/搜索