12864液晶学习笔记
Created on: 2012-8-30
Author: zhang bin
这是我对12864的学习笔记,12864液晶功能很全面,使用起来也很方便,能够满足一般的研究和工程应用的需求。
下面我就对几个方面讲述一下我对它学习过程中的一些体会。我会尽量全面的介绍,并且会主要针对一些特殊的应用和一些我认为要特别注意的地方进行较为详细的说明。而对于那些较为固定的,常用的方面会简略一些。
其中的不管串行模式还是并行模式,对液晶的写指令,写数据,读操作等这些基本的操作都是一些比较固定的,基础的东西。我认为只要能够看懂,并且能够在不同的处理器上移植就够了,没有必要非要自己对着手册时序图写出来。因为有人已经写好了,而且工作稳定,我们只要在它的基础上学会应用就可以了。现在是知识爆炸时期,知识,信息迅速膨胀,我们要学会使用已有的成果,然后在这个基础上自己再进行开发应用的研究。我们不必一定要从底层开始把别人已经做的很成熟的东西再做一遍,这样不但效率不高,而且我们一般人的精力也不允许。
好了,不说废话了,下面就开始介绍,当然,那些基础层面的东西我也会介绍的。
下面所涉及到的程序,是针对msp430g2553的,都是我已经调通的,可以直接应用。
一,12864的介绍
1,液晶显示模块是128×64 点阵的汉字图形型液晶显示模块,可显示汉字及图形,内置国标GB2312 码简体中文字库(16X16 点阵)、128 个字符(8X16 点阵)及64X256 点阵显示RAM(GDRAM)。可与CPU 直接接口,提供两种界面来连接微处理机:8-位并行及串行两种连接方式。具有多种功能:光标显示、画面移位、睡眠模式等。
2,常用的12864液晶内部都是使用ST7920控制器。
1),ST7920提供8位元,4位元及串行三种微处理器控制方式,大陆常用的是8位元和串行控制方式。
2),ST7920可以控制显示字母,数字符号,中文字型和自定义的图画。可以用来显示图形,演示动画,绘制曲线等。
3),字符显示RAM (DDRAM)
ST7920的字符显示RAM (DDRAM)最多可以控制16字元*4行,LCD的显示范围为16字元*2行。
这里要注意,其实ST7920的DDRAM每一行可以控制16个汉字的,共有4行。但是LCD的每行只能显示8个字符,为了显示观察的方便,在lcd制作的过程中,是将DDRAM的其中两行拆分开成四行,然后在lcd上显示,也即是DDRAM只用到了一半。
lcd的显示字符的坐标地址如下表:
汉字显示坐标
Line1 80H 81H 82H 83H 84H 85H 86H 87H
Line2 90H 91H 92H 93H 94H 95H 96H 97H
Line3 88H 89H 8AH 8BH 8CH 8DH 8EH 8FH
Line4 98H 99H 9AH 9BH 9CH 9DH 9EH 9FH
从上表不难看出,其中第一行和第三行是DDRAM中的同一行拆分来的,同理2 4 行也是DDRAM中的同一行拆分而来的。
了解了这一点就不难理解下面程序中在换行显示时,要认为手动地指定下一行的地址。例如:如果第一行显示完了,下面的数据我要接着显示在第二行,这样才符合人观察的习惯,那么我就要在换第二行显示之前要手动地把显示地址切换到第二行。要不然的话,第一行显示完了,地址会自动增加,就会显示到第三行上去,这样的话我们观察起来就不自然了。程序实例会在下面涉及到的。
4),中文字库ROM (CGROM)
内置的是GB2312码简体中文字库,共提供了8192个16*16点的中文字型。
5),半宽字型ROM (HCGROM)
提供126个16*8点半字宽的字母符号字型。
6),图画显示RAM (GDRAM)
提供64*256位元的GDRAM

