[STM8L]TAB段式LCD液晶驱动程序

发布者:平章大人最新更新时间:2017-02-24 来源: eefocus关键字:STM8L  TAB段式  LCD液晶  驱动程序 手机看文章 扫描二维码
随时随地手机看文章

   STM8L152XX系列带有片上段式LCD驱动程序,这为低成本应用和高密度系统设计提供了保证,利用片上LCD驱动模块,可以有效的控制系统整体功耗,简化系统结构,从整体来说可靠性得到提高。

    此处不介绍LCD驱动模块的原理以及驱动时序,请参考STM8原版英文说明文档,已描述的很详细,以下介绍其寄存器的配置方法以及编程方法。

    时钟,系统时钟同样用来产生LCD驱动时钟,通过时钟模块配置:

    CLK_PCKENR2|=S3;   //LCD        使能LCD模块时钟

    CLK_CRTCR=S7|S6|S5|S1;    //RTC&LCD->FCLK/128      注意RTC和LCD是共同一路时钟

    以上配置根据实际时钟进行调整,我在此处采用FCLK=HSI=16MHZ,所以LCDclk=16M/128=125KHZ

我的LCD为六个数字的段式LCD,1/3偏压方式,4根COM线,12根COM线,这两个参数请读者自己查找自己的LCD资料找到,对于驱动LCD来说这两个参数最重要,以下为寄存器配置:


  1. LCD_CR1=S5|S2|S1;                   //1/3偏压   1/4占空比  

  2. LCD_CR2=S6|S4|S0;                   //3.3V    

  3. LCD_FRQ=5<<4;                     //FCK=125000/2^5*16=128000/512=244 Frame=244/4=61HZ  

  4. LCD_PM0=0xFF;  

  5. LCD_PM1=0x0F;     

  6. LCD_CR3|=S6;  

    首先由偏压方式决定了驱动到LCD段码上的电压种类,占空比(标准并非如此翻译)Duty值决定扫过每根COM线的时序比例,由于我将VLCD与VCC接在一起了,所以选择外部电源参考3.3V,若选择内部,则可以进一步选择最高输出电压大小,实测发现选大些对比度可提高一些。LCD_FRQ用于配置扫描更新频率,具体计算不想说,文档里都有。最后是配置那些接在LCD上的COM线和SEG线为LCD驱动复用有效模式,否则仍可以作为IO口使用,最后开启LCD驱动模块扫描。

    配置完以上寄存器之后,LCD模块已开始工作,它是通过从LCD_RAM0-LCD_RAM12这一组寄存器来控制显示内容的,这时向LCD_RAM0-LCD_RAM12写入数据会发现有段码显示在LCD上,作为应用层,需要找到这种关系。

   查手里这块LCD资料列出段码表如下所示:


  1. /*-----------------------------------------------------  

  2. SEG:  0  1  2  3  4  5  6  7  8  9  10 11  

  3.       1D X2 2D X3 3D  X1 4D 4P 5D 5P 6D 6P  

  4.       1E 1C 2E 2C 3E  3C 4E 4C 5E 5C 6E 6C  

  5.       1G 1B 2G 2B 3G  3B 4G 4B 5G 5B 6G 6B  

  6.       1F 1A 2F 2A 3F  3A 4F 4A 5F 5A 6F 6A  


  1. CODE: A  F  B  G  C  E  P  D  

  2. -----------------------------------------------------*/  


  1. 于是我把一个字节最高位至最低位从A段到D段按如上CODE顺序进行排列,并得到段表码如下:  


  1. const uint8 LCD_CodeTable[]={0xED,0x28,0xB5,0xB9,0x78,0xD9,0xDD,0xA8,0xFD,0xF9,0xFC,0x5D,0x15,0x3D,0xD5,0xD4,0x5C,0x10,0xC5,0xA9,0x00};   这些段码表分别对应于以下字符:0,1,2,3,4,5,6,7,8,9,A,b,c,d,E,F,h,-,[,],   [注,最后一个为空格]   为编程方便,我对字符进行编码:A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U  [依次和上面的字符相对应]   为六个字符定义显示内容缓冲区:uint8 LCD_DisplayBuffer[6];void LCD_SetSegValue(void)  

  2. {  

  3.  uint16 T,SEG[4];  

  4.  uint8 i,j,Code[6];  

  5.  for(i=0;i<6;i++){  

  6.   Code[5-i]=LCD_CodeTable[LCD_DisplayBuffer[i]&0x7F];  

  7.   if(LCD_DisplayBuffer[i]&0x80)Code[5-i]|=0x02;  

  8.  }  

  9.  for(i=0;i<4;i++){  

  10.   for(T=0,j=0;j<6;j++){  

  11.    T<<=2;  

  12.    T|=(Code[j]&0x03);  

  13.    Code[j]>>=2;  

  14.   }    

  15.   SEG[i]=T;  

  16.  }  

  17.  LCD_RAM0=(uint8)(SEG[0]);      //COM0->B[7:0]  

  18.  LCD_RAM1=(uint8)(SEG[0]>>8);    //COM0->B[11:8]  

  19.  LCD_RAM3=(uint8)(SEG[1]<<4);    //COM1->B[3:0]->H  

  20.  LCD_RAM4=(uint8)(SEG[1]>>4);    //COM1->B[11:4]  

  21.  LCD_RAM7=(uint8)(SEG[2]);      //COM2->B[7:0]  

  22.  LCD_RAM8=(uint8)(SEG[2]>>8);    //COM2->B[11:8]  

  23.  LCD_RAM10=(uint8)(SEG[3]<<4);    //COM3->B[3:0]->H  

  24.  LCD_RAM11=(uint8)(SEG[3]>>4);    //CoM3->B[11:4]  

  25. }   

  26.   

  27.     以上这段程序将LCD_DisplayBuffer[]中的六个字符解码后写入LCD模块的显示缓冲区中,最终显示成相应字符,这其中用每个字符的最高位代表是否含有小数点位,若为高则点亮相当的小数点,否则关闭。至于LCD_RAM的更新和拆分方法,此外不再描述,文档中已相当详细。

      

  28.     围绕以上刷新程序,可得到如下常用方法:

      

  29. //清显示  

  30. void LCD_Clear(uint8 Index)  

  31. {  

  32.     uint8 i;  

  33.     if(Index==0xFF)for(i=0;i<6;i++)LCD_DisplayBuffer[i]='U'-'A';  

  34.     else LCD_DisplayBuffer[Index]='U'-'A';  

  35.     LCD_SetSegValue();  

  36. }  

  37.   

  38. //写显示缓冲区点  

  39. void LCD_ShowSpecial(uint8 Saddr,uint8 Char)  

  40. {  

  41.     if(Char>0)LCD_DisplayBuffer[Saddr]|=0x80;  

  42.     else      LCD_DisplayBuffer[Saddr]&=0x7F;  

  43. }  

  44.   

  45. //显示字符  

  46. void LCD_ShowChar(uint8 Saddr,uint8 Char)  

  47. {  

  48.     LCD_DisplayBuffer[Saddr]&=0x80;  

  49.     LCD_DisplayBuffer[Saddr]|=Char;  

  50.     LCD_SetSegValue();  

  51. }  

  52.   

  53. //显示字符串  

  54. void LCD_ShowString(uint8 Saddr,void *Text)  

  55. {  

  56.     uint8 T,P,*Str;  

  57.     Str=(uint8 *)Text;  

  58.     while(*Str>0){  

  59.         T=*Str++;  

  60.         P=LCD_DisplayBuffer[Saddr];  

  61.         LCD_DisplayBuffer[Saddr++]=(P&0x80)|(T-'A');  

  62.     }  

  63.     LCD_SetSegValue();  

  64. }  

  65.   

  66. //显示数字  

  67. void LCD_ShowNumber(uint8 Saddr,uint16 Number,uint8 Length)  

  68. {  

  69.     uint8 P;  

  70.     Saddr+=Length-1;  

  71.     while(Length--){  

  72.             P=LCD_DisplayBuffer[Saddr];  

  73.             LCD_DisplayBuffer[Saddr]=(P&0x80)|(Number%10);  

  74.             Saddr--;Number/=10;           

  75.     }  

  76.     LCD_SetSegValue();  

  77. }  

  78.   


  79.   

  80.     由以上函数库,可以方便的显示出如LCD_ShowString(0,"BCDEF")(显示“12345"),LCD_ShowNumber(0,1244,4)(显示"1244"),等等。配合一些简单的数据结构,便可得到一个相对复杂点的菜单操作界面。

      

  81.   

  82.  

      

  83.   

  84.      


关键字:STM8L  TAB段式  LCD液晶  驱动程序 引用地址:[STM8L]TAB段式LCD液晶驱动程序

上一篇:单片机参数处理[保存与读取]
下一篇:[STM8L]EEPROM操作读与写

推荐阅读最新更新时间:2024-03-16 15:34

NT下视频采集及解压驱动程序的设计与实现
    摘要: 分析了多媒体设备驱动程序的体系结构及视频采集与解压卡的驱动程序设计方案。描述了核心态驱动程序的处理流程,提供了用户态驱动程序的设计思路和具体算法。     关键词: 驱动程序 IRP(输入输出请求包) 驱动程序对象 设备对象 Windows NT的结构决定了应用程序不能直接操作硬件设备,它只能通过一个中间层来读写和控制设备,这个中间层就是驱动程序。驱动程序位于计算机软件的最低层(HAL 为硬件抽象层),直接与硬件设备的特性联系在一起。编写驱动程序不仅要了解设备的特性,而且还要了解操作系统的结构,难度较大。本文比较详细地分析了视频采集与解压卡的驱动程序设计思路。 1 视频
[应用]
基于驱动程序
    摘要: 介绍一种集计算机、网络、射频卡技术于一体的“一卡通”邮政综合服务系统。邮政客户只需持一张射频卡,即可在邮政营业厅获得各种邮政服务。给出了系统的总体方案,营业厅局域网软、硬件与功能模块设计,以及确保安全、保密等指标的技术措施。     关键词: 邮政业务  网络  射频卡  邮政业务自动化     随着电信业务与邮政业务的分离,邮政已开始自食其力。提高工作效率、降低营业成本是邮政事业走向兴旺发达的重要方面。邮政业虽然已应用一些新技术手段开通了若干新服务项目,如邮政储蓄的异地存取等,带来了一定的经济和社会效益,但综观整个邮政服务的全过程,可以迅速应用现代化技术之处比比皆是。一卡通邮政综合服务系统
[网络通信]
1602LCD液晶+DS18B20实现数字电子钟
呵呵,我终于按照自己的想法实现了功能比较完善的数字电子钟了 液晶显示内容: 2012-02-02 14'C //第1行 00:20:38 Thurs //第2行 这个时钟表 既可以显示温度,又可以显示 当前日期是星期几了。 这个星期几的判断方法就是根据一个 国际日历公式来实现的。 实现功能: 1. 调整 年月日 时分 2. 显示 当前周围温度 3. 显示 当前日期的 是星期几 4. 整点报时 5. 若调整时间 不合理, 比如2012-02-34 ,则 调整失效 6. 若调整时间,则可以放弃所调整的时候。
[单片机]
MEGA8单片机驱动LCD1602液晶
个头文件,搞了好久都没成功!都快到心灰意冷的边缘了,突然灵光一闪:会不会是mega8的Flash不行了?这片mega8陪伴了我好几年,也应该退休了。抱着试试看的想法换了一片新的mega8,一切ok!自己觉得奇怪,之前在烧程序时,并没有报错啊? 调试过程总结一下: 1)由于找不到的1620资料,不知道它的操作时序。看到一些帖子说1620和1602没区别,还是有点将信将疑。后面用网友编写的1602程序试验,才知道它们俩没啥区别 2)关于是否检测LCD处于空闲,觉得还是最好在写指令和写数据时都加上。不检测,会导致显示结果不正常。 3)由于连线很多14根(加上背光就是16根),如果有一根除了问题就会影响到显示。所以我是用万用表一根线一根线
[单片机]
嵌入式系统开发中五个设计驱动程序的方法
一个 嵌入式 应用软件都会在某些时候访问最底层的固件和进行一些硬件控制。驱动的设计和实施是确保一个系统能够满足其实时性要求的关键。以下5个窍门是每一个开发者在设计驱动程序时应该考虑的,跟随我看看这些设计方法。下面就随嵌入式小编一起来了解一下相关内容吧。 1.使用设计模式 设计模式是一个用来处理那些在软件中会重复出现的问题的解决方案。开发人员可以选择浪费宝贵的时间和预算从无到有地重新发明一个解决方案,也可以从他的解决方案工具箱中选择一个最适合解决这个问题的方案。在微处理器出现之初,底层驱动已经很成熟了,那么,为什么不利用现有的成熟的解决方案呢? 驱动程序设计模式大致分属以下4个类别:Bit bang、轮询、中断驱动和直接存储器
[嵌入式]
LCD12864 液晶显示器 模块化程序
/********************** lcd12864.h 头文件 **********************/ #ifndef _LCD12864_H_ #define _LCD12864_H_ extern void lcd12864_busy(); //忙标志函数 extern void led12864_clear();//清屏 extern void lcd12864_init(); //初始化函数 extern void lcd12864_pxy(unsigned char p,unsigned char x,unsigned char y);//数据的显示位置,p=0左半屏,p=1右半屏,p
[单片机]
<font color='red'>LCD</font>12864 <font color='red'>液晶</font>显示器 模块化程序
STM8L编程问题之segment .text size overflow
#error clnk Debugsolar_charger.lkf:1 segment .text size overflow,提示代码段溢出,此时因为使用STM8L的固件库,造成一些不必要的函数被编译,可以尝试注释掉一些不必要的函数;如果已经没有可以注释的函数,可以尝试在project setting中,选择代码优化,压缩代码。 遇到最多的莫过于使用库的时候,提示代码超过内存范围。 代码量并不多,但是编译器却明明白白的提示代码超过内存范围,为什么会这样? 主要原因,在于库文件中为了做好错误处理,中间添加了assert代码。同时也由于为了将所有功能函数都提供出来,中间有很多用不到的函数,但是在STM8L中,这些没有用
[单片机]
AD9850驱动程序--MSP430版本详解
前段时间忙着画板子搞运放搞滤波了,程序更新的少,发现MSP430不是太好用,尤其Timer,不过也与我使用内部晶振有关,产生正玄波之前用MSP430发出PWM,再进行滤波变为正弦波太麻烦了,这次改用DDS芯片,今天板子回来一会就调了出来很方便。 AD9850为一款DDS芯片,这里不做什么详细介绍了,有两种接口:serial 和 parrel,两种接口驱动均完成 1 /* 2 * AD9850.h 3 * 4 * Created on: 2013-7-12 5 * Author: Allen 6 */ 7 8 #ifndef AD9850_H_ 9 #define AD9850_H_ 10 11 #include 12 #inc
[嵌入式]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved