【蓝桥杯——单片机学习笔记】十八.LCD1602显示自制动画(STC15F2K60S2)

lcd1602的基础操作和配置可查看12章讲解!
在这里插入图片描述

一.原理

基础回顾:
1. lcd1602一个字符的显示是宽5个像素高8个像素,一共40个像素。其中每行的5个像素是由1个字节的低5位控制,高3位不起作用(此处需要注意,后面创建图形需要考虑到)。所以一个字符的显示要8个字节;
在这里插入图片描述
2. 由lcd1602的使用手册可知,其用户字模存储区CGRAM是6位地址(即64个地址),每个地址可存入1个字节的数据。因此,CGRAM最多可存入8个完整字符
3. 动态的制作也是利用视觉残留现象,短时间播放多帧画面。

二.图形模型的创建

由上面动图可见,我使用左边8个字符位置显示图形(即一幅图片宽20,高16),一帧图片8个字符显示的顺序为从左至右,从上至下(即先显示第一行4个字符,再显示第2行4个字符)。
取字模的软件为PCtoLCD2002。

1.设置显示区大小

图片的宽度需保留完整字节的大小,把高3位空出来,因此宽度设为32。
在这里插入图片描述

2.字模输出设置

在这里插入图片描述

3.依据所设计的图形,一帧帧绘制出来。

设计的图形
在这里插入图片描述
逐帧绘制:
第一帧:
在这里插入图片描述
第二帧:
在这里插入图片描述
第n帧:

4.注意事项

实际需要显示的顺序:
在这里插入图片描述
代码生成字模的顺序:
在这里插入图片描述

由于此字模软件无法按需要显示的顺序输出,因此在代码中需要适当更改。
例如字模软件的输出为:

	{0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,	//实际显示的第1个字符
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,			//第5个字符
	0x1F,0x1F,0x1F,0x1F,0x1C,0x1F,0x1F,0x1F,	//第2个字符
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,			//第6个字符
	0x1F,0x1F,0x1F,0x1F,0x07,0x1F,0x1F,0x1F,	//第3个字符
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,			//第7个字符
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,	//第4个字符
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F},			//第8个字符	

三.代码与注释

#include "stc15.h"
#include "intrins.h"

#define LCD1602_DB P0
sbit LCD1602_RS=P2^0;  //RS,数据/命令选择端(H/L)
sbit LCD1602_RW=P2^1;  //R/W,读/写选择端(H/L)
sbit LCD1602_E=P1^2;  // E,使能信号