其中我们常用的RAM就是上面所提到的,还有一些CGRAM ,IRAM这些我们不经常使用,就不再介绍了。
上面介绍的DDRAM控制显示汉字,字符。GDRAM控制显示图画,上电后,默认DDRAM是打开的,控制液晶显示。GDRAM默认不打开,它里面的数据是随机的,如果此时打开了GDRAM的话,lcd会同时受到DDRAM和GDRAM的控制,由于GDRAM中的数据是随机的,所以会显示乱码。所以在使用GDRAM之前要先清除里面的随机数据。
清除GDRAM的函数如下:

void Clear_GDRAM(void)   //清除GDRAM中的的随机数据。因为上电后GDRAM中的数据是随机的,如果不清除而直接打开GDRAM显示时,会显示乱码//所以在局部使用GDRAM显示图形时,要先清除随机数据。如果是全局使用GDRAM,即整个lcd屏全部设置显示数据,则可以//不必清除,因为新数据会把随机数据给覆盖掉
{uchar i,j,k;wr_lcd(comm,0x34);        //打开扩展指令集   操作GDRAM是扩展指令集
i = 0x80;
for(j = 0;j < 32;j++)
{
wr_lcd(comm,i++);
wr_lcd(comm,0x80);for(k = 0;k < 16;k++){wr_lcd(dat,0x00);   //写入空字符,就相当于清零}
}
i = 0x80;for(j = 0;j < 32;j++)
{wr_lcd(comm,i++);wr_lcd(dat,0x88);for(k = 0;k < 16;k++){wr_lcd(dat,0x00);}
}wr_lcd(comm,0x30);        //回到基本指令集
}

3,12864有两种工作模式
1),并行模式和串行模式。并行模式就是常用的8位数据线,4为控制线。这种方式虽然占用的IO口较多,但是向液晶收发数据较容易实现,数据传输速度较快。所以在一些连续显示多幅图画,演示动画或对显示的实时性要求较高的场合应该考虑这种方式。其中在并行模式中,在向液晶写数据或命令前,要进行液晶忙标志判断 BF,要确定液晶显示不忙了,才能进行操作。
其中并行模式的液晶的读写数据,命令函数如下:

void Write_Cmd(uchar cmd)
{
uchar lcdtemp = 0;

LCD_RS_L;
LCD_RW_H;
LCD_DataIn;    //数据输入单片机
do                       //判忙
{LCD_EN_H;_NOP();lcdtemp = LCD2MCU_Data;LCD_EN_L;}
while(lcdtemp & 0x80);  //判断忙标志   等待忙LCD_DataOut;   //数据输出到lcd
LCD_RW_L;
MCU2LCD_Data = cmd;   //单片机向lcd输入命令
LCD_EN_H;
_NOP();
LCD_EN_L;

}

void Write_Data(uchar dat)
{
uchar lcdtemp = 0;

LCD_RS_L;
LCD_RW_H;
LCD_DataIn;
do                       //判忙
{LCD_EN_H;_NOP();lcdtemp = LCD2MCU_Data;LCD_EN_L;
}
while(lcdtemp & 0x80);     //等待忙LCD_DataOut;
LCD_RS_H;
LCD_RW_L;MCU2LCD_Data = dat;   //单片机向lcd中输入数据
LCD_EN_H;
_NOP();
LCD_EN_L;

}

2),串行模式只用到了两根线WR EN于单片机进行通信。这种方式可以大大减少单片机IO口的开销,适用于IO口资源有限的单片机(如msp430g2553)。但是这种方式实现起来较麻烦,数据的传输效率不高。对于一般的文字,简单图形的显示还是可以的。(有可能是因为msp430g2553的处理能力较强,我现在用串行连接方式,显示下面的几幅图画,显示效果很好,看不出有什么数据传输速度慢的问题)。
由于我用的是msp430g2553,所以我一直都是使用串行的控制模式。
//下面重点讲一下串行的时序
//SCLK:串行同步时钟线,每操作一位数据都要有一个SCLK跳变沿,而且在这里是上升沿有效。也即是说,每次SCLK由低电平变为高电平的瞬间,液晶控
//制器将SID上的数据读入或输出。
//SID:串行数据,每一次操作都由三个字节数据组成,第一个字节向控制器发送命令控制字,告诉控制器接下来是什么操作,若为写指令则发送11111000
//(0xf8),若为若为写数据则发送11111010(0xfa),若为读状态则发送11111100(0xfc),若为读数据则发送11111110(0xfe)。
//第二个字节的高4位为发送指令或数据的高4位,第二个字节的低4位补0.
//第三个字节的高4位为发送指令或数据的低4位,第三个字节的低4位补0
//具体的可以观察时序进行理解
12864液晶深入学习笔记_1——基于msp430g2553

