📄 lcd1602.lst
字号:
C51 COMPILER V7.50 LCD1602 05/27/2007 09:10:54 PAGE 1
C51 COMPILER V7.50, COMPILATION OF MODULE LCD1602
OBJECT MODULE PLACED IN lcd1602.OBJ
COMPILER INVOKED BY: C:\Keil\C51\BIN\C51.EXE lcd1602.c BROWSE DEBUG OBJECTEXTEND
line level source
1 /*============================================================
2 使用1602液晶显示和PS/2键盘的示例 孟猛 2006/2
3 -------------------------------------------------
4 Tel:010-51779043
5 ==============================================================
6
7 SMC1602A(16*2)模拟口线接线方式
8 连接线图:
9
10 ---------------------------------------------------
11 |LCM-----51 | LCM-----51 | LCM------51 |
12 --------------------------------------------------|
13 |DB0-----P0.0 | DB4-----P0.4 | RW-------P2.2 |
14 |DB1-----P0.1 | DB5-----P0.5 | RS-------P2.1 |
15 |DB2-----P0.2 | DB6-----P0.6 | E--------P2.0 |
16 |DB3-----P0.3 | DB7-----P0.7 | VLCD接1K电阻到GND|
17 ---------------------------------------------------
18
19 Keyboard接线
20
21
22 PS/2--------51
23 1 DATA------P2.7
24 3 GND
25 4 VCC
26 5 CLK-------P3.2 接在51的外部中断,触发方式为低电平
27
28
29 本程序源码只供学习参考,不得应用于商业用途,如有需要请联系作者。
30
31 [注:AT89x51使用12M或11.0592M晶振,实测使用11.0592M]
32 [Keil uV2 7.01编译运行通过 程序中没有做键盘数据的奇偶校验]
33
34 =============================================================*/
35 #include <reg51.h>
36 #include "scancodes.h"
37 #include "sybxt1.h"
38 sbit LCM_RW= P2^2; //定义LCD引脚
39 sbit LCM_RS= P2^1;
40 sbit LCM_E = P2^0;
41 #define LCM_Data P0
42 sbit Key_Data= P2^7; //定义Keyboard引脚
43 sbit Key_CLK = P3^2;
44 #define Busy 0x80 //用于检测LCM状态字中的Busy标识
45 void LCMInit(void);
46 void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);
47 void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);
48 void Delay5Ms(void);
49 void Delay400Ms(void);
50 void Decode(unsigned char ScanCode);
51 void WriteDataLCM(unsigned char WDLCM);
52 void WriteCommandLCM(unsigned char WCLCM,BuysC);
53 unsigned char ReadDataLCM(void);
54 unsigned char ReadStatusLCM(void);
55 unsigned char code cdle_net[] = {"--nice to you--"};
C51 COMPILER V7.50 LCD1602 05/27/2007 09:10:54 PAGE 2
56 unsigned char code email[] = {"mengmbj@163.com"};
57 unsigned char code Cls[] = {" "};
58 static unsigned char IntNum = 0; //中断次数计数
59 static unsigned char KeyV; //键值
60 static unsigned char DisNum = 0; //显示用指针
61 static unsigned char Key_UP=0, Shift = 0;//Key_UP是键松开标识,Shift是Shift键按下标识
62 static unsigned char BF = 0; //标识是否有字符被收到
63 void DisplayString ()
64 {
65 1 while(uiOffset!=uiRxCount)
66 1 {
67 2 if (DisNum > 15)
68 2 {
69 3 DisplayListChar(0, 1, Cls);//清LCD第二行
70 3 DisNum = 0;
71 3 }
72 2 DisplayOneChar(DisNum, 1,ucRxBuf[uiOffset]);
73 2 DisNum++;
74 2
75 2 uiOffset++;
76 2 uiOffset%=RXBUFSIZE;
77 2 }
78 1 }
79 void sysinit()
80 {
81 1 unsigned char TempCyc;
82 1 Delay400Ms(); //启动等待,等LCM讲入工作状态
83 1 LCMInit(); //LCM初始化
84 1 Delay5Ms(); //延时片刻(可不要)
85 1 DisplayListChar(0, 0, cdle_net);
86 1 DisplayListChar(0, 1, email);
87 1 ReadDataLCM();//测试用句无意义
88 1 for (TempCyc=0; TempCyc<10; TempCyc++)
89 1 Delay400Ms(); //延时
90 1 DisplayListChar(0, 1, Cls);
91 1 IT0 = 0; //设外部中断0为低电平触发
92 1 EA = 1;
93 1 EX0 = 1; //开中断
94 1 }
95 void GetPs2Key(void)
96 {
97 1 if (BF)
98 1 Decode(KeyV);
99 1 else
100 1 EA = 1; //开中断
101 1 }
102
103 //写数据
104 void WriteDataLCM(unsigned char WDLCM)
105 {
106 1 ReadStatusLCM(); //检测忙
107 1 LCM_Data = WDLCM;
108 1 LCM_RS = 1;
109 1 LCM_RW = 0;
110 1 LCM_E = 0; //若晶振速度太高可以在这后加小的延时
111 1 LCM_E = 0; //延时
112 1 LCM_E = 1;
113 1 }
114 //写指令
115 void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC为0时忽略忙检测
116 {
117 1 if (BuysC) ReadStatusLCM(); //根据需要检测忙
C51 COMPILER V7.50 LCD1602 05/27/2007 09:10:54 PAGE 3
118 1 LCM_Data = WCLCM;
119 1 LCM_RS = 0;
120 1 LCM_RW = 0;
121 1 LCM_E = 0;
122 1 LCM_E = 0;
123 1 LCM_E = 1;
124 1 }
125
126 //读数据
127 unsigned char ReadDataLCM(void)
128 {
129 1 LCM_RS = 1;
130 1 LCM_RW = 1;
131 1 LCM_E = 0;
132 1 LCM_E = 0;
133 1 LCM_E = 1;
134 1 return(LCM_Data);
135 1 }
136 //读状态
137 unsigned char ReadStatusLCM(void)
138 {
139 1 LCM_Data = 0xFF;
140 1 LCM_RS = 0;
141 1 LCM_RW = 1;
142 1 LCM_E = 0;
143 1 LCM_E = 0;
144 1 LCM_E = 1;
145 1 while (LCM_Data & Busy); //检测忙信号
146 1 return(LCM_Data);
147 1 }
148 void LCMInit(void) //LCM初始化
149 {
150 1 LCM_Data = 0;
151 1 WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号
152 1 Delay5Ms();
153 1 WriteCommandLCM(0x38,0);
154 1 Delay5Ms();
155 1 WriteCommandLCM(0x38,0);
156 1 Delay5Ms();
157 1 WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号
158 1 WriteCommandLCM(0x08,1); //关闭显示
159 1 WriteCommandLCM(0x01,1); //显示清屏
160 1 WriteCommandLCM(0x06,1); // 显示光标移动设置
161 1 WriteCommandLCM(0x0F,1); // 显示开及光标设置
162 1 }
163 //按指定位置显示一个字符
164 void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
165 {
166 1 Y &= 0x1;
167 1 X &= 0xF; //限制X不能大于15,Y不能大于1
168 1 if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;
169 1 X |= 0x80; //算出指令码
170 1 WriteCommandLCM(X, 1); //发命令字
171 1 WriteDataLCM(DData); //发数据
172 1 }
173 //按指定位置显示一串字符
174 void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
175 {
176 1 unsigned char ListLength;
177 1 ListLength = 0;
178 1 Y &= 0x1;
179 1 X &= 0xF; //限制X不能大于15,Y不能大于1
C51 COMPILER V7.50 LCD1602 05/27/2007 09:10:54 PAGE 4
180 1 while (DData[ListLength]>0x19) //若到达字串尾则退出
181 1 {
182 2 if (X <= 0xF) //X坐标应小于0xF
183 2 {
184 3 DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
185 3
186 3 ListLength++;
187 3 X++;
188 3 }
189 2 }
190 1 }
191 //5ms延时
192 void Delay5Ms(void)
193 {
194 1 unsigned int TempCyc = 5552;
195 1 while(TempCyc--);
196 1 }
197 //400ms延时
198 void Delay400Ms(void)
199 {
200 1 unsigned char TempCycA = 5;
201 1 unsigned int TempCycB;
202 1 while(TempCycA--)
203 1 {
204 2 TempCycB=7269;
205 2 while(TempCycB--);
206 2 };
207 1 }
208
209 void Keyboard_out(void) interrupt 0
210 {
211 1 if ((IntNum > 0) && (IntNum < 9))
212 1 {
213 2 KeyV = KeyV >> 1; //因键盘数据是低>>高,结合上一句所以右移一位
214 2 if (Key_Data) KeyV = KeyV | 0x80; //当键盘数据线为1时为1到最高位
215 2 }
216 1 IntNum++;
217 1 while (!Key_CLK); //等待PS/2CLK拉高
218 1
219 1 if (IntNum > 10)
220 1 {
221 2 IntNum = 0; //当中断11次后表示一帧数据收完,清变量准备下一次接收
222 2 BF = 1; //标识有字符输入完了
223 2 EA = 0; //关中断等显示完后再开中断 (注:如这里不用BF和关中断直接调Decode()则所Decode中所调用的所有函数要
-声明为再入函数)
224 2 }
225 1 }
226
227 void Decode(unsigned char ScanCode) //注意:如SHIFT+G为12H 34H F0H 34H F0H 12H,也就是说shift的通码+G的通码
-+shift的断码+G的断码
228 {
229 1 unsigned char TempCyc;
230 1
231 1 if (!Key_UP) //当键盘松开时
232 1 {
233 2 switch (ScanCode)
234 2 {
235 3 case 0xF0 : // 当收到0xF0,Key_UP置1表示断码开始
236 3 Key_UP = 1;
237 3 break;
238 3
239 3 case 0x12 : // 左 SHIFT
C51 COMPILER V7.50 LCD1602 05/27/2007 09:10:54 PAGE 5
240 3 Shift = 1;
241 3 break;
242 3
243 3 case 0x59 : // 右 SHIFT
244 3 Shift = 1;
245 3 break;
246 3
247 3 default:
248 3 if (DisNum > 15)
249 3 {
250 4 DisplayListChar(0, 1, Cls);//清LCD第二行
251 4 DisNum = 0;
252 4 }
253 3 if(!Shift) //如果SHIFT没按下
254 3 {
255 4 for (TempCyc = 0;(UnShifted[TempCyc][0]!=ScanCode)&&(TempCyc<59); TempCyc++); //查表显示
256 4 if (UnShifted[TempCyc][0] == ScanCode) DisplayOneChar(DisNum, 1, UnShifted[TempCyc][1]);
257 4 DisNum++;
258 4 }
259 3 else //按下SHIFT
260 3 {
261 4 for(TempCyc = 0; (Shifted[TempCyc][0]!=ScanCode)&&(TempCyc<59); TempCyc++); //查表显示
262 4 if (Shifted[TempCyc][0] == ScanCode) DisplayOneChar(DisNum, 1, Shifted[TempCyc][1]);
263 4 DisNum++;
264 4 }
265 3 break;
266 3 }
267 2 }
268 1 else
269 1 {
270 2 Key_UP = 0;
271 2 switch (ScanCode) //当键松开时不处理判码,如G 34H F0H 34H 那么第二个34H不会被处理
272 2 {
273 3 case 0x12 : // 左 SHIFT
274 3 Shift = 0;
275 3 break;
276 3 case 0x59 : // 右 SHIFT
277 3 Shift = 0;
278 3 break;
279 3 }
280 2 }
281 1 BF = 0; //标识字符处理完了
282 1 }
MODULE INFORMATION: STATIC OVERLAYABLE
CODE SIZE = 663 ----
CONSTANT SIZE = 285 ----
XDATA SIZE = ---- ----
PDATA SIZE = ---- ----
DATA SIZE = 6 11
IDATA SIZE = ---- ----
BIT SIZE = ---- ----
END OF MODULE INFORMATION.
C51 COMPILATION COMPLETE. 0 WARNING(S), 0 ERROR(S)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -