基于uCOSⅡ的LCD驱动编写

基于uCOSⅡ的LCD驱动编写
基于uCOSⅡ的LCD驱动编写

天津电子信息职业技术学院

课程设计

课题名称基于uCOSⅡ的LCD驱动编写姓名王浩

学号35

班级电信S10-1

专业电子信息工程

成绩

完成日期2012-06-01

基于uCOSII的LCD驱动编写

摘要

LCD是嵌入式操作系统的重要组成部分,是系统和用户之间进行交互和信息交换的媒介,它实现信息的内部形式与人类可以接受形式之间的转换。用户可以只通过LCD监测系统内部运行状态,然后作出相应的处理。因而具有良好的人机界面的嵌入式操作系统能过很好的完成系统开发、生产生活的需要。

S3C44B0X 中具有内置的LCD 控制器,它能将显示缓存(在SDRAM存储器中)中的LCD 图像数据传输到外部的LCD驱动电路上的逻辑功能。它支持单色、4级、16级灰度LCD显示,以及256彩色LCD显示。在显示灰度时,它采用时间抖动算法(time-based dithering algorithm)和帧率控制 (Frame Rate Control)方法,在显示彩色时,它采用RGB的格式,即RED、GREEN、BLUE,三色混合调色。通过软件编程,可以实现233或332的RGB调色的格式。对于不同尺寸的LCD显示器,它们会有不同的垂直和水平象素点、不同的数据宽度、不同的接口时间及刷新率,通过对LCD 控制器中的相应寄存器写入不同的值,来配置不同的LCD 显示板。

LCD能够正常工作得益于软硬件的协同工作,S3C44B0X集成了LCD的控制器,即不带驱动电路的LCD显示模块,驱动程序需要根据用户需要来自行添加。

u C / O S 是一种免费公开源代码、结构小巧、具有可剥夺实时内核的实时操作系统,在具体应用中稳定可靠,并且支持uIP TCP/IP协议栈、ucGUI等,可扩展性强,功能强大。因此,在uC/OS II下写的LCD驱动具有较好的实时性和稳定性,功能强大。

关键词:嵌入式系统;LCD显示;驱动电路;

目录

一、系统设计 (4)

1.课题目标及总体方案 (4)

2.LCD驱动程序组成 (4)

3.UCOSII操作系统下添加LCD驱动程序 (5)

4.应用程序 (5)

二、实验结果测试 (6)

三、总结 (7)

四、心得体会 (8)

五、参考文献 (9)

六、附录 (9)

一、系统设计

1.课题目标及总体方案

首先学习了解LCD的驱动程序,然后在移植好的UCOSII项目中添加LCD的驱动程序, 最后能够在uCOSII下,编写LCD应用任务的简单编程实例,来检验LCD驱动程序的完好度。本实验实例为在LCD屏上显示跑马灯,同时模拟CPU板上D7、D8灯的交替闪烁,闪烁周期为跑马灯周期。

2.LCD驱动程序组成

LCD驱动程序的文件夹Gui(如图1所示),其中,包括四个文件夹:

图1

Font中存放的是字体文件,存放四个文件,Font_Cn12.c为调用汉字库12X12汉字的引用文件;Font_Cn16.c为调用汉字库16X16汉字的引用文件;Font8X16为调用ASCII码的源文件,它的大小为8X16;Gchar.c为显示字符的源程序库。

Glib中存放绘图的中层和上层的函数,上层函数是直接供用户调用的API,。Glib文件夹内存放两个文件,Glib.c是图形显示库的源代码,它主要实现LCD的中层和上层供用户调用的API函数,Glib.h则是供其他文件或自身调用的头文件。

Init中存放GUI初始化的函数,Init文件夹内存放两个文件,data.h是数据类型重定义的文件,GUI_Init.c是GUI系统的初始化文件。

Lcddriver中存放的是LCD的底层驱动函数,以及对LCD控制器的初始化函数。

Lcddriver文件内存放两个文件,Lcddriver.c包括LCD的底层读写内存用来绘图的函数,以及初始化LCD控制寄存器的初始化硬件的函数。Lcddrive是供其他文件或自身调用的头文件。

3.UCOSII操作系统下添加LCD驱动程序

在UCOSII操作系统下添加LCD驱动程序,也就是把整个GUI文件夹加入该项目里。

同时,还要在Application\INC目录下的config.h文件中,加入GUI程序的头文件,#include "..\..\Gui\Glib\Glib.h",这是为了在应用中方便调用画图的API函数。

如果,要在LCD上显示英文或汉字,还要在Application\SRC\Main.c中声明引用的是extern GUI_FONT CHINESE_FONT12;等外部定义过的字体。这样,编译就能通过,就把LCD 的驱动程序以及小型的GUI图形库,加载到了UCOSII操作系统上了。

在UCOSII操作系统下,要单独开辟一个GUI任务,进行画图,一般这个任务的优先级很低,一般它仅比空闲任务的优先级高,这样做是为了可以使更多的任务等级显示在屏上。

在Application/SRC下的MAIN.C文件,有GUI的应用任务,绘图的API函数即放在这里,或者作一个应用函数的文件,在此任务里调用。所有的对LCD显示操作内容要在MAIN.C 文件中编写。

4.应用程序

本实验实例为在LCD屏上显示跑马灯,同时模拟CPU板上D7、D8灯的交替闪烁,闪烁周期为跑马灯周期。来检验LCD驱动程序是否能正常工作。实验流程图如下:

程序开始先进行各项初始化,包括开发板、GUI初始化、系统初始化,然后配置LCD 屏幕设置,运行时先调用跑马灯延时程序Timedelay(),跑马灯运行一周后,置开发板上D7、D8灯亮灭,通过信号传递置LCD屏幕上模拟D7D8灯亮灭,接着调用Timedelay()函数,循环任务。

二、实验结果测试

测试方法:

①在移植好的UCOSII项目中添加LCD的驱动程序。(方法参见第一章第二节)

②在main.c文件中编写程序(源程序见附录),先使用画图函数绘出包含跑

马灯,模拟D7、D8两灯在内的LCD界,用函数timedelay()控制跑马灯

运行,timedelay()亦是延时函数。D7、D8两灯每交替闪说一次,调用