其中数据的传输的函数如下:
//12864串行连接写数据,写命令函数 按照手册上的时序进行编程
void wr_lcd(uchar dat_comm,uchar content)//
{ // 要写的数据
uchar a,i,j;
delay_us(50);
a=content;
LCD_SCLK0; //en=0;
LCD_SID1; //wr=1
for(i=0;i<5;i++) //数据时序*****************8 前5个高电平的同步码
{
LCD_SCLK1;
LCD_SCLK0;
}
LCD_SID0; //wr=0 写操作
LCD_SCLK1; //en=1 来一个时钟
LCD_SCLK0; //en=0
if(dat_comm)
LCD_SID1; //RS=1 写数据
else
LCD_SID0; //RS=0 写指令

LCD_SCLK1; //来一个时钟
LCD_SCLK0;
LCD_SID0; //控制字的最后一位为0
LCD_SCLK1; //来一个时钟
LCD_SCLK0;
for(j=0;j<2;j++)//**一共2*4次循环写写一字节数据,第一次大循环写高4位,第二次大循环写低4位
{
for(i=0;i<4;i++)
{
if(a&0x80)
LCD_SID1;
else
LCD_SID0;
a=a<<1;
LCD_SCLK1;
LCD_SCLK0;
}
LCD_SID0;
for(i=0;i<4;i++) //时钟下面来4个时钟脉冲
{
LCD_SCLK1;
LCD_SCLK0;
}
}
}

void Draw_TX(uchar Yaddr,uchar Xaddr,const uchar * dp)
{
uchar j;
uchar k=0;

// wr_lcd(comm,0x01); //清屏,只能清除DDRAM
wr_lcd(comm,0x34); //使用扩展指令集,关闭绘图显示 打开扩展指令集
for(j=0;j<16;j++)
{
wr_lcd(comm,Yaddr++); //Y地址
wr_lcd(comm,Xaddr); //X地址
wr_lcd(dat,dp[k++]); //写入数据
wr_lcd(dat,dp[k++]);
}
wr_lcd(comm,0x36); //打开绘图显示
// wr_lcd(comm,0x30); //回到基本指令集模式
}

5,向液晶全屏写图像的函数如下:

void Draw_PM(const uchar *ptr) //整屏显示图形
{
uchar i,j,k;

wr_lcd(comm,0x34);        //打开扩展指令集

i = 0x80;
for(j = 0;j < 32;j++)
{
wr_lcd(comm,i++);
wr_lcd(comm,0x80);
for(k = 0;k < 16;k++)
{
wr_lcd(dat,*ptr++); //先写入32*16个数据
}
}
i = 0x80;
for(j = 0;j < 32;j++)
{
wr_lcd(comm,i++);
wr_lcd(comm,0x88);
for(k = 0;k < 16;k++)
{
wr_lcd(dat,*ptr++); //再写入32*16个数据
}
}
wr_lcd(comm,0x36); //打开绘图显示
wr_lcd(comm,0x30); //回到基本指令集
}

6,下面我就贴上一个对液晶功能测试的函数,其中用到了液晶的很多功能,可以有实现现象观察得到,注释的也较详细,代码如下:

include “msp430g2553.h”

include “ser_12864.h”

