基于51单片机使用LCD1602液晶,后面再学习使用基于stm32的TFTLCD。
1.LCD1602的简介
1602液晶也可以被叫做1602字符型液晶,这个是一种只用来显示字母、数字、符号等的点阵型液晶模块。1602里面存储器有三种:CGROM、CGRAM、DDRAM。
首先显示内容分为两种,一种是常用字符,存储在CGROM中,用户可以直接调用,另一种是自定义的字符,比如自己设计的一些奇怪的图形之,存储在CGRAM。
(1)DDRAM就是显示数据RAM,用来寄存待显示的字符代码。地址与显示位置如下,每行40个地址,1602只用到前16个,共两行,对应关系如下:
当我们想在指定位置写入内容时,要先指定地址,如在第一行第一位写入,地址位是00H,再加上DB7的1,即80H(0010000000),第二行第一位是40H,再加上DB7的1,C0H(0011000000),依次类推。
(2)LCD自定义的存储在CGRAM,留给自定义的位置只有8个地址,字模地址为01000000-01000111八个地址,也就是最多自定义8个符号或者图形。
根据这条指令,来写一个摄氏度℃的自定义符号,对应图如下:
字符对应的数组为table【】={0x10,0x06,0x09,0x08,0x08,0x09,0x06,0x00},将℃显示出来分为4个步骤:
A.设定CGRAM地址,即写命令LcdWriteCom(0x40),表示第1个自定义字符的存储地址是0x40;1个字符有8位,依次类推,设定第2个自定义字符地址用LcdWriteCom(0x48)......
B.将表示字符的8位数据,写进设定的地址:用for循环将数据写入。
C.在想要的地方显示字符:LcdWriteCom(0x80+0x40);//从第2行第1列开始显示。
D.跟据自定义地址显示字符。LcdWriteData(table1[0]); //table1[]为自定义字符地址数组
补充 :为什么自定义字符地址是0x00~0x07 ?
常用字符是从0x20开始显示,而0x00—0x0f都是没有用的,其实这个正式为自定义显示字符准备的。当你把上面的代码输入到CGRAM中,LCD1602机会把汉字或字符赋予地址,这个地址是从0x00开始,因为最多只能8个字符,所以当在CGRAM里面输入8个字符代码时,这8个字符的代码的数据地址就是0x00开始到0x07。
(3)例程:
main.c
#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器
#include "lcd.h"
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
u8 Disp[]=" Pechin Science ";//C语言中把字符串当作数组来处理
//LCD1602只能自定义8个字符
unsigned char character0[8] = {0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02}; //年
unsigned char character1[8] = {0x0f,0x09,0x0f,0x09,0x0f,0x09,0x0b,0x11}; //月
unsigned char character2[8] = {0x0f,0x09,0x09,0x09,0x0f,0x09,0x09,0x0f}; //日
unsigned char characterN[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; //日
uchar code table1[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07}; //自定义字符数据地址
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main(void)
{
u8 i;
LcdInit();
//显示字库的字符
LcdWriteCom(0x80);//显示在第1行
for(i=0;i<16;i++) //显示存储在CGROM的字符
{
LcdWriteData(Disp[i]);
}
//显示相邻两个的自定义字符
LcdWriteCom(0x40); //设定CGRAM地址
for(i=0;i<8;i++) //把自定义字符存储到设定地址
{
LcdWriteData(character0[i]);
}
LcdWriteCom(0x48); //1个字符有8位,所以第2个字符地址是0x40+8=0x48
for(i=0;i<8;i++)
{
LcdWriteData(character1[i]);
}
LcdWriteCom(0x80+0x40);//从第2行第1列开始显示
for(i=0;i<2;i++) // 根据自定义地址显示2个字符
{
LcdWriteData(table1[i]);
}
LcdWriteCom(0x50); //设定第3个字符地址
for(i=0;i<8;i++) //
{
LcdWriteData(character2[i]);
}
LcdWriteCom(0x80+0x44); //显示在第2行第5列开始显示
LcdWriteData(table1[2]);
while(1);
}
LCD.c
#include "lcd.h"
/*******************************************************************************
* 函 数 名 : Lcd1602_Delay1ms
* 函数功能 : 延时函数,延时1ms
* 输 入 : c
* 输 出 : 无
* 说 名 : 该函数是在12MHZ晶振下,12分频单片机的延时。
*******************************************************************************/
void Lcd1602_Delay1ms(uint c) //误差 0us
{
uchar a,b;
for (; c>0; c--)
{
for (b=199;b>0;b--)
{
for(a=1;a>0;a--);
}
}
}
/*******************************************************************************
* 函 数 名 : LcdWriteCom
* 函数功能 : 向LCD写入一个字节的命令
* 输 入 : com
* 输 出 : 无
*******************************************************************************/
#ifndef LCD1602_4PINS //当没有定义这个LCD1602_4PINS时
void LcdWriteCom(uchar com) //写入命令
{
LCD1602_E = 0; //使能
LCD1602_RS = 0; //选择发送命令
LCD1602_RW = 0; //选择写入
LCD1602_DATAPINS = com; //放入命令
Lcd1602_Delay1ms(1); //等待数据稳定
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5); //保持时间
LCD1602_E = 0;
}
#else
void LcdWriteCom(uchar com) //写入命令
{
LCD1602_E = 0; //使能清零
LCD1602_RS = 0; //选择写入命令
LCD1602_RW = 0; //选择写入
LCD1602_DATAPINS = com; //由于4位的接线是接到P0口的高四位,所以传送高四位不用改
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
LCD1602_DATAPINS = com << 4; //发送低四位
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
}
#endif
/*******************************************************************************
* 函 数 名 : LcdWriteData
* 函数功能 : 向LCD写入一个字节的数据
* 输 入 : dat
* 输 出 : 无
*******************************************************************************/
#ifndef LCD1602_4PINS
void LcdWriteData(uchar dat) //写入数据
{
LCD1602_E = 0; //使能清零
LCD1602_RS = 1; //选择输入数据
LCD1602_RW = 0; //选择写入
LCD1602_DATAPINS = dat; //写入数据
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5); //保持时间
LCD1602_E = 0;
}
#else
void LcdWriteData(uchar dat) //写入数据
{
LCD1602_E = 0; //使能清零
LCD1602_RS = 1; //选择写入数据
LCD1602_RW = 0; //选择写入
LCD1602_DATAPINS = dat; //由于4位的接线是接到P0口的高四位,所以传送高四位不用改
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
LCD1602_DATAPINS = dat << 4; //写入低四位
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //写入时序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
}
#endif
/*******************************************************************************
* 函 数 名 : LcdInit()
* 函数功能 : 初始化LCD屏
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
#ifndef LCD1602_4PINS
void LcdInit() //LCD初始化子程序
{
LcdWriteCom(0x38); //开显示
LcdWriteCom(0x0c); //开显示不显示光标
LcdWriteCom(0x06); //写一个指针加1
LcdWriteCom(0x01); //清屏
LcdWriteCom(0x80); //设置数据指针起点
}
#else
void LcdInit() //LCD初始化子程序
{
LcdWriteCom(0x32); //将8位总线转为4位总线
LcdWriteCom(0x28); //在四位线下的初始化
LcdWriteCom(0x0c); //开显示不显示光标
LcdWriteCom(0x06); //写一个指针加1
LcdWriteCom(0x01); //清屏
LcdWriteCom(0x80); //设置数据指针起点
}
#endif
LCD.H
#ifndef __LCD_H_
#define __LCD_H_
/**********************************
当使用的是4位数据传输的时候定义,
使用8位取消这个定义
**********************************/
//#define LCD1602_4PINS
/**********************************
包含头文件
**********************************/
#include<reg52.h>
//---重定义关键词---//
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
/**********************************
PIN口定义
**********************************/
#define LCD1602_DATAPINS P0
sbit LCD1602_E=P2^7;
sbit LCD1602_RW=P2^5;
sbit LCD1602_RS=P2^6;
/**********************************
函数声明
**********************************/
/*在51单片机12MHZ时钟下的延时函数*/
void Lcd1602_Delay1ms(uint c); //误差 0us
/*LCD1602写入8位命令子函数*/
void LcdWriteCom(uchar com);
/*LCD1602写入8位数据子函数*/
void LcdWriteData(uchar dat) ;
/*LCD1602初始化子程序*/
void LcdInit();
#endif
(4)字模提取
LCD1602是5*8点阵,但是5*8不能提取代码,最少只能8*8,所以我们这里只用图像的后5列,前3列不用。
新建图像 8*8,然后再图像里面点想要显示的字符,汉字,注意是在后5列中点,黑点表示显示,白点不显示,用鼠标左键可以切换。
这软件里面可以选择C51或汇编,这里选择C51,就可以产生代码了。