一次timedelay()延时函数。

③连接电脑和试验箱,编译程序,无错误,把程序下载到S3C44B0X,观察结

果。

④观察现象,有问题检查修改MAIN.C文件。

LCD界面显示如下:

图2

三、总结

实验结果显示出预期的LCD界面,LCD屏幕显示预定图案(如图2)。屏幕上D7、D8随CPU板上的D7,D8两灯同步闪烁,而且跑马灯每转一周,两个等交替闪烁一次。说明LCD驱动即添加到内核中没有问题,系统工作正常。

四、心得体会

课程设计完成了,在这个过程中我学到了很多东西。

我对嵌入式系统有了更加深入的了解,对书本上的知识也有了更加深刻的理解,对以前有些含糊不理解的地方也有了新的认识。学会使用嵌入式系统实现问题解决的一般过程,在UCOSII下,LCD驱动程序的结构,以及LCD驱动程序怎样添加道内核中去,也能够使用嵌入式系统设计制作一些简单实例。这次课程设计给我们理论联系实际的机会,书本上的东西很抽象,通过这次课程设计,能够把自己的想法和设计实现是一件很开心的事情,而依靠自己独立思考发现并解决一个问题也更是一件开心的事情。

课程设计中也遇到了许多问题,比如:老师给的参考程序并不能是LCD屏幕和CPU实验板上的灯同步闪烁,最后多次检查并和同学讨论才发现问题所在,问题程序代码如下:for(i=0;i<100000;i++);

rPCONB = 0x7cf;

rPDATB = 0x7ef;

for(i=0;i<100000;i++); //***问题所在****

{ 处理函数}

当设置CPU板D7、D8灯亮灭后,又通过for(i=0;i<100000;i++);延时一段时间,才去修改LCD屏幕上的LCD两个灯,当去掉第二行延时代码时,LCD屏幕模拟的灯泡和CPU实验板上的D7、D8等同步闪烁。

课程设计让我认识到个人的力量是渺小的,依靠一个人的努力也是不够的,许多事情只有靠大家精诚合作,一起思考讨论,分工协作,才能完成。大家之间要默契配合,相互理解,阐述各自对问题不同看法、不同理解的相互交流是发现问题学的新知的良好契机。

课程设计很快就结束了,我觉得最大的收获就是能够理论联系实际,把书本上的知识活学活用道实际中来解决一些实际问题,这样才能发挥用途。独立思考解决问题,并能够接受他人意见来修正完善自己的想法,最终付诸于实现。

五、参考文献

[1] 王永,何立民.嵌入式系统原理与设计[M].浙江:浙江大学出版社.

[2] Jean J. Labrosse著 ; 邵贝贝等译.嵌入式实时操作系统μC/OS-Ⅱ第2版[M] .北京:北京航空航天大学出版社.

六、附录

1.主函数

void Main(void)

{

Target_Init(); // ARMII实验系统的初始化,包括CPU板

GUI_Init();

OSInit(); // 操作系统的初始化

Send_D7light_Sem = OSSemCreate(0); //创建信号量

Send_LCD_Sem = OSSemCreate(0);

OSTaskCreate(Task_1, (void *)0, (OS_STK *)&Stack_Task_1[STACKSIZE - 1], 5);

OSTaskCreate(Task_2, (void *)0, (OS_STK *)&Stack_Task_2[STACKSIZE*3 - 1], 6);

OSSemPost(Send_LCD_Sem);

OSStart();

}

2.跑马灯闪烁程序(即延时程序)

void timedelay()