//共有17帧
unsigned char code picture[17][64]=	
{
	//第一帧
	{0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,	//第1个字符
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,			//第5个字符
	0x1F,0x1F,0x1F,0x1F,0x1C,0x1F,0x1F,0x1F,	//第2个字符
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,			//第6个字符
	0x1F,0x1F,0x1F,0x1F,0x07,0x1F,0x1F,0x1F,	//第3个字符
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,			//第7个字符
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,	//第4个字符
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F},			//第8个字符		

	//第二帧
	{0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x19,0x1C,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x13,0x07,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F},

	{0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x13,0x19,0x1C,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x19,0x13,0x07,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F},

	{0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x07,0x13,0x19,0x1C,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x1C,0x19,0x13,0x07,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F},
	
	{0x1F,0x1C,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x07,0x13,0x19,0x1C,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x1C,0x19,0x13,0x07,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x07,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F},

	{0x1F,0x1C,0x19,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x07,0x13,0x19,0x1C,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x1C,0x19,0x13,0x07,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x07,0x13,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F},

	{0x1F,0x1C,0x19,0x13,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x07,0x13,0x19,0x1C,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x1C,0x19,0x13,0x07,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x07,0x13,0x19,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F},

	{0x1F,0x1C,0x19,0x13,0x17,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x07,0x13,0x19,0x1C,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x1C,0x19,0x13,0x07,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x07,0x13,0x19,0x1D,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F},

	{0x1F,0x1C,0x19,0x13,0x17,0x17,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x07,0x13,0x19,0x1C,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x1C,0x19,0x13,0x07,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x07,0x13,0x19,0x1D,0x1D,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F},

	{0x1F,0x1C,0x19,0x13,0x17,0x17,0x13,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x07,0x13,0x19,0x1C,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x1C,0x19,0x13,0x07,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x07,0x13,0x19,0x1D,0x1D,0x19,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F},

	{0x1F,0x1C,0x19,0x13,0x17,0x17,0x13,0x19,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x07,0x13,0x19,0x1C,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x1C,0x19,0x13,0x07,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x07,0x13,0x19,0x1D,0x1D,0x19,0x13,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F},

	{0x1F,0x1C,0x19,0x13,0x17,0x17,0x13,0x19,
	0x1C,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x07,0x13,0x19,0x1C,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x1C,0x19,0x13,0x07,0x1F,0x1F,0x1F,
	0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x07,0x13,0x19,0x1D,0x1D,0x19,0x13,
	0x07,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F},

	{0x1F,0x1C,0x19,0x13,0x17,0x17,0x13,0x19,
	0x1C,0x1E,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x07,0x13,0x19,0x1C,0x1F,0x1F,0x1F,
	0x1F,0x0F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x1C,0x19,0x13,0x07,0x1F,0x1F,0x1F,
	0x1F,0x1E,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x07,0x13,0x19,0x1D,0x1D,0x19,0x13,
	0x07,0x0F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F},

	{0x1F,0x1C,0x19,0x13,0x17,0x17,0x13,0x19,
	0x1C,0x1E,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x07,0x13,0x19,0x1C,0x1F,0x1F,0x1F,
	0x1F,0x0F,0x07,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x1C,0x19,0x13,0x07,0x1F,0x1F,0x1F,
	0x1F,0x1E,0x1C,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x07,0x13,0x19,0x1D,0x1D,0x19,0x13,
	0x07,0x0F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F},

	{0x1F,0x1C,0x19,0x13,0x17,0x17,0x13,0x19,
	0x1C,0x1E,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x07,0x13,0x19,0x1C,0x1F,0x1F,0x1F,
	0x1F,0x0F,0x07,0x13,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x1C,0x19,0x13,0x07,0x1F,0x1F,0x1F,
	0x1F,0x1E,0x1C,0x19,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x07,0x13,0x19,0x1D,0x1D,0x19,0x13,
	0x07,0x0F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F},

	{0x1F,0x1C,0x19,0x13,0x17,0x17,0x13,0x19,
	0x1C,0x1E,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x07,0x13,0x19,0x1C,0x1F,0x1F,0x1F,
	0x1F,0x0F,0x07,0x13,0x19,0x1F,0x1F,0x1F,
	0x1F,0x1C,0x19,0x13,0x07,0x1F,0x1F,0x1F,
	0x1F,0x1E,0x1C,0x19,0x13,0x1F,0x1F,0x1F,
	0x1F,0x07,0x13,0x19,0x1D,0x1D,0x19,0x13,
	0x07,0x0F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F},


	{0x1F,0x1C,0x19,0x13,0x17,0x17,0x13,0x19,
	0x1C,0x1E,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
	0x1F,0x07,0x13,0x19,0x1C,0x1F,0x1F,0x1F,
	0x1F,0x0F,0x07,0x13,0x19,0x1C,0x1E,0x1F,
	0x1F,0x1C,0x19,0x13,0x07,0x1F,0x1F,0x1F,
	0x1F,0x1E,0x1C,0x19,0x13,0x07,0x0F,0x1F,
	0x1F,0x07,0x13,0x19,0x1D,0x1D,0x19,0x13,
	0x07,0x0F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F},
};

//读状态
void read_state(void)
{
	unsigned char sta;			//状态读取存储变量
	LCD1602_DB=0xff;
	LCD1602_RS=0;
	LCD1602_RW=1;
	LCD1602_E=1;
	do
	{
		LCD1602_E=1;
		sta=LCD1602_DB;//把状态字读取到sta变量中,可通过最高位判断液晶是否处于忙态,1时为忙 
		LCD1602_E=0;//释放总线,防止影响其他模块
	}while(sta&0x80);
}

//写命令
void write_cmd(unsigned char cmd)
{
	read_state();
	LCD1602_RS=0;					 //RS=0->指令
	LCD1602_RW=0;					 //R/W=0->写
	LCD1602_DB=cmd;
	LCD1602_E=1;	
	LCD1602_E=0;			
}
 
