目录
一、LCD显示字符
1、写指令
(1)、LCD状态配置
(2)、显示开关与光标
2、写数据
(1)、设置地址
(2)、设置数据
3、初始化代码
(1)、初始化流程
(2)、初始化代码
4、数据显示
(1)、地址写入
(2)、数据写入
二、按键控制LED流水灯-总线与网络标号
1、原理图
2、代码
一、LCD显示字符
打开LCD1602的控制时序图,其采用了HD44780及兼容芯片,可以看到:
当然一般对LCD,我们都是写指令和写输入,可以先不看读的部分,注意到写指令和写数据最重要的就是RS控制进行区分。
1、写指令
(1)、LCD状态配置
看手册关于指令码,常用的有4.1.1,00111000=0x38;
(2)、显示开关与光标
显示开、关与光标设置,一般如果不进行输入操作的时候不显示光标,而在每次上电的时候,最好先设置关显示,进行清屏后再打开,因此一般为00001100/00001000即0X0C/0X08;
2、写数据
(1)、设置地址
可以看到通过输入80H+地址码设置好要写的地方,即对应上面的图。
(2)、设置数据
3、初始化代码
(1)、初始化流程
手册也提供了一个比较好的初始化流程:
(2)、初始化代码
void LCD1602_init(void)
{
Delay1602(1500); //调用延时函数
LCD1602_Write_com(0x38); //8位数据总线,两行显示模式,5*7点阵显示
Delay1602(500); //调用延时函数
LCD1602_Write_com(0x38); //8位数据总线,两行显示模式,5*7点阵显示
Delay1602(500); //调用延时函数
LCD1602_Write_com(0x38); //8位数据总线,两行显示模式,5*7点阵显示
LCD1602_Write_com_busy(0x38); //8位数据总线,两行显示模式,5*7点阵显示
LCD1602_Write_com_busy(0x08); //显示功能关,无光标
LCD1602_Write_com_busy(0x01); //清屏
LCD1602_Write_com_busy(0x06); //写入新的数据后,光标右移,显示屏不移动
LCD1602_Write_com_busy(0x0C); //显示功能开,无光标
}
相关的寄存器设置都在上面进行了清晰的展示。
前面说到写数据需要检测忙或者不检测,因此需要进行两个代码进行展示
①不忙写入
//1602液晶相关I/O设置
sbit E=P2^3; //1602液晶的E脚接在P2.3口上
sbit RW=P2^4; //1602液晶的RW脚接在P2.4口上
sbit RS=P2^5; //1602液晶的RS脚接在P2.5口上
//写指令 不检测忙信号
void LCD1602_Write_com(unsigned char combuf)
{
RS=0; //选择指令寄存器
RW=0; //选择写状态
P0=combuf; //将命令字通过P0口送至DB
E=1; //E高电平将命令字写入1602液晶
E=0; //写完以后,恢复E的电平
}
②忙检测
void LCD1602_busy(void)
{
P0_7=1; //将P0.7置1,为读状态做准备
RS=0; //RS=0、RW=1、E=1时,忙信号输出到DB7,由P0.7读入
RW=1; //RS=0、RW=1、E=1时,忙信号输出到DB7,由P0.7读入
E=1; //RS=0、RW=1、E=1时,忙信号输出到DB7,由P0.7读入
while(P0_7==1); //由P0.7读入1,表示1602液晶忙,需要等待
//单片机处理完当前任务,忙信号P0_7自动置0(无效),即不忙
E=0; //读完以后,恢复E的电平
}
本质上忙检测就是检测那个IO是否被LCD置位0。
4、数据显示
(1)、地址写入
void LCD1602_Write_address(unsigned char x,unsigned char y)
{
x&=0x0f; //列地址限制在0-15间
y&=0x01; //行地址限制在0-1间
if(y==0) //如果是第一行
LCD1602_Write_com_busy(x|0x80); //将列地址写入
else //如果是第二行
LCD1602_Write_com_busy((x+0x40)|0x80); //将列地址写入
//x列数加上0x40是要从第二行的40的存储单元算起。1602共2行(每行40个存储单元)
}
前文提到,需要地址码+0X80,在数据语言中,|可以用来表示加法,但是如果直接用0-27、40-67在用户态很麻烦,因此一般用户端就写具体的行列,加地址在bsp驱动层完成。
(2)、数据写入
直接调用LCD1602_Write_data_busy即可,写入的就是char字符,如果要多次显示,则多次调用即可。
LCD1602_Disp(0,0,DISbuf/100+'0'); //在第1行的第1列显示百位
LCD1602_Disp(1,0,(DISbuf%100)/10+'0'); //在第1行的第2列显示十位
LCD1602_Disp(2,0,DISbuf%10+'0'); //在第1行的第3列显示个位
二、按键控制LED流水灯-总线与网络标号
1、原理图
可以看到本次采用了一个总线方式的连接,同时放置了网络标号。
通过此总线可以放置蓝色的线,点击放置连线标号,输入字符串例如t1、再点击另一端也输入t1,即可实现该两端连接。
2、代码
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
//延时
void DelayMS(uint x)
{
uchar i;
while(x--)
{
for(i=0;i<120;i++);
}
}
//主程序
void main()
{
uchar i;
P2=0x01;
while(1)
{
for(i=0;i<7;i++)
{
P2=_crol_(P2,1); //P2的值向左循环移动
DelayMS(150);
}
for(i=0;i<7;i++)
{
P2=_cror_(P2,1); //P2的值向右循环移动
DelayMS(150);
}
}
}