LCD1602与键盘扫描作业
一、设计任务
在AT89C51的控制下,利用LCD1602和两只按键完成两屏显示的切换显示:第一屏为自己姓名的拼音,第二位自为子学号;第二屏显示:第一行为自己的籍贯,第二行为自己的生日。显示利用LCd命令1——8进行设置,要求至少使用4个命令。
二、设计思路
选择P0口作为数据口;首先将姓名学号籍贯等数据存放在单片机的程序储存器内。再通过单片机与LCD1206以数据总线的形式相连通过R/W,E控制信号,D0~D7数据或命令信号,加上独立键盘扫描来控制显示第一屏还是第二屏显示;
三、硬件电路
1、LCD1206显示模块
以P0为数据和命令端口,P2^0~P2^2为控制信号端口
LCD1206的命令字特点:
编号 | 命令 | Rs |
R / W ‾ R/ \overline{W} R / W |
D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | 清屏 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
2 | 光标返回 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
× \times × |
3 | 显示模式 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | I/D | S |
4 | 显示开关、光标设置 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | D | C | B |
5 | 光标及字符移位 | 0 | 0 | 0 | 0 | 0 | 1 | S/C | R/L |
× \times × |
× \times × |
6 | 功能设置 | 0 | 0 | 0 | 0 | 1 | DL | N | F |
× \times × |
× \times × |
7 | CGRAM地址 | 0 | 0 | 0 | 1 | 字 | 符 | 库 | 地 | 址 | |
8 | DDRAm地址 | 0 | 0 | 1 | 数 | 据 | R | A | M | 第 | 址 |
9 | 读忙标志或地址 | 0 | 1 | BF | |||||||
10 | 写数据 | 1 | 0 | ||||||||
11 | 读数据 | 1 | 1 |
-
命令1 : 光标返回00H(左上角位置)
-
命令2: 光标返回
-
命令3:显示设置
I/D: (1)地址指针加一;(0)地址指针减一
S: (1)写入字符,整屏左移或右移 ;(0)整屏显示不移动
-
命令4:D——屏幕显示:1 开显示;0关显示
C——光标有无:1 有; 0 无光标
B——光标闪烁:1闪烁;0 不闪烁 -
命令5 :SC =0 移动光标 SC =1 移动显示的字符
RL = 0 左移RL =1 右移 -
命令6: DL :1 八位数据 0 四位数据接口
N:1 两行显示 0 单行显示
F: (1)5
×10
\times10
×
1
0
阵 (0)5
×7
\times7
×
7
点阵 -
命令7:GGRAM地址设置,设置用户自定义的字符
-
命令8:设置显示地址:80H + 显示位置
-
命令9: 读忙: BF =1 忙;
-
命令10:写数据
-
命令10: 读数据
控制操作:
操作 | 单片机发给LCD的控制信号 | LCD的输出 |
---|---|---|
读状态 |
RS=0, R/ W ‾ \overline W W =1,E= 1 |
D0~D7状态 |
写命令 |
RS=0,R/ W ‾ \overline W W =0, D0~D7命令,E正脉冲 |
无 |
读数据 |
RS =1,R/ W ‾ \overline W W =1,E =1 |
D0~D7数据 |
写数据 |
RS =1,R/ W ‾ \overline W W =0,D0~D7 数据,E正脉冲 |
无 |
2、独立键盘扫描模块
四、软件设计
#include<reg51.h>
#include<intrins.h>
#define out P0 //数据和命令端口
#define uchar unsigned char//预定义
#define uint unsigned int
sbit S1 =P1^0; // 按键1
sbit S2 =P1^1;//按键2
uchar keyvalue; // 键值
uchar code name[] ="Tang jie";//预存显示数据
uchar code stu_num[] ="1808441072";
uchar code birthplace[] ="Tong Ling";
uchar code birthday[] = "2000/01/27";
sbit RS = P2^0; // 数据或指令控制线
sbit RW = P2^1; // 读写控制线
sbit E = P2^2; //使能控制线
void key_scan(void); //键盘扫描声明
/*********************
延时函数
*********************/
void delay(uint j)
{
uchar i = 250;
for(;j>0;j--)
{
while (--i);
i= 249;
while(--i);
i=250;
}
}
/*********************
检查忙函数,检查LCD是否处于忙状态
如果处于忙则持续检查
*********************/
void check_busy(void)
{
uchar temp;
do{
temp =0xff; //
E = 0;
RS= 0; //
RW = 1;
E =1;
temp = out; //
}while(temp&0x80); // 如果 BF =1 则持续检查
E = 0;
}
/*********************
写命令函数
*********************/
void write_command(uchar com)
{
check_busy();// 首先检查忙
E= 0;//预置0
RS =0;
RW =0; //按LCD写命令控制信号设置
out = com;
E =1; // 正脉冲
_nop_();//
E = 0; // 还原E
delay(1);
}
/********************
写数据函数
********************/
void write_data(uchar com)
{
check_busy();
E=0; //预置0
RS= 1;
RW =0;//按LCD写数据控制信号设置
out = com;
E=1;// 正脉冲
_nop_();
E =0;
delay(1);
}
/********************
LCD初始化函数
********************/
void lcd_initial(void) //
{
write_command(0x38); // 八位数据,双列显示,5X7阵
_nop_();
write_command(0x0c); //开显示屏,关光标,光标不显示
_nop_();
write_command(0x06); //字符不移动,每次字符地址加1
_nop_();
write_command(0x01); //清屏
_nop_();
delay(100);
}
/********************
//字符串显函数
********************/
void string(uchar add, uchar *s)
{
write_command(add);//显示地址
while(*s != '\0')
{
write_data(*s++);
}
}
/********************
第一屏显示函数
********************/
void key_1(void)
{
lcd_initial();
string(0x83,name); //第一行第四个开始显示学号
string(0xc2,stu_num);//第二行第三个开始显示姓名
do{
key_scan();
} while(S2!=0);// 持续进行键盘扫描,如果按键2没按下,则一直显示第一屏
}
/********************
第二屏显示函数
********************/
void key_2(void)
{
lcd_initial();
string(0x83,birthplace);//第一行第三个开始显示籍贯
string(0xc3,birthday);//第二行第三个开始显示生日
do{
key_scan();
} while(S1!=0); //持续进行键盘扫描,如果按键1没按下,则一直显示第二屏
}
void key_scan(void) //独立键盘扫描函数
{
P1 =0xff;
if((P1&0x0f)!=0x0f)
{
delay(10);
if(S1==0)
{
keyvalue =1;
delay(100);
}
if(S2 == 0)
{
keyvalue =2;
delay(100);
}
}
}
void main(void) //主函数
{
lcd_initial();
while(1)
{
keyvalue =0
key_scan(); //按键扫描
switch(keyvalue) //按键值选择显示第几屏数据
{
case 1 : key_1();delay(10);break;
case 2 : key_2();delay(10);break;
}
}
}
五、仿真调试
按下按键1,显示第一屏数据,显示良好
按下按键2,显示第二屏数据,显示良好