本帖最后由 zhangjw258 于 2018-3-17 11:46 编辑
LCD12864液晶显示器的并行驱动(4位)
这个帖子是对前一篇的补充。
1. 什么叫二值图象? 通俗点说就是黑白图象.图象是由象素点组成的,描述图象的每一个象素点只用一个位(bit)就够了,非1即0,这样的图象就是二值图象.特点是图形文件占用空间少,图象只有黑白两色。 2. 前文中曾提到并口方式有两种, 一种是8位数据口,一种是4位数据口. 对于总线方式的单片机,或者对于接口资源丰富的单片机来说,8位数据口既方便数据传输速度又快.程序编写也简单.但如果又想传输速度快,又不能使用8位或者想节约数据口的情况下,用4位数据口也是一个不错的选择.只要将功能设定中的DL位置0即可.下面的程序代码就是使用4位并口设计的.原代码中相同的地方就不贴了,免得浪费大家时间,只补充不同的部分.只有12864.h和12864.c以及main.c文件有变化.
//12864.h文件 #ifndef __12864_H__ #define __12864_H__
#include <reg52.h>
#include "ZhangType.h" #include "fun.h"
#define SETMODE8 0x30 //并口8位数据接口,DL = 1,基本指令#define SETMODE8_OFF 0x34 //并行8位数据接口,DL = 1,绘图OFF #define SETMODE8_ON 0x36 //并行8位数据接口,DL = 1,绘图ON #define SETMODE4 0x20 //并行4位数据接口,DL = 0,基本指令 #define SETMODE4_OFF 0x24 //并行4位数据接口,DL = 0,绘图OFF #define SETMODE4_ON 0x26 //并行4位数据接口,DL = 0,绘图ON #define DISOPEN 0x0C //显示开,不显示光标,光标不闪烁
#define DISMODE 0x06 //读写字符后地址加1,屏显不移动
#define SETADDR1 0x80 //设置数据地址指针第一行
#define SETADDR2 0x90 //设置数据地址指针第二行
#define SETADDR3 0x88 //设置数据地址指针第三行
#define SETADDR4 0x98 //设置数据地址指针第四行
#define CLEAR 0x01 //清屏,数据指针清零
#define RET 0x02 //回车,数据指针清零
sbit RS = P2^0; //注意这三行sbit RW = P2^1; //说明下面用P2数据口传输数据不会影响低4位 sbit E = P2^2;
void Init12864();
void Write12864_Com(uint8 com); void Write12864_Dat(uint8 dat); void CheckBusy(void); //检查忙
#endif
//12864.c文件 #include "12864.h" void Init12864() { CheckBusy(); Write12864_Com(SETMODE4); //并行4位数据接口 CheckBusy(); Write12864_Com(DISOPEN); CheckBusy(); Write12864_Com(CLEAR); }
void Write12864_Com(uint8 com) //写命令
{ uint8 tmp;
RS = 0;
RW = 0;
tmp = com; tmp &= 0xF0; //先传高4位 P2 &= 0x0F; //保护P2低4位 P2 |= tmp;
E = 0;
E = 1; E = 0;
com <<= 4; //再传低4位
P2 &= 0x0F; P2 |= com;
E = 0;
E = 1; E = 0; }
void Write12864_Dat(uint8 dat) //写数据
{ uint8 tmp;
RS = 1;
RW = 0;
tmp = dat;
tmp &= 0xF0; P2 &= 0x0F; P2 |= tmp;
E = 0;
E = 1; E = 0;
dat <<= 4; P2 &= 0x0F; P2 |= dat;
E = 0;
E = 1; E = 0; }
void CheckBusy(void) //检查忙
{ uint8 tmp;
RS = 0;
RW = 1; E = 0;
while(1) //一次循环内同样要读两次
{ P2 |= 0xF0; E = 1; tmp = (P2 & 0xF0);
E =0;
P2 |= 0xF0; E = 1; tmp |= (P2 >> 4); //合并成一个字节 E =0;
if((tmp & 0x80) == 0) //不忙
break; } }
//main.c文件 #include "12864.h"
uint8 codedis1[] = "胜日寻芳泗水滨,";
uint8 codedis2[] = "无边光景一时新."; uint8 codedis3[] = "等闲识得东风面,"; uint8 codedis4[] = "万紫千红总是春.";
/*-- 图像宽度x高度 = 128x64 --*/
uint8 code **[1024] = { //******************************************************** //内容同前 //******************************************************** };
void Disp(uint8*pic) //显示Gdram内容(显示图片)
{ uint8 x, y, i;
CheckBusy();
Write12864_Com(SETMODE4_OFF); //切换到扩充指令,绘图OFF for(i = 0; i <= 8; i += 8) //画上下两屏 { for(y = 0; y < 32; y++) //每行32个象素点 { for(x = 0; x < 8; x++) //每半屏写8列,每列2字节 { CheckBusy(); Write12864_Com(0x80 + y); //行地址 CheckBusy(); Write12864_Com(0x80 + x + i); //列地址 CheckBusy(); Write12864_Dat(*pic++); //写数据 D15-D8 CheckBusy(); Write12864_Dat(*pic++); //写数据 D7-D0 } } } CheckBusy(); Write12864_Com(SETMODE4_ON); //打开图形显示,绘图ON }
void main()
{ uint8 len, max, t;
Init12864(); CheckBusy(); Write12864_Com(SETADDR1); max = strlen(dis1); for(len = 0; len < max; len++) { CheckBusy(); Write12864_Dat(dis1[len]); } CheckBusy(); Write12864_Com(SETADDR2); for(len = 0; len < max; len++) { CheckBusy(); Write12864_Dat(dis2[len]); } CheckBusy(); Write12864_Com(SETADDR3); for(len = 0; len < max; len++) { CheckBusy(); Write12864_Dat(dis3[len]); } CheckBusy(); Write12864_Com(SETADDR4); for(len = 0; len < max; len++) { CheckBusy(); Write12864_Dat(dis4[len]); }
for(t = 0; t < 30; t++) Delay(50000);
CheckBusy(); Write12864_Com(CLEAR); Disp(**); //填充图形 while(1); }
/******************************The End*********************************************** 注:试验结果完全同前,图形图片可参考前一篇帖子.下一篇:12864的串行驱动 ***************************************************************************************/
|