企业在网站推广,wordpress插件找回,简单干净的网站,wordpress设置视频51单片机控制1602LCD显示屏输出自定义字符二
1.概述
1602LCD除了内置的字符外还提供自定义字符功能#xff0c;当内置的字符中没有我们想要输出的字符时#xff0c;我们就可以自己创造字符让他显示#xff0c;下面介绍1602如何创建自定义字符。
2.1602LCD创建字符原理
自…51单片机控制1602LCD显示屏输出自定义字符二
1.概述
1602LCD除了内置的字符外还提供自定义字符功能当内置的字符中没有我们想要输出的字符时我们就可以自己创造字符让他显示下面介绍1602如何创建自定义字符。
2.1602LCD创建字符原理
自定义字符涉及到三个存储器弄清楚他们的作用后就可以自定义字符。下面详细介绍三个存储器对自定义字符产生的作用。
自定义字符输出原理 程序指定CGROM地址——CGROM查找地址关联的CGRAM地址——CGRAM查找该地对应的自定义字符——输出到1602LCD屏幕。
CGROM
CGROM是1602内置字符的存储器在里面固化了常用的字符当我们输出字母数字字符时1602芯片在CGROM中查找字符对应的地址然后将该地址输出在LCD显示字符。 假如我们输出的字符在CGROM中没有内置这个时候我们可以自己定义需要输出的字符。CGROM为我我们预留了8个CGRAM位置用来输出自定义的字符。也就是说我们最多可以存储8个自定义字符。
内置指令表
查看内置指令表CGRAM地址有6位D0~D5六位是CGRAM存放自定义字符地址D6为1所以它的起始地址是从0x40开始。
CGRAM地址表
D0~D5是如何存放自定义字符就要看下面CGRAM地址表格。CGRAM Address将6位地址划分为两类左边(5,4,3)为高三位对应字符存放地址。3位从001 ~ 111组合后刚好是8个地址存放8个自定义字符。
右边(2,1,0) 为低三位对应自定义字符的8个字节表中CGRAM data是构造一个字符内容该字符每行是8位一个字节有8行组成每个字符是需要8个在字节存储因此地址中的低3位从001 ~ 111组合后刚好是8个地址存放一个字符。
例如我们构造一个大写的一 字符它的数组是
// 数组中每个元素代表字符的一行一共8行。
//LCD显示的字符是5x8点阵因此一行只有5位0x1f1表示第5位为1f表示后面4位为1
unsigned char str[] {0x00,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,};CGRAM 与CGROM对应关系
了解了CGRAM内置指令和地址表就可以构造自定义的字符存放到CGRAM中下一步就是将CGRAM地址中的字符与CGROM地址进行关联这样LCD就可以从CGROM地址中找到CGRAM地址通过CGRAM地址找到字符。
1602LCD已经将CGRAM和CGROM地址进行的关联他们的关系如下图。 例如 CGRAM第一个字符的位置是(0x40-0x47) 对应CGROM地址是0X00当程序中输出内容的地址是0x00就会找到CGRAM第一个字符输出到1602LCD屏幕上。 3.1602LCD创建字符实例
下面的实例中创建了LCDWriteCGRAM函数实现创建自定义字符功能。
首先设置自定义字符存放在CGRAM的位置LCD1602_WriteCMD(0x40);将自定义字符内容存入CGRAMfor(i0;i8;i){LCD1602_WriteData(str[i]);}设置LCD显示字符位置 LCD1602_WriteCMD(0x80| 0x05);指定输出字符的CGROM地址LCD1602_WriteData(0x00);
unsigned char code str[] {0x00,0x00,0x00,0x00,0x1f,0x00,0x00,0x00};
void LCDWriteCGRAM(){//构造自定义字符unsigned char i;//自定义字符存放在CGRAM的第一个位置0x40-0x47LCD1602_WriteCMD(0x40);//存放自定义字符内容for(i0;i8;i){LCD1602_WriteData(str[i]);}//显示字符LCD1602_WriteCMD(0x80| 0x05);//CGRAM第一个位置对应CGROM的0x00地址LCD1602_WriteData(0x00);}完整代码
#include STC12C2052AD.H
typedef unsigned char uint8;
// 定义引脚
#define LCD1602_DB0_DB7 P1 // 定义LCD1602的数据总线
sbit LCD1602_RS P3 ^ 2; // 定义LCD1602的RS控制线
sbit LCD1602_RW P3 ^ 3; // 定义LCD1602的RW控制线
sbit LCD1602_E P3 ^ 4; // 定义LCD1602的E控制线
sbit LCD1602_Busy P1 ^ 7; // 定义LCD1602的测忙线与LCD1602_DB0_DB7关联// 定义指令集
/*设置显示模式*/
#define LCD_MODE_PIN8 0x38 // 8位数据线两行显示
#define LCD_MODE_PIN4 0x28 // 4位数据线两个显示
#define LCD_SCREEN_CLR 0x01 // 清屏
#define LCD_CURSOR_RET 0x02 // 光标复位
#define LCD_CURSOR_RIGHT 0x06 // 光标右移显示不移动
#define LCD_CURSOR_LEFT 0x04 // 光标左移显示不移动
#define LCD_DIS_MODE_LEFT 0x07 // AC自增画面左移
#define LCD_DIS_MODE_RIGHT 0X05 // AC自增画面右移/*光标开关控制*/
#define LCD_DIS_CUR_BLK_ON 0x0f // 显示开光标开光标闪烁
#define LCD_DIS_CUR_ON 0x0e // 显示开光标开光标不闪烁
#define LCD_DIS_ON 0x0c // 显示开光标关光标不闪烁
#define LCD_DIS_OFF 0x08 // 显示关光标关光标不闪烁/*光标、显示移动*/
#define LCD_CUR_MOVE_LEFT 0x10 // 光标左移
#define LCD_CUR_MOVE_RIGHT 0x14 // 光标右移
#define LCD_DIS_MOVE_LEFT 0x18 // 显示左移
#define LCD_DIS_MOVE_RIGHT 0x1c // 显示右移/**
LCD1602忙碌状态不会接收新指令因此在发送新指令前先检测是否忙碌。
判断LCD1602_Busy变量的值为低电平则为不忙。
*/
void LCD1602_TestBusy(void){LCD1602_DB0_DB7 0xff; //将数据引脚置为高电平LCD1602_RS 0; // 指令状态LCD1602_RW 1; // 读状态LCD1602_E 1; // 打开LCD显示器读指令while(LCD1602_Busy); //读取LCD1602_Busy(P1.7)为低电平则结束循环LCD1602_E 0; // 关闭LCD显示器读指令
}/********************************************************************************************
// 写指令程序 //
// 向LCD1602写命令 本函数需要1个指令集的入口参数 //
/********************************************************************************************/
void LCD1602_WriteCMD(uint8 LCD1602_command) { LCD1602_TestBusy();//输入的命令赋值给LCD1602_DB0_DB7LCD1602_DB0_DB7 LCD1602_command;LCD1602_RS 0;LCD1602_RW 0;LCD1602_E 1;LCD1602_E 0;
}
/********************************************************************************************
// 写数据程序 //
// 向LCD1602写数据 //
/********************************************************************************************/
void LCD1602_WriteData(uint8 LCD1602_data){ LCD1602_TestBusy();LCD1602_DB0_DB7 LCD1602_data;LCD1602_RS 1;LCD1602_RW 0;LCD1602_E 1;LCD1602_E 0;
}// LCD1602初始化
void LCD1602_Init(void){LCD1602_WriteCMD(LCD_MODE_PIN8); // 显示模式设置显示2行每个字符为5*7个像素LCD1602_WriteCMD(LCD_DIS_ON); // 显示开及光标设置显示开光标关LCD1602_WriteCMD(LCD_CURSOR_RIGHT); //显示光标移动设置文字不动光标右移LCD1602_WriteCMD(LCD_SCREEN_CLR); // 显示清屏
}/*
输出字符串
x数据地址
y输出的行位置第一行和第二行
str输入字符串
*/
void print(uint8 x, uint8 y, uint8 *str){if(0 y){LCD1602_WriteCMD(0x80 | x);}else{// 第二行起始位置是0x40LCD1602_WriteCMD(0x80 | (0x40x));}while(*str ! \0){LCD1602_WriteData(*str);}}unsigned char code str[] {0x00,0x00,0x00,0x00,0x1f,0x00,0x00,0x00};
void LCDWriteCGRAM(){//构造自定义字符unsigned char i;//自定义字符存放在CGRAM的第一个位置0x40-0x47LCD1602_WriteCMD(0x40);//存放自定义字符内容for(i0;i8;i){LCD1602_WriteData(str[i]);}//显示字符LCD1602_WriteCMD(0x80| 0x05);//CGRAM第一个位置对应CGROM的0x00地址LCD1602_WriteData(0x00);}void main(){unsigned char str1[] Beyound Self;LCD1602_Init();// 显示自定义内容LCDWriteCGRAM();print(0x00,1,str1);while(1);}
优化自定义字符函数
上面创建的LCDWriteCGRAM函数有缺陷每当需要改变字符存放CGRAM位置或者修改LCD显示位置都需要修改这个函数因此对他进行优化将变化的内容提取为参数。成为一个工具函数每次只需要传入参数就可以输出不同的字符。
LCDSetChar函数封装了自定义内容功能该函数设计思想如下
首先定义参数包含字符在LCD显示的位置CGROM位置字符内容 xLCD显示字符位置y设置字符在LCD显示的行pos设置CGRAM位置str字符内容 构造自定义字符包含两个部分 设置字符在CGRAM存储位置设置字符内容 设置字符显示 设置字符在LCD哪个位置显示设置LCD显示哪个字符
/*
xLCD显示字符位置
y设置字符在LCD显示的行
pos设置CGRAM位置
str字符内容
*/
void LCDSetChar(unsigned char x, unsigned char y, unsigned char pos, unsigned char *str){unsigned char i;// 1.构造自定义字符确定CGRAM位置for(i0;i8;i){/*确定CGRAM位置0x40是CGRAM第一个起始位置pos是设置第几个位置一共8个。*/LCD1602_WriteCMD(0x40pos*8i );// 构造自定义字符LCD1602_WriteData(*(stri));}// 2.显示字符// 设置字符在LCD显示的位置if(0 y){LCD1602_WriteCMD(0x80 | x);}else{// 第二行起始位置是0x40LCD1602_WriteCMD(0x80 | (0x40x));}// LCD显示字符内容该地址是CGROMLCD1602_WriteData(0x00pos);
}完整代码
#include STC12C2052AD.H
typedef unsigned char uint8;
// 定义引脚
#define LCD1602_DB0_DB7 P1 // 定义LCD1602的数据总线
sbit LCD1602_RS P3 ^ 2; // 定义LCD1602的RS控制线
sbit LCD1602_RW P3 ^ 3; // 定义LCD1602的RW控制线
sbit LCD1602_E P3 ^ 4; // 定义LCD1602的E控制线
sbit LCD1602_Busy P1 ^ 7; // 定义LCD1602的测忙线与LCD1602_DB0_DB7关联// 定义指令集
/*设置显示模式*/
#define LCD_MODE_PIN8 0x38 // 8位数据线两行显示
#define LCD_MODE_PIN4 0x28 // 4位数据线两个显示
#define LCD_SCREEN_CLR 0x01 // 清屏
#define LCD_CURSOR_RET 0x02 // 光标复位
#define LCD_CURSOR_RIGHT 0x06 // 光标右移显示不移动
#define LCD_CURSOR_LEFT 0x04 // 光标左移显示不移动
#define LCD_DIS_MODE_LEFT 0x07 // AC自增画面左移
#define LCD_DIS_MODE_RIGHT 0X05 // AC自增画面右移/*光标开关控制*/
#define LCD_DIS_CUR_BLK_ON 0x0f // 显示开光标开光标闪烁
#define LCD_DIS_CUR_ON 0x0e // 显示开光标开光标不闪烁
#define LCD_DIS_ON 0x0c // 显示开光标关光标不闪烁
#define LCD_DIS_OFF 0x08 // 显示关光标关光标不闪烁/*光标、显示移动*/
#define LCD_CUR_MOVE_LEFT 0x10 // 光标左移
#define LCD_CUR_MOVE_RIGHT 0x14 // 光标右移
#define LCD_DIS_MOVE_LEFT 0x18 // 显示左移
#define LCD_DIS_MOVE_RIGHT 0x1c // 显示右移/**
LCD1602忙碌状态不会接收新指令因此在发送新指令前先检测是否忙碌。
判断LCD1602_Busy变量的值为低电平则为不忙。
*/
void LCD1602_TestBusy(void){LCD1602_DB0_DB7 0xff; //将数据引脚置为高电平LCD1602_RS 0; // 指令状态LCD1602_RW 1; // 读状态LCD1602_E 1; // 打开LCD显示器读指令while(LCD1602_Busy); //读取LCD1602_Busy(P1.7)为低电平则结束循环LCD1602_E 0; // 关闭LCD显示器读指令
}/********************************************************************************************
// 写指令程序 //
// 向LCD1602写命令 本函数需要1个指令集的入口参数 //
/********************************************************************************************/
void LCD1602_WriteCMD(uint8 LCD1602_command) { LCD1602_TestBusy();//输入的命令赋值给LCD1602_DB0_DB7LCD1602_DB0_DB7 LCD1602_command;LCD1602_RS 0;LCD1602_RW 0;LCD1602_E 1;LCD1602_E 0;
}
/********************************************************************************************
// 写数据程序 //
// 向LCD1602写数据 //
/********************************************************************************************/
void LCD1602_WriteData(uint8 LCD1602_data){ LCD1602_TestBusy();LCD1602_DB0_DB7 LCD1602_data;LCD1602_RS 1;LCD1602_RW 0;LCD1602_E 1;LCD1602_E 0;
}// LCD1602初始化
void LCD1602_Init(void){LCD1602_WriteCMD(LCD_MODE_PIN8); // 显示模式设置显示2行每个字符为5*7个像素LCD1602_WriteCMD(LCD_DIS_ON); // 显示开及光标设置显示开光标关LCD1602_WriteCMD(LCD_CURSOR_RIGHT); //显示光标移动设置文字不动光标右移LCD1602_WriteCMD(LCD_SCREEN_CLR); // 显示清屏
}/*
输出字符串
x数据地址
y输出的行位置第一行和第二行
str输入字符串
*/
void print(uint8 x, uint8 y, uint8 *str){if(0 y){LCD1602_WriteCMD(0x80 | x);}else{// 第二行起始位置是0x40LCD1602_WriteCMD(0x80 | (0x40x));}while(*str ! \0){LCD1602_WriteData(*str);}}/*
xLCD显示字符位置
y设置字符在LCD显示的行
pos设置CGRAM位置
str字符内容
*/
void LCDSetChar(unsigned char x, unsigned char y, unsigned char pos, unsigned char *str){unsigned char i;// 1.构造自定义字符确定CGRAM位置for(i0;i8;i){/*确定CGRAM位置0x40是CGRAM第一个起始位置pos是设置第几个位置一共8个。*/LCD1602_WriteCMD(0x40pos*8i );// 构造自定义字符LCD1602_WriteData(*(stri));}// 2.显示字符// 设置字符在LCD显示的位置if(0 y){LCD1602_WriteCMD(0x80 | x);}else{// 第二行起始位置是0x40LCD1602_WriteCMD(0x80 | (0x40x));}// LCD显示字符内容该地址是CGROMLCD1602_WriteData(0x00pos);
}void main(){unsigned char str1[] Beyound Self;unsigned char code c1[] {0x00,0x00,0x00,0x00,0x1f,0x00,0x00,0x00};LCD1602_Init();// 显示自定义内容LCDSetChar(3,0,0,c1);print(0x00,1,str1);while(1);}
预装8个自定义字符
如果8个字符已经定义好还可以一次全部存储在CGRAM中使用时候直接调用。
CgramWrite函数一次读取8个字符print2函数用来输出字符
uint8 code Xword[]{0x18,0x18,0x07,0x08,0x08,0x08,0x07,0x00, //℃代码 0x000x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00, //一代码 0x010x00,0x00,0x00,0x0e,0x00,0xff,0x00,0x00, //二代码 0x020x00,0x00,0xff,0x00,0x0e,0x00,0xff,0x00, //三代码 0x030x00,0x00,0xff,0xf5,0xfb,0xf1,0xff,0x00, //四代码 0x040x00,0xfe,0x08,0xfe,0x0a,0x0a,0xff,0x00, //五代码 0x050x00,0x04,0x00,0xff,0x00,0x0a,0x11,0x00, //六代码 0x060x00,0x1f,0x11,0x1f,0x11,0x11,0x1f,0x00, //日代码 0x07
};
void CgramWrite(void) { // 装入CGRAM //unsigned char i;LCD1602_WriteCMD(0x06); // CGRAM地址自动加1LCD1602_WriteCMD(0x40); // CGRAM地址设为从第一个位置开始for(i0;i64;i) {LCD1602_WriteData(Xword[i]);// 按数组写入数据}
}// aLCD显示位置 b显示哪个字符
void print2(unsigned char a,unsigned char t){LCD1602_WriteCMD(a | 0x80);LCD1602_WriteData(t);
}void main(){LCD1602_Init();CgramWrite();while(1){print2(0x01,0x00);print2(0x03,0x01);print2(0x05,0x02);print2(0x07,0x03);print2(0x09,0x04);print2(0x0b,0x05);print2(0x0d,0x06);print2(0x0f,0x07);}}