{

INT32U i,k ;

for(i=0;i<8;i++)

{

k=i%8;

switch(k)

{

case 0 : Set_Color(GUI_RED);

Fill_Circle (220, 80, 20); //跑马灯1 亮

Set_Color(GUI_GREEN);

Fill_Circle (262, 98, 20); //跑马灯2灭

Fill_Circle (280, 140, 20); //跑马灯3灭

Fill_Circle (262, 182, 20); //跑马灯4灭

Fill_Circle (220, 200, 20); //跑马灯5灭

Fill_Circle (178, 182, 20); //跑马灯6灭

Fill_Circle (160, 140, 20); //跑马灯7灭

Fill_Circle (178, 98, 20); //跑马灯8灭

break;

case 1 :{处理函数1};//省略,类似case 0处理函数

case 2 :{处理函数2};//省略,类似case 0处理函数

case 3 :{处理函数3};//省略,类似case 0处理函数

case 4 :{处理函数4};//省略,类似case 0处理函数

case 5 :{处理函数5};//省略,类似case 0处理函数

case 6 :{处理函数6};//省略,类似case 0处理函数

case 7 :{处理函数7};//省略,类似case 0处理函数}

}

}

3.控制CPU板上D7、D8和LCD模拟灯同步闪烁部分程序

for(;;)

{

OSSemPend(Send_D7light_Sem, 0, &err);

if(flag==0)

{

Set_Color(GUI_RED);

Fill_Circle(60, 160, 20); ///LCD模拟D7亮Set_Color(GUI_BLACK);

Fill_Circle(60, 100, 20);

flag = 1;

}

else

{

Set_Color(GUI_BLACK);

Fill_Circle(60, 160, 20); //LCD模拟D8亮

Set_Color(GUI_RED);

Fill_Circle(60, 100, 20);

flag = 0;

}

OSSemPost(Send_LCD_Sem);

}

void Task_1(void *pdata)

{

INT8U err;

INT32U flag=0;

Rtc_Tick_Init(); //打开时钟节拍,让操作系统跑起来

for(;;)

{

OSSemPend(Send_LCD_Sem, 0, &err);

if(flag==0)

{

timedelay(); //调用延时

rPCONB = 0x7cf;

rPDATB = 0x7ef; //CPU板上D7亮

flag = 1;

}

else

{

timedelay(); //调用延时

rPCONB = 0x7cf;

rPDATB = 0x7df; //CPU板上D8亮

flag = 0;

}

OSSemPost(Send_D7light_Sem);

}

}

TFT LCD液晶显示器的驱动原理

TFT LCD液晶显示器的驱动原理 我们针对feed through电压,以及二阶驱动的原理来做介绍.简单来说Feed through电压主要是由于面板上的寄生电容而产生的,而所谓三阶驱动的原理就是为了解决此一问题而发展出来的解决方式,不过我们这次只介绍二阶驱动,至于三阶驱动甚至是四阶驱动则留到下一次再介绍.在介绍feed through电压之前,我们先解释驱动系统中gate driver所送出波形的timing图. SVGA分辨率的二阶驱动波形 我们常见的1024*768分辨率的屏幕,就是我们通常称之为SVGA分辨率的屏幕.它的组成顾名思义就是以1024*768=786432个pixel来组成一个画面的数据.以液晶显示器来说,共需要1024*768*3个点(乘3是因为一个pixel需要蓝色,绿色,红色三个点来组成.)来显示一个画面.通常在面板的规划,把一个平面分成X-Y轴来说,在X轴上会有1024*3=3072列.这3072列就由8颗384输出channel的source driver 来负责推动.而在Y轴上,会有768行.这768行,就由3颗256输出channel的gate driver来负责驱动.图1就是SVGA分辨率的gate driver输出波形的timing图.图中gate 1 ~ 768分别代表着768个gate

driver的输出.以SVGA的分辨率,60Hz的画面更新频率来计算,一个frame的周期约为16.67 ms.对gate 1来说,它的启动时间周期一样为16.67ms.而在这16.67 ms之间,分别需要让gate 1 ~ 768共768条输出线,依序打开再关闭.所以分配到每条线打开的时间仅有16.67ms/768=21.7us而已.所以每一条gate d river打开的时间相对于整个frame是很短的,而在这短短的打开时间之内,source driver再将相对应的显示电极充电到所需的电压. 而所谓的二阶驱动就是指gate driver的输出电压仅有两种数值,一为打开电压,一为关闭电压.而对于common电压不变的驱动方式,不管何时何地,电压都是固定不动的.但是对于common电压变动的驱动方式,在每一个frame开始的第一条gate 1打开之前,就必须把电压改变一次.为什么要将这些输出电压的t iming介绍过一次呢?因为我们接下来要讨论的feed through电压,它的成因主要是因为面板上其它电压的变化,经由寄生电容或是储存电容,影响到显示电极电压的正确性.在LCD面板上主要的电压变化来源有3个,分别是gate driver电压变化,source driver电压变化,以及common电压变化.而这其中影响最大的就是gate driver电压变化(经由Cgd或是Cs),以及common电压变化(经由Clc或是Cs+Clc). Cs on common架构且common电压固定不动的feed through电压 我们刚才提到,造成有feed through电压的主因有两个.而在common电压固定不动的架构下,造成f eed through电压的主因就只有gate driver的电压变化了.在图2中,就是显示电极电压因为feed thro ugh电压影响,而造成电压变化的波形图.在图中,请注意到gate driver打开的时间,相对于每个frame 的时间比例是不正确的.在此我们是为了能仔细解释每个frame的动作,所以将gate driver打开的时间画的比较大.请记住,正确的gate driver打开时间是如同图1所示,需要在一个frame的时间内,依序将7

基于某STM32LCD12864驱动程序

STM32 LCD12864驱动程序(头文件)(2012-05-29 21:25:08)转载▼ 标签:杂谈 #ifndef LCD12864_H #define LCD12864_H #define LCD_CONTROL GPIOD //默认LCD12864的控制口在PD口 #define LCD_DATAPORT GPIOD //默认LCD12864的数据口在PD口 #define LCD_RESET_Pin GPIO_Pin_12 //默认LCD12864的复位引脚连接到PD.12 也可不用 #define LCD_RS_Pin GPIO_Pin_13 //默认LCD12864 RS -- PD.13 #define LCD_RW_Pin GPIO_Pin_14 //默认LCD12864 RW -- PD.14 #define LCD_EN_Pin GPIO_Pin_15 //默认LCD12864 E -- PD.15 #define LCD_CONTROL_CLOCK RCC_APB2Periph_GPIOD //默认LCD12864的控制口时钟 #define LCD_DATAPORT_CLOCK RCC_APB2Periph_GPIOD //默认LCD12864的数据口时钟 #define LCD_RS_1 LCD_CONTROL->BSRR &=~LCD_RS_Pin;LCD_CONTROL->BSRR |=LCD_RS_Pin //RS置高电平 #define LCD_RS_0 LCD_CONTROL->BRR &=~LCD_RS_Pin;LCD_CONTROL->BRR |=LCD_RS_Pin //RS置低电平 #define LCD_RW_1 LCD_CONTROL->BSRR &=~LCD_RW_Pin;LCD_CONTROL->BSRR |=LCD_RW_Pin //RW置高电平 #define LCD_RW_0 LCD_CONTROL->BRR &=~LCD_RW_Pin;LCD_CONTROL->BRR |=LCD_RW_Pin //RW置低电平 #define LCD_EN_1 LCD_CONTROL->BSRR &=~LCD_EN_Pin;LCD_CONTROL->BSRR |=LCD_EN_Pin //EN置高电平 #define LCD_EN_0 LCD_CONTROL->BRR &=~LCD_EN_Pin;LCD_CONTROL->BRR |=LCD_EN_Pin //EN置低电平 #define LCD_RESET_0 LCD_CONTROL->BRR = LCD_RESET_Pin // 复位 #define LCD_RESET_1 LCD_CONTROL->BSRR = LCD_RESET_Pin // 复位脚拉高 #define DATAOUT LCD_DATAPORT->ODR &=0xff00;LCD_DATAPORT->ODR // 数据输出寄存器 #define DATAIN LCD_DATAPORT->IDR // 数据输入寄存器 #define LCD_BF ((DATAIN)& 0x0080) // 忙状态 void LCD_delayus(unsigned long n); //延时n(us) void LCD_delayms(unsigned long n); //延时n(ms) void LCD_WriteInitcmd(uint8_t initcmd); //写初始化命令 void LCD_WaitLaisure(void); //一直等待到LCD内部操作完成,变为空闲状态 void LCD_Writecmd(uint8_t cmd); //写命令到LCD12864 void LCD_WriteByte(uint8_t byte); //写一字节数据到LCD12864 void LCD_pos(uint16_t pos); //LCD显示位置设置 void LCD_Setpos(uint16_t row,uint16_t col);//设定LCD12864的显示地址,根据习惯 void LCD_DispChar(char ch); //显示一个字符 void LCD_Setpos_DispChar(uint16_t row,uint16_t col,char ch);//在指定位置显示一个字符 void LCD_DispString(char str[]); //显示一个字符串,显示位置需提前设定

Linux的LCD驱动源码分析及移植

Linux的LCD驱动源码分析及移植(三部曲) 第一部分: 基于ARM9处理器的linux-2.6.32.2操作系统内核移植手记part5.1(LCD驱动源码分析及移植之platform device) 1.与LCD控制器硬件相关的寄存器内容请参照三星S3C2440A技术手册中的第15章。 2. LCD Controller的平台设备定义如下(文件位于linux/arch/arm/plat-s3c24xx/devs.c):

1./* LCD Controller */ 2. 3.static struct resource s3c_lcd_resource[] = { 4. [0] = { 5. .start = S3C24XX_PA_LCD, 6. .end = S3C24XX_PA_LCD + S3C24XX_SZ_LCD - 1, 7. .flags = IORESOURCE_MEM, 8. }, 9. [1] = { 10. .start = IRQ_LCD, 11. .end = IRQ_LCD, 12. .flags = IORESOURCE_IRQ, 13. } 14. 15.}; 16. 17.static u64 s3c_device_lcd_dmamask = 0xffffffffUL; 18. 19.struct platform_device s3c_device_lcd = { 20. .name = "s3c2410-lcd", 21. .id = -1, 22. .num_resources = ARRAY_SIZE(s3c_lcd_resource), 23. .resource = s3c_lcd_resource, 24. .dev = { 25. .dma_mask = &s3c_device_lcd_dmamask, 26. .coherent_dma_mask = 0xffffffffUL 27. } 28.}; 29. 30.EXPORT_SYMBOL(s3c_device_lcd); 平台设备的结构体定义为s3c_device_lcd,该设备在平台总线中的名字取为s3c2410-lcd,该平台设备申请的两个板级资源为以S3C24XX_PA_LCD为起始的IORESOURCE_MEM资源和一个定义为IRQ_LCD的IORESOURCE_IRQ资源。 其中, 1.#define S3C24XX_PA_LCD S3C2410_PA_LCD 1./* LCD controller */ 2.#define S3C2410_PA_LCD (0x4D000000) 3.#define S3C24XX_SZ_LCD SZ_1M 0x4D000000为LCDCON1寄存器的地址。

LED液晶显示器的驱动原理

LED液晶显示器的驱动原理 艾布纳科技有限公司 前两次跟大家介绍有关液晶显示器操作的基本原理, 那是针对液晶本身的特性,与TFT LCD 本身结构上的操作原理来做介绍. 这次我们针对TFT LCD 的整体系统面来做介绍, 也就是对其驱动原理来做介绍, 而其驱动原理仍然因为一些架构上差异的关系, 而有所不同. 首先我们来介绍由于Cs(storage capacitor)储存电容架构不同, 所形成不同驱动系统架构的原理. Cs(storage capacitor)储存电容的架构 一般最常见的储存电容架构有两种, 分别是Cs on gate与Cs on common这两种. 这两种顾名思义就可以知道, 它的主要差别就在于储存电容是利用gate走线或是common走线来完成的. 在上一篇文章中, 我曾提到, 储存电容主要是为了让充好电的电压,能保持到下一次更新画面的时候之用. 所以我们就必须像在CMOS的制程之 中, 利用不同层的走线, 来形成平行板电容. 而在TFT LCD的制程之中, 则是利用显示电极与gate走线或是common走线,所形成的平行板电容,来制作出储存电容Cs. For personal use only in study and research; not for commercial use

图1就是这两种储存电容架构, 从图中我们可以很明显的知道, Cs on gate由于不必像Cs on common一样, 需要增加一条额外的common走线, 所以它的开口率(Aperture ratio)会比较大. 而开口率的大小, 是影响面板的亮度与设计的重要因 素. 所以现今面板的设计大多使用Cs on gate的方式. 但是由于Cs on gate的方 式, 它的储存电容是由下一条的gate走线与显示电极之间形成的.(请见图2的Cs on gate与Cs on common的等效电路) 而gate走线, 顾名思义就是接到每一个TFT 的gate端的走线, 主要就是作为gate driver送出信号, 来打开TFT, 好让TFT对显 示电极作充放电的动作. 所以当下一条gate走线, 送出电压要打开下一个TFT时, 便会影响到储存电容上储存电压的大小. 不过由于下一条gate走线打开到关闭的时间很短,(以1024*768分辨率, 60Hz更新频率的面板来说. 一条gate走线打开的时间约为20us, 而显示画面更新的时间约为16ms, 所以相对而言, 影响有限.) 所以当下一条gate走线关闭, 回复到原先的电压, 则Cs储存电容的电压, 也会随之恢复到正常. 这也是为什么, 大多数的储存电容设计都是采用Cs on gate的方式的原因. For personal use only in study and research; not for commercial use

很好用的12864驱动程序

/////////////////////////////////////////////////////////// #include #include #define uchar unsigned char #define uint unsigned int //////////单片机与液晶显示的引脚连接///////// sbit P32=P3^2; //RST sbit P33=P3^3; //CS2 sbit P34=P3^4; //CS1 sbit P35=P3^5; //E sbit P36=P3^6; //rs&DI sbit P37=P3^7; // R/W ////////延时///////// void delay(uint v) { while(v!=0)v--; } ////////复位/////////// void reset() { P32=0; delay(10); P32=1; delay(10); } ////////write code写指令/////// void wcode(uchar c,uchar cs1,uchar cs2) { P34=cs1; P33=cs2; P37=0; P36=0; P1=c; P35=0; delay(10);

P35=1; delay(10); P35=0; } /////////write data写数据/////////////// void wdata(uchar c,uchar cs1,uchar cs2) { P34=cs1; P33=cs2; P37=1; P36=0; P1=c; P35=0; delay(10); P35=1; delay(10); P35=0; } ////////////set start设置起始行///////////// void set_startline(uchar i)//起始行。11A5A4A3A2A1A0 共有64行 // 液晶显示器的最底层为第一行 { i=0xc0+64-i;//此算法为把最顶层做为第一层 wcode(i,1,1); } ////////////set 页值设置,起始列值函数///////////// void set_adr(uchar x,uchar y) { x=x+0xb8;//页地址设置。10111A2A1A0 DDRAM的8行为一页,A0~A2为页码,LCD为64行8页 y=y+0x40;//列地址设置。01A5A4A3A2A1A0 两半屏分别有64列,A0~A5送入列地址计数器, //作为列(Y)地址指针。每读写一次其自动加一,指向下一列DDRAM单元wcode(x,1,1); wcode(y,1,1); } ///////////on/off开/关显示函数//////////////

