问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

LCD1602显示屏:硬件连接与C语言编程实现

创作时间:
2025-01-21 22:05:02
作者:
@小白创作中心

LCD1602显示屏:硬件连接与C语言编程实现

LCD1602显示屏的使用

1、引脚功能

VSS:接地引脚
VDD:电源正极5v
VO:对比度调节电压
RS:指令/数据选择,0为指令,1为数据
RW:读写选择,0为写,1为读
E:使能,1为数据有效,下降沿执行指令
D0~D7:数据输入/输出引脚
A:背光灯电源正极
K:背光灯电源负极

2、组成结构

LCD1602的分辨率是16x2,也就是有2行16列的小屏幕组成,而每个小屏幕都有相应对应的地址。在要屏幕显示数据的时候,需要发送指令,指定位置小屏幕显示。如下图所示,每个位置都要不同的1个字节数据对应。

【注意】
例如第二行第一个字符的地址是 40H,那么是否直接写入 40H 就可以将光标定位在第二行第。一个字符的位置呢?这样不行,因为写入显示地址时要求最高位 D7 恒定为高电平 1 。所以实际写入的数据应该是 01000000B(40H) +10000000B(80H)=11000000B(C0H)

而这些地址数据是存储在DDRAM中,DDRAM是一个40x2的存储数据的存储区,它前面16列存储对应的屏幕地址数据,后面的位置用于存储,发送来的指令/显示的数据。

而显示的字符,数字,特殊符号都要对应的字模库。

例如,需要在屏幕上面显示0,则只需要向D0~D7输入0011 0000的1个字节的数据即可。需要在屏幕上面显示A,则只需要向D0~D7输入0100 0001的1个字节的数据即可。我们将这个字模库和ASCII码表进行对比一下。

如图,ASCII码表中的’0’对应的一个字节数也是0010 0000。‘A’对应的一个字节的数据是0100 0001。所以我们需要显示0时,不需要给数据线输入一个字节的二进制数据,我们只需要向输入一个字符‘0’,单片机接收到字符‘0’,会按照ASCII码表转换为对应的一个字节数据,然后将这个数据和字母表中的数据进行比对,最终在屏幕上面显示。(但是有些字符ASCII码并不和字模库相对应)

3、时序结构与指令集

如图为向模块写数据/指令的时序结构:
RS = 0;R/W = 0;此时向模块写入数据(指令),而写指令时,E = 0。
在写完数据的tsp2的时间后,E变为1,在E= 1;时不能在写入数据了,在E下降沿时执行写入的数据(指令)。
RS = 1;R/W = 0;此时向模块写入屏幕显示的数据,而时序和写入指令同理。

LCD1602.c文件

#include <REGX52.H>
#include "intrins.h"
//引脚定义
sbit RS = P1^0;
sbit RW = P1^1;
sbit EN = P1^4;
#define LCD_DataPort P0
void LCD_Delay1ms()		//@11.0592MHz,1ms的延迟
{
    unsigned char i, j;
    i = 2;
    j = 199;
    do
    {
        while (--j);
    } while (--i);
}
/*
 * 给LCD写入指令
*/
void LCD_WriteCommand(signed char Command)
{
    RS = 0;/**RS为0代表写入的是指令,
           *为1代表写入的是要显示的数据*/
    RW = 0;/**RW为0代表从LCD中写入数据,
             *RW为1代表从LCD中读取数据*/
    EN = 0;//将E置为低电平开始写入数据
    LCD_DataPort = Command;//开始将指令传给引脚口
    _nop_();								//5us
    EN = 1;
    LCD_Delay1ms();//EN为高电平的时候,传来的数据才有效
    EN = 0;        //E置低,为下一次写入数据做准备
    LCD_Delay1ms();
}
/*
 * 给LCD写入显示的数据
*/
void LCD_WriteData(unsigned char Data)
{
  RS = 1;/**RS为0代表写入的是指令,
           *为1代表写入的是要显示的数据*/
    RW = 0;/**RW为0代表从LCD中写入数据,
             *RW为1代表从LCD中读取数据*/
    EN = 0;
    LCD_DataPort = Data;//开始将数据传给引脚口
    _nop_();
    EN = 1;
    LCD_Delay1ms();//EN为高电平的时候,传来的数据才有效
    EN = 0;
    LCD_Delay1ms();
}
/*
 * 给LCD初始化,也就是给LCD写入一下指令进行配置,为显示做准备
*/
void LCD_Init()//给LCD初始化,传输指令集
{
    LCD_WriteCommand(0x38);//8位数据接口
    LCD_WriteCommand(0x0C);//显示开,光标关,闪烁关
    LCD_WriteCommand(0x06);//读写操作,光标自动+1,画面不动
    LCD_WriteCommand(0x01);//清屏
}
/*
 * 显示行列,第1行第1列的地址为0x00,第2列0x01.....
             第2行第1列的地址为0x40,第2列0x41.....
*/
void LCD_SetCuror(unsigned char Line,unsigned char Column)
{
    if(Line == 1)//若第一行
    {
        LCD_WriteCommand(0x80|(Column-1));//1000 0000 + (x-1)
    }
    else
    {
        LCD_WriteCommand(0x80|(Column-1) + 0x40);
    }
}
    
/*
 ***显示一个字符(行,列,字符)***
*/
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{
  LCD_SetCuror(Line,Column);
    LCD_WriteData(Char);
}
/*
 ***显示字符串(行,列,字符串,字符串长度)***
*/
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{
    unsigned char i;
    LCD_SetCuror(Line,Column);
    for(i=0;String[i]!='\0';i++)
    {
        LCD_WriteData(String[i]);
  }
}
/*
 ***显示数字(行,列,数字,数字长度)***
*/
/*
     894  长度为:3
     894/100 = 8    8%10 = 8
     894/10 = 89    89%10 = 9
     894/1 = 894    894%10 = 4
*/
int Counting_power(int x,int y)//x^y
{
    unsigned char i;
    int a = 1;
    for(i = 0; i<y; i++)
    {
            a *= x;
    }
    return a;
}
void LCD_ShowNum(unsigned char Line,unsigned char Column,int Num, unsigned char Length)
{
    unsigned char i;
    unsigned int Num1;
    LCD_SetCuror(Line,Column);
    for(i = 1; i<= Length; i++)
    {
        Num1 = (Num/Counting_power(10,Length - i))%10;
        LCD_WriteData('0'+ Num1);
    }
}
/*
 ***显示有符号的数字(行,列,数字,数字长度)***
*/
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Num, unsigned char Length)
{
    unsigned char i;
    unsigned int Num1;
    LCD_SetCuror(Line,Column);
    if(Num >= 0)
    {
        LCD_WriteData('+');
        for(i = 1; i<= Length; i++)
        {
            LCD_WriteData('0'+ (Num/Counting_power(10,Length - i))%10);
        }
    }
    else
    {
        LCD_WriteData('-');
        for(i = 1; i<= Length; i++)
        {
            Num1 = -Num;
            LCD_WriteData('0'+ (Num1/Counting_power(10,Length - i))%10);
        }
    }
}
  

主函数main.c文件

#include <REGX52.H>
#include "LCD1602.h"
void main(void)
{
    LCD_Init();
    LCD_ShowChar(1,1,'C');
    LCD_ShowString(1,3,"nihao");
    LCD_ShowNum(1,9,888,3);
    LCD_ShowSignedNum(2,3,-12,2);
}
  
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号