作为单片机小白,最痛苦的莫过于从网上良莠不齐的文章中寻找自己所需知识。本人之前就非常想用LCD1602显示自定义字符(想玩点花操作),但苦于自身愚钝,对网上拷来的代码根本就不知道怎么使用,更别说清楚的了解其原理了,于是苦心专研,研究出实现自定义字符的代码。
注:
1.代码部分只讲怎么用(给那些了解基本原理不想太过深入研究只想实现现象的人使用),
至于小白可以看看后面的原理分析和代码讲解(点赞收藏数够就开坑)
2.本人使用的是普中A2版C51单片机(不是此版的单片机注意检查IO口是否不同)
3.以下放出图像证明代码可行性(是我部门作业的截图,懒得再弄):
#include
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0
/**
* @brief LCD1602延时函数,可延时1ms
* @param 无
* @retval 无
*/
void LCD_Delay()
{
unsigned char i, j;
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
/**
* @brief LCD1602写命令
* @param Command 要写入的命令
* @retval 无
*/
void LCD_WriteCommand(unsigned char Command)
{
LCD_RS=0;
LCD_RW=0;
LCD_DataPort=Command;
LCD_EN=1;
LCD_Delay();
LCD_EN=0;
LCD_Delay();
}
/**
* @brief LCD1602写数据
* @param Data 要写入的数据
* @retval 无
*/
void LCD_WriteData(unsigned char Data)
{
LCD_RS=1;
LCD_RW=0;
LCD_DataPort=Data;
LCD_EN=1;
LCD_Delay();
LCD_EN=0;
LCD_Delay();
}
/**
* @brief LCD1602初始化函数
* @param 无
* @retval 无
*/
void LCD_Init()
{
LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵
LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关
LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动
LCD_WriteCommand(0x01);//光标复位,清屏
}
/**
* @brief LCD1602设置光标位置
* @param Line 行位置,范围:1~2
* @param Column 列位置,范围:1~16
* @retval 无
*/
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
if(Line==1)
{
LCD_WriteCommand(0x80|(Column-1));
}
else if(Line==2)
{
LCD_WriteCommand(0x80|(Column-1+0x40));
}
}
/**
* @brief 在LCD1602指定位置显示自定义字符
* @param Line 起始行位置,范围:1~2
* @param Column 起始列位置,范围:1~16
* @param add 选择展示CGRAM中哪个自定义字符 1~8
* @param CG_dat[]存放LCD1602屏幕对应LED亮灭数据,
CG_dat[9]保存设置CGRAM8个地址中其中一个的第1行的指令
(规律0x40,0x48,0x50,0x58,0x60,0x58,0x70,0x78)
* @retval 无
*/
void LCD_makechar(unsigned char Line,unsigned char Column,unsigned char add,unsigned char CG_dat[])
{
unsigned char i;
//CGRAM输入自定义字符数据
for(i=0;i<8;i++)
{
LCD_WriteCommand(CG_dat[8]+i);//写入指令:设置CGRAM地址为5*8点阵的第几行
LCD_WriteData(CG_dat[i]);//把自定义字符第一行的LED灯亮灭数据写入
}
LCD_SetCursor(Line,Column);//设置光标位置(确定显示位置)
LCD_WriteData(add-1);//向DDRAM写入数据(数据为CGRAM中自定义字符的地址)
}
#ifndef __LCD1602_H__
#define __LCD1602_H__
void LCD_Init();
void LCD_WriteCommand(unsigned char Command);
void LCD_WriteData(unsigned char Data);
void LCD_makechar(unsigned char Line,unsigned char Column,unsigned char add,unsigned char CG_dat[]);
#endif
#include "regx52.h"
#include "LCD1602.h"
unsigned char code CG_dat1[]={0x1F,0x11,0x11,0x1F,0x11,0x11,0x1F,0x00,0x40};//日
unsigned char code CG_dat2[]={0x04,0x1F,0x04,0x0E,0x15,0x0E,0x04,0x00,0x48};//本
unsigned char code CG_dat3[]={0x00,0x07,0x02,0x04,0x0B,0x03,0x00,0x00,0x50};//石
unsigned char code CG_dat4[]={0x02,0x1F,0x12,0x17,0x15,0x12,0x15,0x00,0x58};//皮
unsigned char code CG_dat5[]={0x00,0x02,0x07,0x02,0x07,0x00,0x00,0x00,0x60};//土
unsigned char code CG_dat6[]={0x1F,0x04,0x04,0x0C,0x16,0x05,0x04,0x00,0x68};//不
unsigned char code CG_dat7[]={0x17,0x08,0x07,0x15,0x0F,0x05,0x12,0x06,0x70};//海
unsigned char code CG_dat8[]={0x05,0x10,0x07,0x12,0x07,0x0A,0x17,0x02,0x78};//洋
void main()
{
LCD_Init();
while(1)
{
LCD_makechar(1,1,1,CG_dat1);
LCD_makechar(1,2,2,CG_dat2);
LCD_makechar(1,3,3,CG_dat3);
LCD_makechar(1,4,4,CG_dat4);
LCD_makechar(1,5,5,CG_dat5);
LCD_makechar(1,6,6,CG_dat6);
LCD_makechar(1,7,7,CG_dat7);
LCD_makechar(1,8,8,CG_dat8);
}
}
1.把对端口的重命名和宏定义,对LCD写指令和写数据函数,LCD自定义字符相应函数放入创建的LCD1602.c文件中,复制头文件代码创建LCD1602.h
2.LCD自定义函数参数的填入:
# Line,Column是设置自定义字符在哪一行哪一列显示的
# add是选择展示CGRAM中哪个自定义字符
# CG_dat[ ] LCD1602屏幕对应字符LED亮灭的8组数据+设置CGRAM8个地址中其中一个的第1行的指令(这句话看不懂没关系,你只需知道如何得到字符LED亮灭的8组数据和add与CG_dat[8]的对应关系规律即可)
以"今"字为例,得到字符LED亮灭的8组数据方法如下:
1.打开字模取模软件新建图像(8*8),并绘制你想要的汉字
2.点击C51格式生成数据并赋值数据到创建的CG_dat1[ ]中
如上面主函数部分CG_dat1[ ]={0x04,0x0A,0x15,0x00,0x1F,0x01,0x02,0x04,};
(现在只有 LCD1602屏幕对应字符LED亮灭的8组数据,还要加上设置CGRAM8个地址中其中一个的第1行的指令)
3.值得注意的是:注意参数是横向取模
然后(8*8)点阵左边三列不能绘制(这个很重要!!!!!!)
add与CG_dat[8]的对应关系规律如下:
1对应0x40 2对应0x48
3对应0x50 4对应0x58
5对应0x60 6对应0x68
7对应0x70 8对应0x78
如我要把"今"字设置在CGRAM的第一个地址,则add为1,根据对应关系可得CG_dat[8]=0x40
所以"今"字创建的数据为
unsigned char code CG_dat1[]={0x04,0x0A,0x15,0x00,0x1F,0x01,0x02,0x04,0x40};
要是实在看不懂就看看主函数就懂了
由于只能定义8个字符,所以海洋两个字有点丑,见谅哈
另外提一下小技巧就是复杂的汉字(无法用单个5*8点阵显示的)可以用两个点阵来同时显示
1.如果成功实现LCD1602自定义字符,别忘了给视频点个赞哦!!!!!
(拜托拜托,这对我非常重要,这文章都肝了一晚上都T_T)
2.等过几天看看文章的反响如何,好的话速更LCD1602基本原理,自定义字符实现原理以及实现LCD1602滚动字幕和显示5*10点阵的字符等一系列函数
3.最近几天真的被日本的那些政客的丑恶嘴脸和恶劣行径恶心坏了,日本擅排核污水这一自私,疯狂,反人类,反自然的行为,必将受到全人类和大自然的惩罚!!!!——8月24后日本排海的第二天晚上记下