51单片机LCD1602显示的例程

时间:2024-02-15 21:46:44

  闲着没事,把自己写过的一些函数好好封装打包一下,以便以后自己使用,懒得又忘记了在哪个文件夹里面保存着。

1、LCD1602显示的原理

  原理:https://zhuanlan.zhihu.com/p/166184285

2、LCD1602头文件

#ifndef __LCD1602_H__
#define __LCD1602_H__


#define LCD1602_Order_OFF 0x08
#define LCD1602_Order_CursorClose 0x0C



#define LCD1602_Port P0        //LCD输出的8位串行数据口

sbit LCD1602_RS = P2^0;        //0命令 1数据
sbit LCD1602_RW = P2^1;        //0写  1读
sbit LCD1602_EN = P2^2;        //读写使能,0允许


extern void LCD1602_init();    //初始化函数
extern void LCD1602_Write(unsigned char cmd,unsigned char dat);                                    //写开启函数
extern void LCD1602_displaySring(unsigned char hang, unsigned char lie, unsigned char *pstr);    //显示字符串函数
extern void LCD1602_CursorSet(unsigned char hang, unsigned char lie);                            //设置光标函数

#define LCD1602_CursorClose() LCD1602_Write(0,LCD1602_Order_CursorClose)        //关闭光标
#define LCD1602_Off() LCD1602_Write(0,LCD1602_Order_OFF)                //关显示    



/************LCD1602指令集及配置*****************运行时间(在250KHz下)*/
#define LCD1602_Order_Clear 0x01    //清屏 1.64us
#define LCD1602_Order_Home 0x02        //光标归位 1.64us

#define LCD1602_Order_Mode_ID 0x01    //1=数据读写操作后,AC自动增1;  0=自动减1    
#define LCD1602_Order_Mode_S 0x00    //1=数据读写操作 画面平移;  0=画面不动      
#define LCD1602_Order_Mode (0x04|\
                            (LCD1602_Order_Mode_ID<<1)|\
                            LCD1602_Order_Mode_S)    //输入方式设置    40us

#define LCD1602_Order_OnOFF_D 0x01    //1=开显示,0=关显示
#define LCD1602_Order_OnOFF_C 0x00    //1=显示光标,0=不显示光标
#define LCD1602_Order_OnOFF_B 0x00    //1=光标闪烁,0=不闪烁
#define LCD1602_Order_OnOFF (0x08|\
                            (LCD1602_Order_OnOFF_D<<2)|\
                            (LCD1602_Order_OnOFF_C<<1)|\
                             LCD1602_Order_OnOFF_B)    //显示开关控制 40us

#define LCD1602_Order_Shift_SC 0x00    //0=光标平移一个字符位,1=画面平移
#define LCD1602_Order_Shift_RL 0x01    //1=右移,0=左移
#define LCD1602_Order_Shift (0x10|\
                            (LCD1602_Order_Shift_SC<<3)|\
                            (LCD1602_Order_Shift_RL<<2))    //光标、画面移动    40us

#define LCD1602_Order_Function_DL 0x00    //1=8位数据接口,0=4位
#define LCD1602_Order_Function_N  0x01    //1=两行显示,0=1行
#define LCD1602_Order_Function_F  0x01    //1=5*10点阵,0=5*7
#define LCD1602_Order_Function    (0x20|\
                            (LCD1602_Order_Function_DL<<4)|\
                            (LCD1602_Order_Function_N<<3)|\
                            (LCD1602_Order_Function_F<<2))    //工作方式设置  40us

#define LCD1602_Order_CGRAM_Address 0    //CGRAM(Character Generator 字符产生器)地址(共6位)
#define LCD1602_Order_CGRAM (0x40|LCD1602_Order_CGRAM_Address)    //CGRAM地址设置    40us

#define LCD1602_Order_DDRAM_Address 0    //一行显示:0~0x4F;两行显示:首行:0~0x27,次行:0x40~0x67
#define LCD1602_Order_DDRAM (0x80|LCD1602_Order_DDRAM_Address)    //设置DDRAM地址 40us

#endif
View Code

3、LCD1602C文件

#include<reg51.h>
#include "LCD1602.h"

//自带延时函数
void LCD1602_Delay(unsigned int dely)
{
    for(;dely>0;dely--);
}