//写数据
void write_data(unsigned char date)
{
	read_state();
	LCD1602_RS=1;					 //RS=1->数据
	LCD1602_RW=0;	
	LCD1602_DB=date;
	LCD1602_E=1;
	LCD1602_E=0;
}

//LCD初始化
void lcd_init()
{				
	LCD1602_E=0;		 //使能关(操作前关使能使用时打开)
	write_cmd(0x3c);     //设置16*2显示,5*8点阵,8位数据口
	write_cmd(0x0c);     //设置开显示,不显示光标
	write_cmd(0x06);     //设置写一个字符后地址指针自动加1
	write_cmd(0x01);     //显示清0,数据指针清0
}

//把字符写入用户字模RAM
void Write_CGRAM(void)
{
	static unsigned char i=0;	//帧数
	unsigned char j,k;//j为字符的序号,k为每个字符的行序号
	
	for(j=0;j<8;j++)
	{
		write_cmd(0x40+j*8);	//此处的0x40为写入CGRAM命令的固定位,
								//不理解可以看12节,j*8为对应地址
		//此处的写入数据即将输出的字模转为所需的显示顺序依次存入CGRAM
		if(j<4)		//先将第一行4个字符存入
		{
			for(k=0;k<8;k++)
			{
				write_data(picture[i][2*8*j+k]);
			}
		}
		else	//再存入第二行4个字符
		{
			for(k=0;k<8;k++)
			{
				write_data(picture[i][2*8*(j-4)+8+k]);
			}
		}
	}
	
	i++;
	if(i==17)
		i=0;
}

//LCD显示一帧画面
void display()
{	
		unsigned char m;
		//按顺序把CGRAM中的字符存入DDRAM中进行显示
		write_cmd(0x80);
		for(m=0;m<4;m++)
		{
			write_data(m);	//从CGRAM中进行显示直接输出对应字符序号即可
		}	
		write_cmd(0xc0);
		for(m=0;m<4;m++)
		{
			write_data(m+4);
		}
}
//100ms延时
void Delay100ms()		//@11.0592MHz
{
	unsigned char i, j, k;

	_nop_();
	_nop_();
	i = 5;
	j = 52;
	k = 195;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}

void main()
{
	lcd_init();
	while(1)
	{
		Write_CGRAM();
		display();
		Delay100ms();	//适当延时,10帧/s
	}
}
  • 9
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
下面是STC15F2K60S2单片机LCD1602显示代码,您可以参考一下: ``` #include <reg52.h> #include <intrins.h> #define uint unsigned int #define uchar unsigned char sbit RS=P3^5; sbit RW=P3^6; sbit EN=P3^4; void delay_ms(uint xms) { uint i,j; for(i=xms;i>0;i--) for(j=110;j>0;j--); } void Write_Command(uchar Command) { RS=0; RW=0; P0=Command; EN=1; _nop_(); _nop_(); EN=0; } void Write_Data(uchar Data) { RS=1; RW=0; P0=Data; EN=1; _nop_(); _nop_(); EN=0; } void Init_Lcd1602() { Write_Command(0x38); delay_ms(5); Write_Command(0x38); delay_ms(5); Write_Command(0x38); delay_ms(5); Write_Command(0x0c); delay_ms(5); Write_Command(0x01); delay_ms(5); Write_Command(0x06); delay_ms(5); } void Display_Lcd1602(uchar x,uchar y,uchar *String) { uchar i; if(x==0) Write_Command(0x80+y); else Write_Command(0xc0+y); for(i=0;String[i]!='\0';i++) Write_Data(String[i]); } void main() { Init_Lcd1602(); Display_Lcd1602(0,0,"Hello,World!"); Display_Lcd1602(1,3,"Goodbye!"); while(1); } ``` 在此代码中,我们使用了P3.4、P3.5和P3.6三个引脚来控制LCD1602屏幕的显示。其中,RS接在P3.5上,RW接在P3.6上,EN接在P3.4上。 在主函数中,我们首先调用Init_Lcd1602()函数来初始化LCD1602屏幕。然后,我们使用Display_Lcd1602()函数来在屏幕上显示"Hello,World!"和"Goodbye!"两个字符串。 请注意,此代码中的delay_ms()函数是用来延时的,它的作用是等待一段时间,以确保LCD1602屏幕的操作被执行。在实际应用中,您可以根据需要调整延时的时间。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

默默无闻小菜鸡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值