单片机C语言拉高1位,第二讲 单片机C语言之12864液晶显示

前面一讲我们焊接了C51的最小系统。这讲里我们将继续焊接上液晶显示相关电路,并分别实现用12864显示一个汉字,字符串,数字,浮点数以及可调节的电子时钟。

概念

点阵式液晶显示模块(LCD)广泛应用于单片机控制系统,比数码管、段式液晶能模块显示更多、更直观的信息,如汉字、曲线、图片等。点阵液晶显示模块集成度很高,一般都内置控制芯片、行驱动芯片和列驱动芯片,点阵数量较大的LCD还配置RAM芯片,带汉字库的LCD还内嵌汉字库芯片,有负压输出的LCD还设有负压驱动电路等。单片机读写LCD实际上就是对LCD的控制芯片进行读写命令和数据。编程驱动LCD时,不需要对LCD的结构和点阵行列驱动原理深入了解,只要理解LCD接口的定义和LCD的控制芯片的读写时序和命令就可以了。

12864LCD属于点阵图形液晶显示模块,不但能显示字符,还能显示汉字和图形,分带汉字库和不带那字库两种,价格也有差别。带汉字库的12864LCD使用起来非常方便,不需要编写复杂的汉字显示程序,只要按时序写入两个字节的汉字机内码,汉字就能显示出来了,驱动程序简单许多。本文例程就是基于带汉字库的12864液晶显示模块。DM12864M 汉字图形点阵液晶显示模块,可显示汉字及图形,内置 8192 个中文汉字(16X16 点阵)、128

个字符(8X16 点阵)及 64X256 点阵显示 RAM(GDRAM)。

a2eba2828d28a17d2ecc5e34b0febb8d.png

12864有如下特点:

1. 128点X 64行=8192点。

2. 12864有两种工作模式。

(1)文本工作模式

整屏平均分成32个显示区(每个显示区是16X16点阵),每个显示区可显示一个中文,每个显示区可显示两个英文ASCII字符。下图为汉字显示坐标即地址。

d9401112daf306430153d6eacf1de015.png

(2)绘图工作模式          整屏按水平方向每16个点分为一组,所以整屏共有8192/16=512组,每次可控制任意一组的16个点。图形显示坐标:水平方向 X—以字节单位,垂直方向 Y—以位为单位。

61146c3f5cf1463bbe6a5c5514856307.jpg

3. 12864的硬件接口

ca729a22640d44e098cf808d08a9d349.jpg

0034939a13b348a399fed4ed4ac71078.jpg

1501bbb39e0b42f68f432c6a1efe723a.jpg

总共20个引脚。其中引脚4-14是连接到MCU的。4.5.6引脚有两种功能,分别对应不同串并驱动模式。当为串行驱动时,4.5.6分别为CS,SID,CLK,且此时8位数据并行线无效;当为并行驱动时,4.5.6分别为RS,RW,E,且此时8位并行数据线有效。而15脚则是用于选择串并模式的。

汉字显示实验

好了现在我们来显示一个汉字。首先明确思路,初始化液晶屏,切换到文本模式,设置要显示汉字的地址,写入显示汉字。新建工程,分别建立三个文件main.c, 12864.c, 12864.h。

main.c

#include "12864.h"

void main()

{

LCD_Init();

LCD_SetAddText(0x93);

LCD_WriteDat(0XC4);

LCD_WriteDat(0Xe3);

LCD_SetAddText(0x94);

LCD_WriteDat(0XBa);

LCD_WriteDat(0XC3);

while(1)

{

}

}12864.c

#include "12864.h"

sbit LCDRS_CS=P3^5;

sbit LCDWR_SID=P3^6;

sbit LCDE_CLK=P3^7;

/*

数据 0xFA

命令-地址0xF8

*/

void delay(u16 x)

{

while(x--);

}

void LCD_Send8bit(u8 dat) //向LCD发送一个字节

{

u8 i;

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

{

LCDE_CLK=0;

//LCDWR_SID=dat>>7;

LCDWR_SID=dat&(1<<7);

LCDE_CLK=1;

dat<<=1;

}

}

void LCD_EntryText() //LCD进入文本模式

{

LCD_WriteCmd(0x30);

}

void LCD_EntryDraw() //LCD进入绘图模式

{

}

voidLCD_SetAddText(u8 add)//设置LCD文本模式显示地址

{

LCDE_CLK=0;

LCDRS_CS=1;

LCD_Send8bit(0Xf8);

LCD_Send8bit(add&0xf0);

LCD_Send8bit(add<<4);

LCDE_CLK=0;

LCDRS_CS=0;

}

void LCD_SetAddDraw(u8 x, u8 y)//设置LCD绘图模式显示地址

{

x=y;

}

