网络游戏 2017-05-23
————————————————————————————————————————————
SMG12864液晶显示器
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
引脚功能:
基本结构:
内部结构:IC1,IC2,IC3含有的主要功能器件
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
操作时序:
读操作时序图:
写操作时序图:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
操作指令:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
DDRAM与地址、显示位置的关系 p.s.CS2对应左屏,CS1对应右屏
DDRAM与页地址的对应关系
在图中可以看到每个CS由8页(64行)*64列组成
DDRAM与地址显示位置的对应关系
DDRAM与起始行对应关系
DDRAM行 | 62 | 63 | 0 | 1 | ... | 29 |
————————————————————————————————————————————
SMG12864液晶显示器使用实例
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
设计要求:一行显示八个字,滚动显示
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
实现思路:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
主体模块:
初始化LCD,清屏 动态显示
滚动控制
子模块:
初始化
选择左右屏(前四个字在左屏,后四个字在右屏) 显示字的上半部分
LCD基本操作:
读状态
rs=0;rw=1; do循环(BUSY为1忙碌时)
选择全屏 循环遍历8页
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
清屏过程:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
字显示过程:
第1个字(对应字库1~2行)
上半部分,第0页(字库第1行)
第0页(字库第3行)
第0页(字库第i*2-1行)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
实现代码:
1 #include <reg52.h> 2 #include <intrins.h> 3 #define DATA P0 4 typedef unsigned char uchar; 5 sbit rs = P2 ^ 2; 6 sbit rw = P2 ^ 1; 7 sbit en = P2 ^ 0; 8 sbit cs1 = P2 ^ 4; 9 sbit cs2 = P2 ^ 3; 10 uchar code zhCN[] = 11 { 12 //每个位置占据1列8行 13 //第1个字 14 //上半部分:第1列,第2列,第3列...第8列 15 0x00, 0x04, 0x04, 0xC4, 0xB4, 0x8C, 0x87, 0x84, 0xF4, 0x84, 0x84, 0x84, 0x84, 0x04, 0x00, 0x00, 16 //下半部分 17 0x00, 0x00, 0x20, 0x18, 0x0E, 0x04, 0x20, 0x40, 0xFF, 0x00, 0x02, 0x04, 0x18, 0x30, 0x00, 0x00, 18 //第2个字 19 0x20, 0x20, 0x2A, 0x2A, 0xAA, 0x6A, 0x3E, 0x2B, 0xAA, 0xAA, 0xEA, 0xAA, 0x2A, 0x22, 0x20, 0x00, 20 0x82, 0x82, 0x45, 0x45, 0x25, 0x15, 0x0D, 0xFF, 0x04, 0x0C, 0x14, 0x24, 0x65, 0xC2, 0x42, 0x00, 21 //第3个字 22 0x00, 0x00, 0xF8, 0x48, 0x48, 0x48, 0x48, 0xFF, 0x48, 0x48, 0x48, 0x48, 0xF8, 0x00, 0x00, 0x00, 23 0x00, 0x00, 0x0F, 0x04, 0x04, 0x04, 0x04, 0x3F, 0x44, 0x44, 0x44, 0x44, 0x4F, 0x00, 0x70, 0x00, 24 //第4个字 25 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0xE2, 0x12, 0x0A, 0x06, 0x02, 0x00, 0x80, 0x00, 0x00, 26 0x01, 0x01, 0x01, 0x01, 0x01, 0x41, 0x81, 0x7F, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 27 //第5个字 28 0x40, 0x20, 0xD0, 0x4C, 0x43, 0x44, 0x48, 0xD8, 0x30, 0x10, 0x00, 0xFC, 0x00, 0x00, 0xFF, 0x00, 29 0x00, 0x00, 0x3F, 0x40, 0x40, 0x42, 0x44, 0x43, 0x78, 0x00, 0x00, 0x07, 0x20, 0x40, 0x3F, 0x00, 30 //第6个字 31 0x20, 0x24, 0x2C, 0x35, 0xE6, 0x34, 0x2C, 0x24, 0x00, 0xFC, 0x24, 0x24, 0xE2, 0x22, 0x22, 0x00, 32 0x21, 0x11, 0x4D, 0x81, 0x7F, 0x05, 0x59, 0x21, 0x18, 0x07, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 33 //第7个字 34 0x00, 0x04, 0x04, 0x04, 0xFF, 0x54, 0x54, 0x54, 0x54, 0x54, 0xFF, 0x04, 0x04, 0x04, 0x00, 0x00, 35 0x11, 0x51, 0x49, 0x4D, 0x4B, 0x49, 0x49, 0x7D, 0x49, 0x49, 0x4B, 0x45, 0x4D, 0x59, 0x09, 0x00, 36 //第8个字 37 0x10, 0x10, 0x10, 0xFE, 0x10, 0x50, 0x40, 0xFE, 0x20, 0x20, 0xFF, 0x10, 0x10, 0xF8, 0x10, 0x00, 38 0x20, 0x20, 0x10, 0x1F, 0x08, 0x08, 0x00, 0x3F, 0x40, 0x40, 0x4F, 0x42, 0x44, 0x43, 0x70, 0x00 39 }; 40 void Delay(uchar m) 41 { 42 uchar i; 43 for (; m > 0; --m) 44 for (i = 0; i < 110; ++i) 45 ; 46 } 47 /* 检查忙碌状态 */ 48 void CheckState() 49 { 50 //通过读取BF标志位(引脚9,对应P0^7)状态判断模块是否繁忙 51 uchar dat; 52 //读状态下RS=0,R/W=1,E=1 53 rs = 0; 54 rw = 1; 55 do 56 { 57 DATA = 0x00; //RST=0正常,BUSY=0准备状态,ON/OFF=0显示关, 58 en = 1; 59 _nop_(); //打开使能后检测模块状态 60 dat = DATA; //状态读入dat 61 en = 0; 62 dat = 0x80 & dat; // 1000 0000 & dat 通过与操作隔离后7位,仅判断最高位 63 } 64 while(dat != 0x00); //P0^7为0时跳出循环,BUSY=0准备状态 65 } 66 /* 选择要显示的屏幕 */ 67 void SelectScreen(uchar screen) 68 { 69 //CS为低电平时亮 70 switch(screen) 71 { 72 case 0: //全屏显示 73 cs1 = 0; //IC1控制右半屏 74 _nop_(); 75 _nop_(); 76 _nop_(); 77 cs2 = 0; //IC2控制左半屏 78 _nop_(); 79 _nop_(); 80 _nop_(); 81 break; 82 case 1: //右屏显示 83 cs1 = 0; 84 _nop_(); 85 _nop_(); 86 _nop_(); 87 cs2 = 1; 88 _nop_(); 89 _nop_(); 90 _nop_(); 91 break; 92 case 2: //左屏显示 93 cs1 = 1; 94 _nop_(); 95 _nop_(); 96 _nop_(); 97 cs2 = 0; 98 _nop_(); 99 _nop_(); 100 _nop_(); 101 break; 102 } 103 } 104 /* 写命令操作 */ 105 void SendCommandToLCD(uchar com) 106 { 107 //p.s.在CS1或CS2低电平情况下才能写入命令 108 CheckState(); 109 rs = 0; 110 rw = 0; 111 DATA = com; 112 en = 1; 113 _nop_(); 114 _nop_(); 115 en = 0; 116 } 117 /* 显示开闭 */ 118 void SetOnOff(uchar onoff) 119 { 120 //传入0,关显示,00111110|00000000 = 00111110 121 //传入1,开显示,00111110|00000001 = 00111111 122 onoff = 0x3E | onoff; 123 SendCommandToLCD(onoff); //写指令onoff 124 } 125 /* 行(页)建立 */ 126 void SetLine(uchar page) 127 { 128 //10111000|00000000 = 10111000 129 //10111000|00000001 = 10111001 130 //10111000|00000010 = 10111010 131 //... 132 //10111000|00000111 = 10111111 133 //共8页,设置页地址 134 page = 0xb8 | page; 135 SendCommandToLCD(page); 136 } 137 /* 列建立 */ 138 void SetColumn(uchar column) 139 { 140 //01xxxxxx 后六位为列地址 141 //先通过与操作屏蔽前2位,将地址范围限制在0-63之间 142 //再通过或操作将列操作指令前两位代入 143 column = column & 0x3F; //00000000 & 00111111 = 00000000 144 column = 0x40 | column; //01000000 | 00000000 = 01000000 145 SendCommandToLCD(column); 146 } 147 /* 写入数据 */ 148 void WriteByte(uchar dat) 149 { 150 CheckState(); 151 rs = 1; 152 rw = 0; 153 DATA = dat; 154 en = 1; 155 _nop_(); 156 _nop_(); 157 en = 0; 158 } 159 /* 清屏 */ 160 void ClearScreen(uchar screen) 161 { 162 uchar i, j; 163 SelectScreen(screen); 164 for (i = 0; i < 8; ++i) //书上源码建立16页,此处建立8页正常运行 165 { 166 SetLine(i); //建立行 167 SetColumn(0); //建立列 168 for (j = 0; j < 64; ++j) //通过遍历该行的64列写入内容,列地址自动+1 169 WriteByte(0x00); 170 } 171 } 172 /* 设置开始行 */ 173 void SetStartLine(uchar startline) 174 { 175 //设置开始行时前两位为11 176 startline = 0xC0 | startline; 177 SendCommandToLCD(startline); 178 } 179 /* 初始化 */ 180 void InitLCD() 181 { 182 CheckState(); //检查LCD状态,是否繁忙,每次操作前都要进行检查 183 SelectScreen(0); //全屏显示,将要显示的屏幕部分置为低电平 184 SetOnOff(0); //关显示,1为开显示,0位关显示 185 SelectScreen(0); 186 SetOnOff(1); //开显示 187 SelectScreen(0); 188 ClearScreen(0); //0清全屏,1清左屏,2清右屏 189 SetStartLine(0); //从第0行开始 190 } 191 /* 显示汉字 */ 192 void Display(uchar screen, uchar page, uchar column, uchar num) 193 { 194 uchar i; 195 SelectScreen(screen); //选择对应要亮的屏 196 /* 显示字的上半部分 */ 197 SetLine(page); //建立行(页) 198 column = column & 0x3F; // column & 00111111 屏蔽前两位 199 SetColumn(column); //建立列 200 //写入字库第32*num~32*num+16位的数据 201 //第1个字:0~15,对应字库第1行 202 //第2个字:32~47,对应字库第3行 203 //第3个字:64~79,对应字库第5行 204 //... 205 for (i = 0; i < 16; ++i) 206 WriteByte(zhCN[i + 32 * num]); 207 /* 显示字的下半部分 */ 208 SetLine(page + 1); 209 SetColumn(column); 210 //写入字库第32*num+16~32*num+32位的数据 211 //第1个字:16~31,对应字库第2行 212 //第2个字:48~63,对应字库第4行 213 //第3个字:80~95,对应字库第6行 214 //... 215 for (i = 0; i < 16; ++i) 216 WriteByte(zhCN[i + 32 * num + 16]); 217 } 218 /* 主函数 */ 219 int main() 220 { 221 uchar i; 222 /* 初始化LCD,书上进行了一系列初始化操作,仅清屏的话不影响运行结果 */ 223 // InitLCD(); 224 ClearScreen(0); //清屏 225 /* 动态显示 */ 226 while(1) //余晖效应 227 { 228 for (i = 0; i < 64; ++i) //如果此处改成10,则在向上移动10行后重新出现在第0行,此处使用64的倍数来实现无限循环(无间断),书上源码循环128次,64次也无影响 229 { 230 /* 滚动控制 */ 231 SetStartLine(i); //循环建立开始行,每一次循环都上移1行 232 /* 汉字显示 */ 233 Display(2, 0, 0 * 16, 0); //左屏,第0页, 0列,第0个字 234 Display(2, 0, 1 * 16, 1); //左屏,第0页, 16列,第1个字 235 Display(2, 0, 2 * 16, 2); //左屏,第0页, 32列,第2个字 236 Display(2, 0, 3 * 16, 3); //左屏,第0页, 48列,第3个字 237 Display(1, 0, 4 * 16, 4); //右屏,第0页, 64列,第4个字 238 Display(1, 0, 5 * 16, 5); //右屏,第0页, 80列,第5个字 239 Display(1, 0, 6 * 16, 6); //右屏,第0页, 96列,第6个字 240 Display(1, 0, 7 * 16, 7); //右屏,第0页,128列,第7个字 241 SelectScreen(0); //由于显示后四个字符时左屏处于关显示状态,需要打开全屏 242 Delay(50); 243 } 244 } 245 }