LCD驱动分析_LCD控制器设置及代码详解

LCD驱动分析_LCD控制器设置及代码详解 1. LCD工作的硬件需求: 要使一块LCD正常的显示文字或图像,不仅需要LCD驱动器,而且还需要相应的LCD 控制器。在通常情况下,生产厂商把LCD驱动器会以COF/COG的形式与LCD玻璃基板制作在一起,而LCD控制器则是由外部的电路来实现,现在很多的MCU内部都集成了LCD控制器,如S3C2410/2440等。通过LCD控制器就可以产生LCD驱动器所需要的控制信号来控制STN/TFT屏了。 2. S3C2440内部LCD控制器结构图: 我们根据数据手册来描述一下这个集成在S3C2440内部的LCD控制器: a:LCD控制器由REGBANK、LCDCDMA、TIMEGEN、VIDPRCS寄存器组成; b:REGBANK由17个可编程的寄存器组和一块256*16的调色板内存组成,它们用来配置LCD控制器的; c:LCDCDMA是一个专用的DMA,它能自动地把在侦内存中的视频数据传送到LCD驱动器,通过使用这个DMA通道,视频数据在不需要CPU的干预的情况下显示在LCD屏上; d:VIDPRCS接收来自LCDCDMA的数据,将数据转换为合适的数据格式,比如说4/8位单扫,4位双扫显示模式,然后通过数据端口VD[23:0]传送视频数据到LCD驱动器;e:TIMEGEN由可编程的逻辑组成,他生成LCD驱动器需要的控制信号,比如VSYNC、HSYNC、VCLK和LEND等等,而这些控制信号又与REGBANK寄存器组中的LCDCON1/2/3/4/5的配置密切相关,通过不同的配置,TIMEGEN就能产生这些信号的不同形态,从而支持不同的LCD驱动器(即不同的STN/TFT屏)。 3. 常见TFT屏工作时序分析: LCD提供的外部接口信号:

