历史上的今天
返回首页

历史上的今天

今天是:2025年06月20日(星期五)

正在发生

2020年06月20日 | 12864液晶深入学习笔记_1——基于msp430g2553

2020-06-20 来源:eefocus

这是我对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);        //打开扩展指令集

1

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大小图形  显示上面定义的图像,是一个小喇叭

推荐阅读

史海拾趣

东软载波(EastSoft)公司的发展小趣事

随着市场的不断变化和技术的不断发展,东软载波始终保持对技术创新的重视。公司不断投入研发资源,相继开发出窄带低速、窄带高速、宽带低速、宽带高速等系列电力载波通信芯片,产品性能持续提升。同时,公司还形成了支撑电力线载波通信系统的三大重点核心技术,包括电力线通信网络与数据交换技术、电力线高精度同步和速率自适应扩频通信技术等。这些技术的突破使东软载波在行业中保持领先地位。

CDIL[Continental Device India Pvt. Ltd.]公司的发展小趣事

随着全球化进程的加速,CDIL积极寻求与国际知名企业的合作,共同推动电子产业的发展。通过与全球领先企业的合作,CDIL不仅引进了先进的技术和管理经验,还拓展了国际市场,进一步提升了公司的国际影响力。如今,CDIL的产品已远销海外多个国家和地区,为全球电子产业的发展作出了重要贡献。

这五个故事展示了CDIL在电子行业中的发展历程和取得的成就。从半导体制造的先驱到IC封装与电子制造服务的转型,再到产能提升、新技术研发以及国际合作与市场拓展,CDIL始终保持着对技术的追求和对市场的敏锐洞察。正是这些努力,使CDIL在激烈的市场竞争中脱颖而出,成为电子行业中备受瞩目的企业。

EnerSys公司的发展小趣事

EnerSys一直致力于技术创新和研发投入。公司拥有一支专业的研发团队,不断推出具有竞争力的新产品和解决方案。例如,EnerSys在锂电池领域取得了重要突破,成功开发出高能量密度、长寿命的锂电池产品。这些创新产品不仅满足了客户的多样化需求,还推动了公司在电子行业中的持续发展。

ebm-papst公司的发展小趣事

ebm-papst一直致力于通风和驱动技术的研发与创新。在中国市场,公司针对数据中心等特定应用场景,推出了革命性的创新产品——“数据中心列间空调用轴流风机”。该产品凭借其独特的设计和优异的性能,荣获了2022年中国制冷展创新产品奖。这一技术创新不仅解决了数据中心散热的难题,也进一步巩固了ebm-papst在通风与驱动技术领域的领先地位。

Desco Tools公司的发展小趣事

近年来,随着全球对环保问题的日益关注,Desco Tools公司也积极响应环保号召,将环保理念融入公司的生产和经营中。公司采用环保材料和工艺,减少生产过程中的废弃物和污染物排放。同时,公司还积极推动绿色生产和可持续发展,为客户提供更加环保、可持续的防静电解决方案。这些举措不仅有助于保护环境,还提升了公司的社会责任感和形象。

AKM [Asahi Kasei Microsystems]公司的发展小趣事

Desco Tools公司最初成立于上世纪70年代,专注于防静电工具的研发和生产。当时,随着电子行业的迅速发展,对静电防护的需求日益增加。Desco Tools公司凭借其敏锐的市场洞察力和技术实力,成功开发出了一系列防静电工具,如防静电手套、手腕带等,这些产品迅速在市场上获得了认可,为公司的发展奠定了坚实的基础。

问答坊 | AI 解惑

DCS系统UPS电源配置

  某化工企业的化工操作、监视、控制都采用DCS系统,如何向DCS系统提供高质量、安全可靠的电源就显得非常重要。该厂采用UPS向DCS系统供电,UPS系统由整流模块、充电模块、蓄电池、逆变模块、自动旁路开关、手动维修旁路开关等组成,UPS可以向D ...…

查看全部问答>

每一个JAVA初学者都应该搞懂的问题

对于这个系列里的问题,每个学Java的人都应该搞懂。当然,如果只是学Java玩玩就无所谓了。如果你认为自己已经超越初学者了,却不很懂这些问题,请将你自己重归初学者行列。内容均来自于CSDN的经典老贴。   问题一:我声明了什么!   String ...…

查看全部问答>

找位兄弟编一些程序

我最近有个事情,打算在MINI2440基础上做一个简易的CCD采集系统,软件完成的功能是控制IO口的时序读取AD数值,并通过USB发送。我本人对软件不算太了解,找比较清楚的兄弟帮忙编写一些代码。报酬可以谈。 PS:后续的数据处理在电脑上完成希望可以移 ...…

查看全部问答>

关于wince5.0下虚拟串口的问题!

我的开发板的cpu是s3c2410的,操作系统是wince5.0。买了一个gps接收器和一个蓝牙棒(板子上不带蓝牙),将蓝牙棒和板子的usb连接,wince下的一个蓝牙管理程序可以找到gps,但是我用OZi for ppc的软件只支持com口的数据传输,在笔记本上蓝牙口可以自 ...…

查看全部问答>

请教达人

我想采集几路直流电压信号到计算机,然后经过运算再输出到外围显示一些数字,不知道硬件电路需要些什么?因为我不是学计算机的,所以希望由一些市场上可以买到的模块拼请来实现,希望哪位达人知道一下,谢谢了!…

查看全部问答>

大家帮忙啊,我用OPC 连 KEPSERVEREX 报 0X80040202错误?怎么回事?

大家帮忙啊,我用OPC 连 KEPSERVEREX 报 0X80040202错误?怎么回事?…

查看全部问答>

lpc1114样片进展

首先LPC1114这个板是不好分开的,我的工具就一把削笔刀,所以只是把PCB线画断。昨晚把外围电路电源和芯片的电源分开 居然可以找到 还可以仿真 下载也没出错  就是不运行下载的程序,怀疑是复位电路电阻大了,弄了下没效果 眼看2点了 明早上班 ...…

查看全部问答>

ISE 相关问题

请问一下,ise里的clock_dedicated_route就什么意思?? rt??通常在什么情况下,ise会建议做这个约束,谢谢…

查看全部问答>

能不能聊ARM7的问题?

最近移植TCPIP协议到LPC2292,在测试过程中发现有程序跑飞的问题,经查找原因发现在给一个指向不被四整除的地址的结构体指针第一个数据赋值时,说明下第一个数据也是一个结构体指针,系统自动将指针向前移到能被四整除的位置,从而使得被赋值的结构 ...…

查看全部问答>

谁有用过驱动ic 为OTA5180A的液晶屏

我这边第一次用这种液晶屏,它除了数据I/O口外,就只有DISP、VSYNC、HSYNC和DE I/O口。想问一下有哪位大神用过这一类型的液晶,类似的也行。最好有源代码或者详细的讲解。谢谢。…

查看全部问答>