void main( void )
{
uint i;
uchar laba[]= //16*16大小图形数据
{ 0x00,0x00,0x00,0xC0,0x01,0x48,0x02,0x44,0x04,0x52,0xF8,0x49,0x88,0x49,0x88,0x49,
0x88,0x49,0x88,0x49,0xF8,0x49,0x04,0x52,0x02,0x44,0x01,0x48,0x00,0xC0,0x00,0x00};

WDTCTL = WDTPW + WDTHOLD;    //关狗BCSCTL1 = CALBC1_12MHZ;  //设定cpu时钟DCO频率为12MHz
DCOCTL = CALDCO_12MHZ;
P2DIR |=BIT5+BIT4;      //液晶的两条线init_lcd();                 //初始化液晶//下面是显示液晶字符表中的字符
wr_lcd(comm,0x80);            //写第一行的显示地址    写命令0x80
for(i = 0; i < 16; i++)        //每一行可以显示16个字符wr_lcd(dat,0x00 + i);     //显示0x00~0x0f对应的字符  写数据wr_lcd(comm,0x90);            //写第二行的显示地址    因为12864的1 3行和2 4行分别由控制器ST7920的两行切割来的,为了看起来方便
//这里要手动把地址切换到第二行。要不然的话,显示完了第一行,液晶会自动切换显示到第三行上去
for(i = 0; i < 16; i++)wr_lcd(dat,0x10 + i);     //显示0x10~0x1f对应的字符wr_lcd(comm,0x88);            //写第三行的显示地址
for(i = 0; i < 16; i++)wr_lcd(dat,0x20 + i);     //显示0x20~0x2f对应的字符wr_lcd(comm,0x98);            //写第四行的显示地址
for(i = 0; i < 16; i++)wr_lcd(dat,0x30 + i);     //显示0x30~0x3f对应的字符

// delay_ms(1000); //延迟1s,观察效果

//调试时,可以在此处设置断点,单步执行下面的指令,观察结果
//在显示时DDAM和GDRAM是同时显示的,也就是它们的显示结果是叠加在一起的

//1.设定DDRAM地址命令wr_lcd(comm,0x90);            //设定DDRAM地址,因为此时DDRAM地址已经溢出
//2.显示状态命令wr_lcd(comm,0x08);            //整体显示关,游标关,游标位置关wr_lcd(comm,0x0c);            //整体显示开,游标关,游标位置关wr_lcd(comm,0x0e);            //整体显示开,游标开,游标位置关wr_lcd(comm,0x0f);            //整体显示开,游标开,游标位置开  游标闪烁
//3.位址归位wr_lcd(comm,0x02);            //位址归位,游标回到原点wr_lcd(comm,0x84);            //将DDRAM地址设为0x88,游标在此闪烁
//4.点设定指令
//(以下四个命令是控制写入字符以后光标及整屏显示的移动)wr_lcd(comm,0x07);            //光标右移整体显示左移wr_lcd(comm,0x20);           //写入两个空格wr_lcd(dat,0x20);wr_lcd(comm,0x05);            //光标左移整体显示右移
wr_lcd(dat,0x20);           //写入两个空格
wr_lcd(dat,0x20);wr_lcd(comm,0x06);            //光标右移整体显示不移动
wr_lcd(dat,0x20);           //写入两个空格
wr_lcd(dat,0x20);wr_lcd(comm,0x04);            //光标左移整体显示不移动
wr_lcd(dat,0x20);           //写入两个空格
wr_lcd(dat,0x20);
//5.游标和显示移位控制
//(以下四个命令无需写入显示数据,直接控制光标和整屏显示的移动,上面执行的命令是写入空格实现光标移动和整屏的移动)
wr_lcd(comm,0x10);            //光标左移
wr_lcd(comm,0x14);            //光标右移
wr_lcd(comm,0x18);            //整体显示左移,光标跟随
wr_lcd(comm,0x1c);            //整体显示右移,光标跟随wr_lcd(comm,0x0c);            //关闭光标//6.进入扩展功能模式命令
wr_lcd(comm,0x34);            //打开扩展功能模式,绘图显示关闭
//7.反白命令
wr_lcd(comm,0x04);            //同时反白1、3行
wr_lcd(comm,0x04);            //再次反白1、3行,相当于关闭1、3行反白
wr_lcd(comm,0x05);            //同时反白2、4行
wr_lcd(comm,0x05);            //再次反白2、4行,相当于关闭2、4行反白
//8.睡眠模式命令
wr_lcd(comm,0x08);            //进入睡眠模式  液晶的控制器ST7920关闭,降低功耗。但是背光还是亮的
wr_lcd(comm,0x0c);            //退出睡眠模式   继续显示
//9.待命模式命令
wr_lcd(comm,0x01);            //进入待命模式  也是不显示内容的,液晶已经准备好接受数据或命令了
//10.打开GDRAM显示                        //这样打开GDRAM显示,液晶的GDRAM和DDRAM会同时控制液晶的显示
wr_lcd(comm,0x36);            //打开扩展功能模式,打开绘图显示  由于上电后GDRAM中的数据是随机的,所以如果在显示之前不清除的话,会显示乱码
Draw_TX(0x80,0x84,laba);    //显示16*16大小图形  显示上面定义的图像,是一个小喇叭
Clear_GDRAM();              //清除上电复位后GDRAM中的随机数值,此时GDRAM显示空字符,但是DDRAM中还是有数据,所以此时会显示DDRAM中的数据
Draw_TX(0x80,0x84,laba);    //重新显示设置16*16大小图形

//11.关闭GDRAM显示
wr_lcd(comm,0x34); //打开扩展功能模式,关闭绘图显示 显示DDRAM中的数据
//12.设定基本指令集
wr_lcd(comm,0x30); //回到基本指令集
//13.清除显示命令
wr_lcd(comm,0x01); //清屏 只能清除DDRAM 此时液晶就什么都不显示了

 //下面是显示液晶字符表中的字符wr_lcd(comm,0x80);            //写第一行的显示地址
for(i = 0; i < 16; i++)wr_lcd(dat,0x40 + i);     //显示0x40~0x4f对应的字符wr_lcd(comm,0x90);            //写第二行的显示地址
for(i = 0; i < 16; i++)wr_lcd(dat,0x50 + i);     //显示0x50~0x5f对应的字符wr_lcd(comm,0x88);            //写第三行的显示地址
for(i = 0; i < 16; i++)wr_lcd(dat,0x60 + i);     //显示0x60~0x6f对应的字符wr_lcd(comm,0x98);            //写第二行的显示地址
for(i = 0; i < 16; i++)wr_lcd(dat,0x70 + i);     //显示0x70~0x7f对应的字符LPM4;

}