void LCD_WriteDat(u8 dat)//向LCD写入显示数据

{

LCDE_CLK=0;

LCDRS_CS=1;

LCD_Send8bit(0Xfa);

LCD_Send8bit(dat&0xf0);

LCD_Send8bit(dat<<4);

LCDE_CLK=0;

LCDRS_CS=0;

}

void LCD_WriteCmd(u8 cmd) //向LCD发送一条命令

{

LCDE_CLK=0;

LCDRS_CS=1;

LCD_Send8bit(0Xf8);

LCD_Send8bit(cmd&0xf0);

LCD_Send8bit(cmd<<4);

LCDE_CLK=0;

LCDRS_CS=0;

}

void LCD_Init()

{

LCD_EntryText();

delay(50);

LCD_WriteCmd(0x01);//清屏

delay(5000);

LCD_WriteCmd(0x0c); //开显示

delay(50);

}12864.h

#ifndef _12864_

#define _12864_

#include "reg51.h"

#define u8 unsigned char

#define u16 unsigned int

void delay(u16 x);

void LCD_EntryText();

void LCD_EntryDraw();

void LCD_SetAddText(u8 add);

void LCD_SetAddDraw(u8 x, u8 y);

void LCD_WriteDat(u8 dat);

void LCD_WriteCmd(u8 cmd);

void LCD_Send8bit(u8 dat);

void LCD_Init();

#endif这个程序显示了两个汉字,在地址0x93和0x94处装入了“你好”两个汉字。我们一步一步来分析整个程序,所有的驱动都放在了12864.c里面。首先程序刚开始定义了三个IO口分别对应4.5.6脚,因为我们这里要采用串行模式。接下来液晶屏是要工作在文本模式还是绘图模式呢,所以我们又新建了两个函数LCD_EntryText()和LCD_EntryDraw(),暂时不管绘图模式,然后查看数据手册,得知进入绘图模式需要发送指令0x30给液晶,因此我们需要新建一个发送命令的函数。这样的话这个函数可以在这里被调用,也可以在其他地方被调用。这个函数为LCD_WriteCmd(u8 cmd),然而命令是怎么被发送的呢?这就得回到串行连接时序图了。

cfb90dfb485c10c25058e690a6dbcbaf.png

如图SID总共发送了三个字节,其中第一个字节的RW位用来表明数据传送方向,1则为数据从LCD到MCU,0相反。显然我们这里是写数据到LCD所以这位为0。RS位则表明数据的类型,1表示数据是显示数据,0表示数据是控制指令。显然我们是发送指令因此这位为0。因此第一个字节就是0Xf8。第二个字节发送的是目标数据的高4位,如果发送的命令为cmd,那么取cmd的高4位构成这第二个字节,即为cmd&0xf0。同理第三个字节发的是目标数据低4位,cmd<<4。CS和SCLK的时序就不具体讲了。但是LCD_WriteCmd(u8 cmd)函数要完成,前面说的三个字节具体又是怎么发送的呢?因此我们还需要内嵌一个函数来发送一个字节。这样我们就又新建一个函数LCD_Send8bit(u8 dat)。根据前面的时序图,要发送一个位,首先当SCLK为低时,拉高CS并保持,准备好要发送的位(这里取要发送的字节dat的最高位,即右移7位),在SCLK由低跳变到高时,发送这位。然后再拉低SCLK,以此循环直到8个位都发完。

切换到文本模式后,我们就要选择显示的地址了。怎么选择地址呢,MCU就需要把一个地址数据发送给LCD,然后LCD就知道接下来要在这个地址上放MCU发来的显示数据。因此又新建一个函数LCD_SetAddText(u8 add)。前面我们讲了怎么发送命令,实际上发送地址也是使用相同的程序(液晶能识别命令和地址),这里就不再赘述了。

再接下来就是发送显示数据了。因此又新建一个函数 LCD_WriteDat(u8 dat)。显然还是跟发送命令和地址一个模式,唯一的区别就是第一个字节这时候变成了0xfa。好了讲解完毕。

引申:

如果是要发送数字和浮点数,我们可以在12864.c中引入如下函数,然后载主函数作相应调用即可。

void Show_String(u8 add, u8 *str)//lcd显示字符串

{

LCD_EntryText(); //lcd进入文本模式

LCD_SetAddText(add);

while(*str)

{

LCD_WriteDat(*str++);

}

}

void Show_Number(u8 add, u16 n) //lcd显示一个数字

{

char s[6];

sprintf(s,"%05d",n);

Show_String(add, s);

}

void Show_Float(u8 add, float n) //lcd显示一个浮点数

{

char s[6];

sprintf(s,"%03.2f",n);

Show_String(add, s);

}

电子时钟实验

相关代码可查看我的代码片。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值