LCD1602驱动详解

一.接口 LCD1602是很多单片机爱好者较早接触的字符型液晶显示器,它的主控芯片是HD44780或者其它兼容芯片。刚开始接触它的大多是单片机的初学者。由于对它的不了解,不能随心所欲地对它进行驱动。经过一段时间的学习,我对它的驱动有了一点点心得,今天把它记录在这里,以备以后查阅。与此相仿的是LCD12864液晶显示器,它是一种图形点阵显示器,能显示的内容比LCD1602要丰富得多,除了普通字符外,还可以显示点阵图案,带有汉字库的还可以显示汉字,它的并行驱动方式与LCD1602相差无几,所以,在这里花点时间是值得的。 一般来说,LCD1602有16条引脚,据说还有14条引脚的,与16脚的相比缺少了背光电源A(15脚)和地线K(16脚)。我手里这块LCD16 02的型号是HJ1602A,是绘晶科技公司的产品,它有16条引脚。如图1所示:

图1 再来一张它的背面的,如图2所示:

图2它的16条引脚定义如下:

3. VO是液晶显示的偏压信号,可接10K的3296精密电位器。或同样阻值的RM065/RM063蓝白可调电阻。见图3。 图3 4. RS是命令/数据选择引脚,接单片机的一个I/O,当RS为低电 平时,选择命令;当RS为高电平时,选择数据。 5. RW是读/写选择引脚,接单片机的一个I/O,当RW为低电平时,向LCD1602写入命令或数据;当RW为高电平时,从LCD1602读取状态 或数据。如果不需要进行读取操作,可以直接将其接VSS。 6. E,执行命令的使能引脚,接单片机的一个I/O。 7. D0—D7,并行数据输入/输出引脚,可接单片机的P0—P3任意 的8个I/O口。如果接P0口,P0口应该接4.7K—10K的上拉电阻。如果是4线并行驱动,只须接4个I/O口。 8. A背光正极,可接一个10—47欧的限流电阻到VDD。 9. K背光负极,接VSS。见图4所示。

无字库12864液晶的驱动方法

无字库12864液晶的驱动方法 在制作单片机系统时,一般都需要用显示器件来显示单片机的工作状态并显示输出结果,如LED、数码管和液晶显示器等。LED最简单,但能给出的信息很少。数码管能清晰地显示数字和部分字母,但是耗电较大,不适合使用电池供电的装置。 常见的液晶显示器有段式液晶、字符液晶和图形液晶等。其中,段式液晶最省电,但对于通用显示使用起来不很方便,只能显示固定式数字或符号,而且需要专用驱动电路或特殊的单片机。 字符液晶(如1602)用得比较多,容易和单片机配合,但是一般都需要5V工作电压,虽然现在也有3V就可以工作的模块,但是体积还是较大,而且只能显示数字和西文字符,无法显示图形和汉字。 点阵液晶模块既可以显示ASCII字符,又可以显示汉字和图形,相对于前面几种,具有更大的灵活性,所以使用得越来越多。不过常用的图形液晶因为显示面积增加,体积比字符液晶(如1602)更大,价格也更贵。初学者要注意的是,12864图形点阵液晶随着厂家设计使用的驱动芯片不同,驱动程序有所区别,不像1602那样基本通用。 几种常见的12864图形点阵模块 12864点阵液晶模块分为带汉字库和不带汉字库两大类,目前带汉字库的通常是ST7920驱动,它可以工作在汉字字符方式和图形点阵方式,很多制作都用它,如果需要显示较多汉字,用它最为方便。 在显示汉字数量很少的场合,我们可以使用更加廉价的、不带字库的点阵液晶模块,这正是本文重点介绍的。它们的控制电路有KS0108和ST7565两种:KS0108很简单,一共只有7条指令,可是它没有串行接口;ST7565有20多条指令(最常用的也就几条),有串行接口,可选串行或并行工作。KS0108和ST7565的指令和上述带字库的ST7920区别较大,所以初学者买液晶时一定要搞清楚是哪种驱动电路。即使同样的驱动电路,不同厂家或者不同型号的产品,具体细节仍可能不同。例如有的片选信号是高电平有效,有的却是低电平有效,有的把显示区分为左右两半分别选取,有的却不加区分。所以使用前要仔细看厂家说明,如果没有,就要看液晶模块背面给出的具体型号,根据这个型号去查找使用手册。 笔者最近在淘宝网上搜寻到一款12864的图形点阵液晶,只有4cm宽、3.5cm高,显示面积为3.2cm宽、1.95cm高,非常小巧。更加难能可贵的是它可以在3V低电压工作,很适合我们制作小型便携装置。该液晶模块型号是SP12864FPD-12CSBE,由北京集粹电子设备公司出品,它的外形见图1。