12864液晶深入学习笔记_1——基于msp430g2553相关推荐

  1. 学习笔记之——基于深度学习的图像超分辨率重建

    最近开展图像超分辨率( Image Super Resolution)方面的研究,做了一些列的调研,并结合本人的理解总结成本博文~(本博文仅用于本人的学习笔记,不做商业用途) 本博文涉及的paper已 ...

  2. C#入门学习笔记(基于刘铁锰老师C#入门2014教学视频)【1】

    C#入门学习笔记(基于刘铁锰老师C#入门2014教学视频)[1] 前言: 本笔记作为记录我从零开始学习C#的记录,为了unity的兴趣爱好自学一门C#,也算是寒假为自己充个电,希望这个寒假可以坚持下去 ...

  3. C#入门学习笔记(基于刘铁锰老师C#入门2014教学视频)【2】

    C#入门学习笔记(基于刘铁锰老师C#入门2014教学视频)[2] 初识类和名称空间 前言: 本笔记作为记录我从零开始学习C#的记录,为了unity的兴趣爱好自学一门C#,也算是寒假为自己充个电,希望这 ...

  4. 【图神经网络】图神经网络(GNN)学习笔记:基于GNN的图表示学习

    图神经网络GNN学习笔记:基于GNN的图表示学习 1. 图表示学习 2. 基于GNN的图表示学习 2.1 基于重构损失的GNN 2.2 基于对比损失的GNN 参考资料 本文主要就基于GNN的无监督图表 ...

  5. 学习笔记之——基于matlab的数字通信系统(2)之离散信号的傅里叶分析

    关于连续信号的傅里叶分析,可以参考博文<学习笔记之--基于matlab的数字通信系统(1)&连续信号的傅里叶分析> 目录 离散时间信号的傅里叶变换(DTFT) 连续时间信号的抽样- ...

  6. 【QT学习笔记】基于QT的天气预报

    [QT学习笔记]基于QT的天气预报 前言 那就开始吧! 先看一下效果 颜面最重要,画个UI 构造实现 怎么开始? 开始解析数据 关于城市切换 ok 最后源码献上 感谢 前言 学习qt已经有一段时间了, ...

  7. RISC-V 指令学习笔记(基于CH32V103)

    文章目录 RISC-V 指令学习笔记(基于CH32V103) 一.指令结构分类 二.寄存器功能 三.加载存储指令 四.算数运算指令 五.移位指令 六.逻辑操作指令 七.跳转指令 7.1 条件跳转 7. ...

  8. Unity游戏框架学习笔记——03基于观察者模式的事件中心

    Unity游戏框架学习笔记--03基于观察者模式的事件中心 基于观察者模式的事件中心 一如既往指路牌:https://www.bilibili.com/video/BV1C441117wU?p=5. ...

  9. 带时滞的病毒模型计算模板【基于matlab的动力学模型学习笔记_1】

    /*仅当作学习笔记,若有纰漏欢迎友好交流指正,此外若能提供一点帮助将会十分荣幸*/ 摘 要:无论是生物病毒还是网络病毒,其内核的传播机理都有很多的相似之处.因此,本文在经典的SIR病毒模型基础上改造出 ...