//读忙
unsigned char LCD1602_ReadBusy()
{
    unsigned char lcd_status;
    LCD1602_RS=0;
    LCD1602_RW=1;
    LCD1602_EN=1;
    
#if(LCD1602_Order_Function_DL==1)    
    LCD1602_Port=0xFF;
#endif
#if(LCD1602_Order_Function_DL==0)
    LCD1602_Port|=0xF0;
#endif    
    
    LCD1602_Delay(10);
    lcd_status=LCD1602_Port;
    LCD1602_EN=0;
    
#if(LCD1602_Order_Function_DL==0)
    LCD1602_EN=1;
    LCD1602_Delay(10);
    lcd_status=(lcd_status&0xF0)|((0xF0&LCD1602_Port)>>4);
    LCD1602_EN=0;
#endif        
    return lcd_status;  
}

/*向液晶显示器写命令/数据函数
参数说明:cmd=0为写命令,cmd=1为写数据
*/
void LCD1602_Write(unsigned char cmd,unsigned char dat)
{
    while((LCD1602_ReadBusy()&0x80) == 0x80);
    LCD1602_RS=cmd;
    LCD1602_RW=0;
    LCD1602_EN=1;
#if(LCD1602_Order_Function_DL==1)    
    LCD1602_Port=dat;
#endif
    
#if(LCD1602_Order_Function_DL==0)        
    LCD1602_Port=(LCD1602_Port&0x0F)|(dat&0xF0);
    LCD1602_Delay(50);
    LCD1602_EN=0;
    

    LCD1602_EN=1;
    LCD1602_Port=(LCD1602_Port&0x0F)|(dat<<4);
#endif    
    LCD1602_Delay(50);
    LCD1602_EN=0;
}


/*显示字符串
参数说明:起始行,列,字符串
*/
void LCD1602_displaySring(unsigned char hang, unsigned char lie, unsigned char *pstr) 
{
    LCD1602_Write(0,0x80+(0x40 * (hang - 1)) + (lie - 1));
    while(*pstr)
    {
        LCD1602_Write(1,*pstr++);
    }
}


/*让指定位置闪烁光标
参数说明:行,列
*/
void LCD1602_CursorSet(unsigned char hang, unsigned char lie) 
{
    LCD1602_Write(0,0x80+(0x40 * (hang - 1)) + (lie - 1));
    LCD1602_Write(0,0x0F);
}



/*初始化*/
void LCD1602_init()
{
    LCD1602_RS=0;
    LCD1602_RW=0;
    LCD1602_EN=1;
#if(LCD1602_Order_Function_DL==1)    
    LCD1602_Port=LCD1602_Order_Function;
#endif
    
#if(LCD1602_Order_Function_DL==0)
    LCD1602_Port=(LCD1602_Port&0x0f)|(LCD1602_Order_Function&0xF0);
#endif
    LCD1602_Delay(10);
    LCD1602_EN=0;
    LCD1602_Delay(10000);
    LCD1602_Write(0,LCD1602_Order_Function);    //工作方式设置 
    LCD1602_Write(0,LCD1602_Order_OFF);        //关显示
    LCD1602_Write(0,LCD1602_Order_Clear);        //清屏
    LCD1602_Write(0,LCD1602_Order_Mode);        //输入方式设置    
    LCD1602_Write(0,LCD1602_Order_OnOFF);        //开显示
}
View Code

4、例程的main文件

#include <reg51.h>
#include "stdio.h"
#include "LCD1602.h"

char str_temp[16];
float t = 3.14;


//延时n毫秒
void delay_ms(unsigned int n)
{
    unsigned int i=0,j=0;
    for(i=0;i<n;i++)
        for(j=0;j<123;j++);
}

void main()
{
    int i;
    LCD1602_init();
    while(1)
    {
        LCD1602_displaySring(1,1,"------test------");
        sprintf(str_temp,"%f",t);
        LCD1602_displaySring(2,13,str_temp);
        for (i=0;i<10;i++)
        {
            LCD1602_displaySring(2,1,"the value:");
            sprintf(str_temp,"%d",i);
            LCD1602_displaySring(2,11,str_temp);
            delay_ms(500);    
            
        }
    }
}
View Code

 

5、对于那个stdio.h头文件,作用是调用那个sprintf函数,这是一个非常强大的函数,能将整型数据转换为字符串数据,这样调用显示的时候就不用将数据一位一位地显示了。PS:还能显示负数哦!当想显示浮点数据的时候,就将sprintf函数的第二个参数改一改就好啦!

 

6、下面是整个例程的仿真图加代码,分享给大家哦。

  代码+仿真图:https://wwe.lanzoui.com/inRrBqf340d