段式LCD驱动原理详解

LCD Driver(液晶驱动器) 在单片机的应用中,人机界面占据相当重要的地位。人机界面主要包括事件输入和结果指示,事件输入包括键盘输入,通讯接口,事件中断等,结果指示包括LED/LCD显示、通讯接口、外围设备操作等。而在这些人机界面当中,LCD 显示技术由于其具有界面友好,成本较低等特点而在很多应用场合得以广泛应用。 1.LCD的显示原理 在讲解LCD driver之前,我们先就LCD的显示原理作一简单的介绍。 LCD(Liquid Crystal Display)是利用液晶分子的物理结构和光学特性进行显示的一种技术。液晶分子的特性: 液晶分子是介于固体和液体之间的一种棒状结构的大分子物质; 在自然形态,具有光学各向异性的特点,在电(磁)场作用下,呈各向同性特点; 下面以直视型简单多路TN/STN LCD Panel(液晶显示面板)的基本结构介绍LCD的基本显示原理,示意图如图-1: 图-1 LCD的基本显示原理

整个LCD Panel 由上下玻璃基板和偏振片组成,在上下玻璃之间,按照螺旋结构将液晶分子有规律的进行涂层。液晶面板的电极是通过一种ITO 的金属化合物蚀刻在上下玻璃基板上。如图所示,液晶分子的排列为螺旋结构,对光线具有旋旋光性,上下偏振片的偏振角度相互垂直。在上下基板间的电压为0时,自然光通过偏振片后,只有与偏振片方向相同的光线得以进入液晶分子的螺旋结构的涂层中,由于螺旋结构的的旋旋光性,将入射光线的方向旋转90度后照射到另一端的偏振片上,由于上下偏振片的偏振角度相互垂直,这样入射光线通过另一端的偏振片完全的射出,光线完全进入观察者的眼中,看到的效果就为白色。而在上下基板间的电压为一交流电压时,液晶分子的螺旋结构在电(磁)场的作用下,变成了同向排列结构,对光线的方向没有作任何旋转,而上下偏振片的偏振角度相互垂直,这样入射光线就无法通过另一端的偏振片射出,光线无法进入观察者的眼中,看到的效果就为黑色。这样通过在上下玻璃基板电极间施加不同的交流电压,即可实现液晶显示的两种基本状态亮(On)和暗(Off)。 在实际的液晶模以驱动电压中,有几个参数非常关键: 交流电压,液晶分子是需要交流信号来驱动的,长时间的直流电压加在液晶分子两端,会影响液晶分子的电气化学特性,引起显示模糊,寿命的减少,其破坏性为不可恢复; 扫描频率,直接驱动液晶分子的交流电压的频率一般在60~100Hz 之间,具体是依据LCD Panel 的面积和设计而定,频率过高,会导致驱动功耗的增加,频率过低,会导致显示闪烁,同时如果扫描频率同光源的频率之间有倍数关系,则显示也会有闪烁现象出现。 图-2 帧频(Frame)示意图 液晶分子是一种电压积分型材料,它的扭曲程度(透光性)仅仅和极板间电压的有效值有关,和充电波形无关。电压的有效值用COM/SEG 之间的电压差值的均方根VRMS 表示: []dt t V T RMS V T 2 )(1 )(∫= LCD 显示黑白(透光和不透光)的电压有效值的分界电压称为开启电压Vth,当电压有效值超过Vth,螺旋结构的旋光角度加大,透光率急剧变化,透明度急剧上升。反之,则透明度急剧下降。光线的透射率与交流电压的有效值的关系如图-3:

12864液晶经典驱动程序,一看就懂,有详细的注释(C语言编写,不看后悔)

这个程序写得很好,自己也是看的别人写的很好的程序,但是它代码不够完整,注释不详细,经过自己的修改加以完善。另外我发现很多的测试代码都没有附上测试代码效果图,在本人的代码下面有自己拍的效果图,填补不足之处。 自己在找资料的过程中花掉很多的财富值,如果大家看得起该代码请评五分加以下载,在下感激不尽! /******************************************* 程序名称:12864液晶经典驱动程序(带中文字库) 功能:12864测试程序 修改作者:王程 修改时间:2014年2月5日23:22:32 ********************************************/ #include #define uchar unsigned char #define uint unsigned int // P0 为数据口 sbit LCD_RS=P2^0; //数据、命令选择端口 sbit LCD_RW=P2^1; //液晶读写控制 sbit LCD_EN=P2^2; //液晶使能控制 sbit PSB = P2^4; //模式选择1为并行0为串行 sbit RES = P2^5; //复位端口低电平复位,上电之前进行复位,为了稳定!unsigned char code DAT[] = "我爱我家"; //测试显示的汉字,下面的A为测试显示的英文 /******************************************* 函数名称:Delay_1ms (晶振为12M) 功能:延时约1ms的时间 参数:无 返回值:无 ********************************************/ void delay_1ms(uint x) { uinti,j; for(j = 0;j

TFT-LCD液晶显示器的驱动原理

TFT-LCD液晶显示器的驱动原理 LCD显示器在近年逐渐加快了替代CRT显示器的步伐,你打算购买一台LCD吗?你了解LCD吗?液晶显示器和传统的CRT显示器,在其发光的技术原理上有什么不同?传统的CRT 显示器主要是依靠显象管内的电子枪发射的电子束射击显示屏内侧的荧光粉来发光,在显示器内部人造磁场的有意干扰下,电子束会发生一定角度的偏转,扫描目标单元格的荧光粉而显示不同的色彩。而TFT-LCD却是采用“背光(backlight)”原理,使用灯管作为背光光源,通过辅助光学模组和液晶层对光线的控制来达到较为理想的显示效果。 液晶是一种规则性排列的有机化合物,它是一种介于固体和液体之间的物质,目前一般采用的是分子排列最适合用于制造液晶显示器的nematic细柱型液晶。液晶本身并不能构发光,它主要是通过因为电压的更改产生电场而使液晶分子排列产生变化来显示图像。 液晶面板主要是由两块无钠玻璃夹着一个由偏光板、液晶层和彩色滤光片构成的夹层所组成。偏光板、彩色滤光片决定了有多少光可以通过以及生成何种颜色的光线。液晶被灌在两个制作精良的平面之间构成液晶层,这两个平面上列有许多沟槽,单独平面上的沟槽都是平行的,但是这两个平行的平面上的沟槽却是互相垂直的。简单的说就是后面的平面上的沟槽是纵向

排列的话,那么前面的平面就是横向排列的。位于两个平面间液晶分子的排列会形成一个Z轴向90度的逐渐扭曲状态。背光光源即灯管发出的光线通过液晶显示屏背面的背光板和反光膜,产生均匀的背光光线,这些光线通过后层会被液晶进行Z 轴向的扭曲,从而能够通过前层平面。如果给液晶层加电压将会产生一个电场,液晶分子就会重新排列,光线无法扭转从而不能通过前层平面,以此来阻断光线。 LCD由两块玻璃板构成,厚约1mm,其间由包含有液晶(LC)材料的5μm均匀间隔隔开。因为液晶材料本身并不发光,所以在显示屏两边都设有作为光源的灯管,而在液晶显示屏背面有一块背光板(或称匀光板)和反光膜,背光板是由荧光物质组成的可以发射光线,其作用主要是提供均匀的背景光源。背光板发出的光线在穿过第一层偏振过滤层之后进入包含成千上万水晶液滴的液晶层。液晶层中的水晶液滴都被包含在细小的单元格结构中,一个或多个单元格构成屏幕上的一个像素。在玻璃板与液晶材料之间是透明的电极,电极分为行和列,在行与列的交叉点上,通过改变电压而改变液晶的旋光状态,液晶材料的作用类似于一个个小的光阀。在液晶材料周边是控制电路部分和驱动电路部分。当LCD中的电极产生电场时,液晶分子就会产生扭曲,从而将穿越其中的光线进行有规则的折射,然后经过第二层过滤层的过滤在屏幕上显示出来。 液晶显示器的缺点在于亮度、画面均匀度、可视角度和反应

TFT_LCD液晶显示器的驱动原理详解

TFT LCD液晶显示器的驱动原理 TFT LCD液晶显示器的驱动原理(一) 我们针对TFT LCD的整体系统面来做介绍, 也就是对其驱动原理来做介绍, 而其驱动原理仍然因为一些架构上差异的关系, 而有所不同. 首先我们来介绍由于Cs(storage capacitor)储存电容架构不同, 所形成不同驱动系统架构的原理. Cs(storage capacitor)储存电容的架构 一般最常见的储存电容架构有两种, 分别是Cs on gate与Cs on common这两种. 这两种顾名思义就可以知道, 它的主要差别就在于储存电容是利用gate走线或是common走线来完成的. 在上一篇文章中, 我曾提到, 储存电容主要是为了让充好电的电压,能保持到下一次更新画面的时候之用. 所以我们就必须像在CMOS的制程之中, 利用不同层的走线, 来形成平行板电容. 而在TFT LCD的制程之中, 则是利用显示电极与gate走线或是common走线,所形成的平行板电容,来制作出储存电容Cs.

图1就是这两种储存电容架构, 从图中我们可以很明显的知道, Cs on gate由于不必像Cs on common一样, 需要增加一条额外的common走线, 所以它的开口率(Aperture ratio)会比较大. 而开口率的大小, 是影响面板的亮度与设计的重要因素. 所以现今面板的设计大多使用Cs on gate的方式. 但是由于Cs on gate的方式, 它的储存电容是由下一条的gate走线与显示电极之间形成的.(请见图2的Cs on gate与Cs on common的等效电路) 而gate走线, 顾名思义就是接到每一个TFT的gate端的走线, 主要就是作为gate driver送出信号, 来打开TFT, 好让TFT对显示电极作充放电的动作. 所以当下一条gate走线, 送出电压要打开下一个TFT时 ,便会影响到储存电容上储存电压的大小. 不过由于下一条gate走线打开到关闭的时间很短,(以1024*768分辨率, 60Hz更新频率的面板来说. 一条gate走线打开的时间约为20us, 而显示画面更新的时间约为16ms, 所以相对而言, 影响有限.) 所以当下一条gate走线关闭, 回复到原先的电压, 则Cs储存电容的电压, 也会随之恢复到正常. 这也是为什么, 大多数的储存电容设计都是采用Cs on gate 的方式的原因. 至于common走线, 我们在这边也需要顺便介绍一下. 从图2中我们可以发现, 不管您采用怎样的储存电容架构, Clc的两端都是分别接到显示电极与common. 既然液晶是充满在上下两片玻璃之间, 而显示电极与TFT都是位在同一片玻璃上, 则common电极很明显

基于STM32--LCD12864驱动程序

基于STM32--LCD12864驱动程序

STM32 LCD12864驱动程序(头文件)(2012-05-29 21:25:08)转载▼ 标签:杂谈 #ifndef LCD12864_H #define LCD12864_H #define LCD_CONTROL GPIOD //默认LCD12864的控制口在PD口 #define LCD_DATAPORT GPIOD //默认LCD12864的数据口在PD口 #define LCD_RESET_Pin GPIO_Pin_12 //默认LCD12864的复位引脚连接到PD.12 也可不用 #define LCD_RS_Pin GPIO_Pin_13 //默认LCD12864 RS -- PD.13 #define LCD_RW_Pin GPIO_Pin_14 //默认LCD12864 RW -- PD.14 #define LCD_EN_Pin GPIO_Pin_15 //默认LCD12864 E -- PD.15 #define LCD_CONTROL_CLOCK RCC_APB2Periph_GPIOD //默认LCD12864的控制口时钟

#define LCD_DATAPORT_CLOCK RCC_APB2Periph_GPIOD //默认LCD12864的数据口时钟 #define LCD_RS_1 LCD_CONTROL->BSRR &=~LCD_RS_Pin;LCD_CONTROL->BSRR |=LCD_RS_Pin //RS置高电平 #define LCD_RS_0 LCD_CONTROL->BRR &=~LCD_RS_Pin;LCD_CONTROL->BRR |=LCD_RS_Pin //RS置低电平 #define LCD_RW_1 LCD_CONTROL->BSRR &=~LCD_RW_Pin;LCD_CONTROL->BSRR |=LCD_RW_Pin //RW置高电平 #define LCD_RW_0 LCD_CONTROL->BRR &=~LCD_RW_Pin;LCD_CONTROL->BRR |=LCD_RW_Pin //RW置低电平 #define LCD_EN_1 LCD_CONTROL->BSRR &=~LCD_EN_Pin;LCD_CONTROL->BSRR |=LCD_EN_Pin //EN置高电平 #define LCD_EN_0 LCD_CONTROL->BRR &=~LCD_EN_Pin;LCD_CONTROL->BRR |=LCD_EN_Pin //EN置低电平

12864液晶屏串口驱动程序

12864液晶屏串口驱动程序代码 12864液晶屏驱动采用4_Wire-SPI串口驱动方式,可有效的减少IO口的占用,方便使用调试,本程序的代码驱动IC为ST7565R,是基于STC89C53RC的12864串行模式的程序,硬件电路连接只需要5根线:RS、 SDA、 SCLK、RES、CS 。 程序已经调试通过,很好用。代码如下: //---------------------------------------------------------------------- /*hotdisplay CO,.LTD.*/ // Module : HTG12864 // Lanuage : C51 Code // Create : // Version : 1.0 // Date : OCT-21-2016 // LCM Drive IC : ST7565R // INTERFACE : 4_Wire-SPI // MCU : STC89C53RC // VDD : 3.3V //********************************************************* ****************** #include #define uchar unsigned char

#define uint unsigned int uchar bdata transdata; sbit R_S= P3^5; sbit RES= P3^4; sbit SCK= P1^6; sbit SDA= P1^7; sbit CS1= P3^7; sbit transbit = transdata^7 ; #define Page 0xb0 //##########################################// void Comwrite(unsigned char com); //D′??á?3ìDò// void Datawrite(unsigned char dat); void Delay(unsigned int time); //?óê±×ó3ìDò// char code Hanzi[]={ 0xFF,0x01,0x01,0x09,0xF9,0x09,0x01,0x01,0x09,0xF9,0x09,0xE1 ,0x11,0x09,0x09,0x09, 0x11,0xE1,0x01,0x19,0x09,0x09,0xF9,0x09,0x09,0x19,0x01,0x01 ,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x09,0xF9,0x09,0x09,0x09,0x11,0xE1,0x01,0x01 ,0x09,0x09,0xF9,0x09,

LCD驱动程序分析

//****************************************************** * //* 2007.6.18 //****************************************************** * 在/kernel/include/asm-arm/arch-s3c2410/bitfield.h 文件中: #ifndef __ASSEMBLY__ #define UData(Data) ((unsigned long) (Data)) #else #define UData(Data) (Data) #endif 例:UData(5); = 5 /* * MACRO: Fld * * Purpose * The macro "Fld" encodes a bit field, given its size and its shift value

* with respect to bit 0. * * Note * A more intuitive way to encode bit fields would have been to use their * mask. However, extracting size and shift value information from a bit * field''''s mask is cumbersome and might break the assembler (255-character * line-size limit). * * Input * Size Size of the bit field, in number of bits. * Shft Shift value of the bit field with respect to bit 0. * * Output * Fld Encoded bit field. */

lcd16824驱动程序

#include #define fuc_PERIPH SYSCTL_PERIPH_GPIOE #define fuc_PORT GPIO_PORTE_BASE #define rs_PIN GPIO_PIN_0 #define rw_PIN GPIO_PIN_1 #define en_PIN GPIO_PIN_2 #define lcd_PERIPH SYSCTL_PERIPH_GPIOD #define lcd_PORT GPIO_PORTD_BASE #define lcd_PINS 0xff #define SysCtlPeriEnable SysCtlPeripheralEnable #define SysCtlPeriDisable SysCtlPeripheralDisable #define GPIOPinTypeIn GPIOPinTypeGPIOInput #define GPIOPinTypeOut GPIOPinTypeGPIOOutput #define GPIOPinTypeOD GPIOPinTypeGPIOOutputOD #define FIRST_ADDR 0 //定义字符/汉字显示起始位置 unsigned char CGRAM[]={ 0x08,0x20,0x1c,0x10,0x1c,0x1c,0xff,0x9e,0x7f,0x1e,0x1c,0x1f,0x3e,0x1f,0x3e, 0x1f, 0x77,0x1f,0x41,0x3f,0x00,0x7e,0x00,0xfe,0x83,0xfc,0x7f,0xf8,0x3f,0xf0,0x0f, 0xc0, }; unsigned char BMP1[]; unsigned char BMP2[]; unsigned char BMP3[]; unsigned char BMP4[]; unsigned char BMP5[]; unsigned char BMP6[]; unsigned char BMP7[]; unsigned char BMP8[]; unsigned char Num[]={'0','1','2','3','4','5','6','7','8','9','.'}; void delay (int m) { i nt n; f or(n=0;n<=m;n++); } void check(void) //判断是否忙碌 {

相关文档
最新文档