最新文章

  1. 大数据分布式集群搭建(8)
  2. 关键字提取_SEO怎么做?从排名和关键字优化入手
  3. boost::fusion::unfused_typed用法的测试程序
  4. Apache专用笔记贴
  5. 在Sqoop中管理密码的关键提示
  6. 正态分布的前世今生(1)
  7. web元件库、axure元件库、通用元件库、常用web组件、常用表单、框架、数据表单、导航栏、边框、图标、列表、日期时间选择器、评分组件、穿梭框、输入框、步骤条、图表组件、数据可视化、后台模板、时间轴
  8. 最短Hamilton路径(位运算基本思路)
  9. 学习写了一个新年倒计时->jQuery+CSS+Html
  10. 最佳现代设计必备衬线字体
  11. c语言代码姓名全拼,巧用拼音首字母输入人名(代码)
  12. Android Bottom Sheet详解
  13. 【深度学习】猫狗识别TensorFlow2实验报告
  14. 【笔记】Jenkins- 解决 “Error 403 No valid crumb was included in the request“
  15. Win7系统的电脑还可以装win10吗
  16. 算法入门刷题笔记 Day10 - A - 拓扑排序·一 -- D - K-th Path
  17. 大数据医疗面临着哪些挑战?
  18. Ansible Ad—hoc 模式常用模块
  19. Python 写对联
  20. RPG Maker MV游戏解包

热门文章

  1. mac单节点安装Erda实践
  2. Zebra BI for Excel
  3. 通过Value获取JSON中对应的KEY
  4. SharpDevelop浅析_1_AddInTree
  5. 锚定情境法:有效控制变量自评偏差
  6. 关于gps测量精度的分析
  7. PC版微信内置浏览器 缓存文件保存位置
  8. 显示器是个人计算机上的一个重要输出设备,东大17秋学期《计算机应用基础》在线作业123满分答案...
  9. Hive  if null 的用法
  10. 双系统如何修改系统默认启动项?简易教程