一、LCD1602A液晶说明。
DataSheet说明(技术参数)
①此LCD共16个管脚。每个接口说明如下表。
PS:1-2管脚没什么好说的,就是接电源和地的。
3管脚是偏压信号,这一管脚一般可以接个滑动变阻器,通过调节滑动变阻器可以控制字符显示颜色的深浅。
4管脚是数据命令选择端,当其高电平为命令输入端,低电平为命令输入端。
5管脚为读写选择端,当其高电平为读数据状态,底电平为写数据。
6是使能信号(详细见时序图(下)),当其为高电平时把数据输送给液晶,这里需要注意的是当E为高电平时,数据必须是稳定的。
7-14为数据I/O口。
15-16我们暂时不作考虑。
② RAM映射。
PS:这里可以看出地址00-10和40-50为LCD的显示区域分别显示第一行和第二行,而10-27和50-67为非显示区域,但是可以存放数据。
③操作时序图
读操作
由时序图和DataSheet说明(技术参数)可看出需输入
读状态:RS=L,RW=H,E=H。输出D0-D7状态字。
读数据:RS=H,RW=H,E=H。输出D0-D7数据。
写操作
由时序图和DataSheet说明(技术参数)可看出需输入:
写指令:RS=L,RW=L,D0--D7=指令码,E=H。输出:无
写数据:RS=H,RW=L,D0--D7=指令码,E=H。输出:无
PS:状态字说明:
注意:对控制字每次进行读写操作时都必须进行读写检测,确保STA7=0。
④1602A指令说明:
1、显示模式设置
指令码:0011 1000 功能:设置LCD为16X2显示,5X7点阵,8位只数据接口。
0000 0DCB 功能:D1=1 开显示,D1=0关显示。C1=1 显示光标,C1=0 不显示光标。B=1 光标闪烁,B=0 光标不显示。
0000 01NS 功能:N=1 当读或写一个字符后指针加一且光标加一。N=0 当读或写一个字符后指针减一且光标减一。
S=1 当写一个字符,整屏显示左移(N=1)或者右移(N=0),得到效果是光标不移动而屏幕移动的效果。
S=0当写一个字符时,屏幕不移动。
2、数据指针设置:80H+地址码。 需要注意的是前面要加上一个80H。
3、其他设置:01H:数据指针清0,所有数据显示清0。
02H:数据指针清0。
二:实验原理图:
为了更好的让大家明白第三部分的程序,以下是电路图:
三、程序源码:
1 #include<reg52.h> 2 #include<intrins.h> 3 //宏定义 4 #define uchar unsigned char 5 #define uint unsigned int 6 7 //dula wela与本实验无关、由于外接了数码管所以为了让1602有足够电压所以需禁用数码管 8 sbit dula=P2^6; 9 sbit wela=P2^7; 10 //分别定义了1602的使能,数据/命令选择,读写选择管脚 11 sbit lcden=P3^4; 12 sbit lcdrs=P3^5; 13 sbit lcdrw=P3^6; 14 //读写检测位(详见状态字说明) 15 sbit sta7=P0^7; 16 //定义了4个按钮来实现调整时间的功能(S1:选择按钮,S2:上调,S3:下调,S4:计时停止) 17 sbit s1=P3^0; 18 sbit s2=P3^1; 19 sbit s3=P3^2; 20 sbit s4=P3^3; 21 //1602第一行要显示的数据 22 uchar code string[]={"2013-05-15 THI"}; 23 //1602第二行显示的数据 24 uchar code string1[]={"00-00-00"}; 25 uchar count,shi,fen,miao,keynum; 26 27 //延时函数 28 void delay(uchar ms) 29 { 30 uint x,y; 31 for(x=ms;x>0;x--) 32 { 33 for(y=110;y>0;y--); 34 } 35 } 36 37 //判断是否可以对1602进行读写操作 38 uchar BusyTest() 39 { 40 bit result; 41 lcdrs=0; 42 lcdrw=1; 43 lcden=1; 44 _nop_(); 45 _nop_(); 46 _nop_(); 47 _nop_(); 48 result=sta7; 49 lcden=0; 50 return result; 51 } 52 53 //向1602写命令 54 void WriteInstruction(uchar instruction) 55 { 56 while(BusyTest()==1);//可读写判断 57 lcdrs=0; 58 lcdrw=0; 59 lcden=0; 60 61 _nop_(); 62 _nop_(); 63 64 P0=instruction; 65 66 _nop_(); 67 _nop_(); 68 _nop_(); 69 _nop_(); 70 71 lcden=1; 72 73 _nop_(); 74 _nop_(); 75 _nop_(); 76 _nop_(); 77 78 lcden=0; 79 } 80 81 //向1602写数据 82 void WriteData(uchar Data) 83 { 84 while(BusyTest()==1);//可读写判断 85 lcdrs=1; 86 lcdrw=0; 87 lcden=0; 88 89 _nop_(); 90 _nop_(); 91 92 P0=Data; 93 94 _nop_(); 95 _nop_(); 96 _nop_(); 97 _nop_(); 98 99 lcden=1; 100 101 _nop_(); 102 _nop_(); 103 _nop_(); 104 _nop_(); 105 106 lcden=0; 107 } 108 109 //102初始化 110 void Initiate() 111 { 112 P0=1; 113 dula=0; 114 wela=0; 115 delay(15); 116 WriteInstruction(0x38);//显示模式设置 117 delay(5); 118 WriteInstruction(0x38);//显示模式设置 119 delay(5); 120 WriteInstruction(0x38);//显示模式设置 121 delay(5); 122 WriteInstruction(0x0c);//开显示,不显示光标 123 delay(5); 124 WriteInstruction(0x06);//读写一个字符后地址指针加1,光标加1 125 delay(5); 126 WriteInstruction(0x01);//数据指针清0,显示清0 127 delay(5); 128 } 129 130 //显示时分秒 131 void write_sfm(uchar add,uchar Data) 132 { 133 uchar shi,ge; 134 shi=Data/10; 135 ge=Data%10; 136 WriteInstruction(0x80+0x44+add); //确定起始光标位置。 137 WriteData(0x30+shi); //写入十位 注:0的字符时0x30 详细见附件:字符手册 138 WriteData(0x30+ge); //写入个位 139 } 140 141 //搜索按下的按键,来确定光标的显示位置 ,一般的逻辑控制没什么好说的 142 void keyscan() 143 { 144 lcdrs=0; 145 if(s1==0) 146 { 147 delay(5); 148 if(s1==0) 149 { 150 while(!s1); //按键去抖 151 keynum++; 152 TR0=0; 153 if(keynum==4) 154 { 155 keynum=1; 156 } 157 if(keynum==1) 158 { 159 WriteInstruction(0x80+0x44+7); 160 } 161 if(keynum==2) 162 { 163 WriteInstruction(0x80+0x44+4); 164 } 165 if(keynum==3) 166 { 167 WriteInstruction(0x80+0x44+1); 168 } 169 170 WriteInstruction(0x0f); 171 } 172 } 173 174 if(s2==0) 175 { 176 delay(5); 177 if(s2==0) 178 { 179 while(!s2); 180 if(keynum==1) 181 { 182 miao++; 183 if(miao==60) 184 { 185 miao=0; 186 } 187 WriteInstruction(0x80+0x44+7); 188 write_sfm(6,miao); 189 } 190 if(keynum==2) 191 { 192 fen++; 193 if(fen==60) 194 { 195 fen=0; 196 } 197 WriteInstruction(0x80+0x44+4); 198 write_sfm(3,fen); 199 } 200 if(keynum==3) 201 { 202 shi++; 203 if(shi==24) 204 { 205 shi=0; 206 } 207 WriteInstruction(0x80+0x44+1); 208 write_sfm(0,shi); 209 } 210 } 211 } 212 213 if(s3==0) 214 { 215 delay(5); 216 if(s3==0) 217 { 218 while(!s3); 219 if(keynum==1) 220 { 221 if(miao==0) 222 { 223 miao=59; 224 } 225 else 226 { 227 miao--; 228 } 229 WriteInstruction(0x80+0x44+7); 230 write_sfm(6,miao); 231 } 232 if(keynum==2) 233 { 234 if(fen==0) 235 { 236 fen=59; 237 } 238 else 239 { 240 fen--; 241 } 242 WriteInstruction(0x80+0x44+4); 243 write_sfm(3,fen); 244 } 245 if(keynum==3) 246 { 247 if(shi==0) 248 { 249 shi=23; 250 } 251 else 252 { 253 shi--; 254 } 255 WriteInstruction(0x80+0x44+1); 256 write_sfm(0,shi); 257 } 258 } 259 } 260 261 if(s4==0) 262 { 263 delay(5); 264 if(s4==0); 265 while(!s4); 266 keynum=0; 267 WriteInstruction(0x0c); 268 TR0=1; 269 } 270 } 271 272 273 void main() 274 { 275 //LCD显示初始值 276 uchar i; 277 Initiate(); 278 delay(10); 279 i=0; 280 WriteInstruction(0x80+0x01); 281 while(string[i]!='\0') 282 { 283 WriteData(string[i]); 284 i++; 285 delay(10); 286 } 287 WriteInstruction(0x80+0x44); 288 i=0; 289 while(string1[i]!='\0') 290 {291 WriteData(string1[i]); 292 i++; 293 delay(10); 294 } 295 296 //设置定时器 297 TMOD=0x01; 298 TH0=(65536-50000)/256; 299 TL0=(65536-50000)%256; 300 EA=1; 301 ET0=1; 302 TR0=1; 303 304 while(1) 305 { 306 keyscan(); 307 if(count==20) 308 { 309 count=0; 310 miao++; 311 if(miao==60) 312 { 313 miao=0; 314 fen++; 315 if(fen==60) 316 { 317 fen=0; 318 shi++; 319 if(shi==24) 320 { 321 shi=0; 322 } 323 } 324 } 325 write_sfm(6,miao); 326 write_sfm(3,fen); 327 write_sfm(0,shi); 328 } 329 } 330 } 331 332 //计数器50ms 333 void timer0() interrupt 1 334 { 335 TH0=(65536-50000)/256; 336 TL0=(65536-50000)%256; 337 count++; 338 }
附:字符手册: