51 個のマイクロコントローラーが 1602LCD ディスプレイ画面を制御して、カスタマイズされた文字を出力します 2
1。概要
1602LCD には、内蔵文字以外に外字機能も用意されており、内蔵文字の中に出力したい文字がない場合、独自に文字を作成して表示することができます。
2.1602LCDキャラクター作成原理
外字には3つのメモリがあり、その機能を理解した上で、文字をカスタマイズすることができます。以下に、3 つの記憶が外字に及ぼす影響について詳しく説明します。
外字出力の原理:
CGROMアドレスを指定→CGROMがそのアドレスに対応するCGRAMアドレスを検索→CGRAMがその位置に対応する外字を検索→1602LCD画面に出力。
CGROM
CGROM は 1602 に内蔵されている、よく使われる文字を固めたキャラクタメモリで、英数字を出力する際、1602 チップはその文字に対応するアドレスを CGROM から検索し、そのアドレスを出力して LCD に文字を表示します。 。
出力する文字が CGROM に組み込まれていない場合は、この時点で出力する必要がある文字を自分で定義できます。CGROM は、カスタマイズされた文字を出力するために 8 つの CGRAM ロケーションを予約しています。これは、最大 8 つのカスタム文字を保存できることを意味します。
組み込みコマンドリスト
内蔵命令テーブルを確認してください CGRAMアドレスは6ビットあります D0~D5の6ビットは外字を格納するCGRAMアドレスです D6は1なので先頭アドレスは 0x40 から始まります
CGRAMアドレステーブル
D0~D5 に外字をどのように格納するかは、以下の CGRAM アドレステーブルによって異なります。CGRAM アドレスは 6 ビットのアドレスを 2 つに分類し、左側 (5、4、3) が対応する上位 3 桁のキャラクタ格納アドレスになります。001 ~ 111 の 3 ビットを組み合わせると、8 つの外字を格納するためのアドレスがちょうど 8 つ存在します。
右側 (2,1,0) は、外文字に対応する下位 3 ビットの 8 バイトです。表内の CGRAM データは文字コンテンツを構成するものです。文字の各行は 8 ビット/バイトで構成されています。各文字の格納には 8 バイトが必要であるため、アドレスの下位 3 ビットは 001 から 111 まで結合され、1 つの文字を格納するにはちょうど 8 つのアドレスになります。
たとえば、大文字を作成すると一
、その配列は次のようになります。
// 数组中每个元素代表字符的一行,一共8行。
//LCD显示的字符是5x8点阵,因此一行只有5位,0x1f:1表示第5位为1,f表示后面4位为1
unsigned char str[] = {
0x00,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,};
CGRAMとCGROMの対応
CGRAM の組み込み命令とアドレス テーブルを理解したら、カスタム キャラクタを作成して CGRAM に保存できます。次のステップは、CGRAM アドレスの文字を CGROM アドレスに関連付けて、LCD が CGRAM アドレスを見つけられるようにすることです。 CGROM アドレスから、CGRAM アドレスを渡して文字を検索します。
1602LCD には CGRAM と CGROM のアドレスが関連付けられており、その関係は次のようになります。
たとえば、CGRAM の最初の文字の位置は (0x40-0x47) で、対応する CGROM アドレスは 0X00 です。プログラムの出力内容のアドレスが 0x00 の場合、CGRAM の最初の文字が検索され、CGRAM に出力されます。 1602LCDスクリーン。
3.1602LCD はキャラクターインスタンスを作成します
次の例ではLCDWriteCGRAM
、外字作成機能を実装する関数を作成しています。
- まず、CGRAM 内のカスタム文字を保存する場所を設定します。 LCD1602_WriteCMD(0x40);
- カスタム キャラクタ コンテンツを CGRAM に保存します: for(i=0;i<8;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-0x47
LCD1602_WriteCMD(0x40);
//存放自定义字符内容
for(i=0;i<8;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_DB7
LCD1602_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{
// 第二行起始位置是0x40
LCD1602_WriteCMD(0x80 | (0x40+x));
}
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-0x47
LCD1602_WriteCMD(0x40);
//存放自定义字符内容
for(i=0;i<8;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 の位置、文字の内容などのパラメータを定義します。
- ×:LCD表示文字位置
- y: LCDに文字を表示する行を設定します。
- pos: CGRAM の場所を設定します
- str: 文字の内容
- カスタム キャラクターの作成は 2 つの部分で構成されます
- CGRAM内のキャラクターの保存場所を設定します
- 文字内容を設定する
- 文字表示の設定
- LCDのどこに文字を表示するかを設定します
- LCD に表示する文字を設定する
/*
x:LCD显示字符位置
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(i=0;i<8;i++){
/*
确定CGRAM位置
0x40是CGRAM第一个起始位置,pos是设置第几个位置,一共8个。
*/
LCD1602_WriteCMD(0x40+pos*8+i );
// 构造自定义字符
LCD1602_WriteData(*(str+i));
}
// 2.显示字符
// 设置字符在LCD显示的位置
if(0 == y){
LCD1602_WriteCMD(0x80 | x);
}
else{
// 第二行起始位置是0x40
LCD1602_WriteCMD(0x80 | (0x40+x));
}
// LCD显示字符内容,该地址是CGROM
LCD1602_WriteData(0x00+pos);
}
完全なコード
#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_DB7
LCD1602_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{
// 第二行起始位置是0x40
LCD1602_WriteCMD(0x80 | (0x40+x));
}
while(*str != '\0'){
LCD1602_WriteData(*str++);
}
}
/*
x:LCD显示字符位置
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(i=0;i<8;i++){
/*
确定CGRAM位置
0x40是CGRAM第一个起始位置,pos是设置第几个位置,一共8个。
*/
LCD1602_WriteCMD(0x40+pos*8+i );
// 构造自定义字符
LCD1602_WriteData(*(str+i));
}
// 2.显示字符
// 设置字符在LCD显示的位置
if(0 == y){
LCD1602_WriteCMD(0x80 | x);
}
else{
// 第二行起始位置是0x40
LCD1602_WriteCMD(0x80 | (0x40+x));
}
// LCD显示字符内容,该地址是CGROM
LCD1602_WriteData(0x00+pos);
}
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, //℃,代码 0x00
0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00, //一,代码 0x01
0x00,0x00,0x00,0x0e,0x00,0xff,0x00,0x00, //二,代码 0x02
0x00,0x00,0xff,0x00,0x0e,0x00,0xff,0x00, //三,代码 0x03
0x00,0x00,0xff,0xf5,0xfb,0xf1,0xff,0x00, //四,代码 0x04
0x00,0xfe,0x08,0xfe,0x0a,0x0a,0xff,0x00, //五,代码 0x05
0x00,0x04,0x00,0xff,0x00,0x0a,0x11,0x00, //六,代码 0x06
0x00,0x1f,0x11,0x1f,0x11,0x11,0x1f,0x00, //日,代码 0x07
};
void CgramWrite(void) {
// 装入CGRAM //
unsigned char i;
LCD1602_WriteCMD(0x06); // CGRAM地址自动加1
LCD1602_WriteCMD(0x40); // CGRAM地址设为从第一个位置开始
for(i=0;i<64;i++) {
LCD1602_WriteData(Xword[i]);// 按数组写入数据
}
}
// a:LCD显示位置 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);
}
}