当前位置: 首页 > article >正文

51单片机-LCD1602(液晶显示屏)- 写驱动

时间永远是检验真理唯一标准!Whappy!

主要简单写出几个驱动

初始化、显示字符、显示字符串、显示整形数据、有符号数据、十六进制、二进制!

void LCD_Init(); 
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);

介绍
 

LCD1602驱动程序编写

根据时序写出发送指令和发送数据的操作,

首先设置指令(查看指令格式)集存取RS,RS=0,输入指令,1输入数据。再RS=1期间,将R/W设置位写,并打开使能从1 -0,然后数据就会被写入进去。

下面两个函数实现写数据和写指令的操作,接下来我们就要根据相关寄存器发送,对应的指令和数据即可,可参考数据手册。



//RS写指令的驱动
void LCD1602_WriteCommand(unsigned char Command)
{
	LCD_RS = 0; //写入指令
	LCD_WR = 0; //写入数据
	LCD_DataPort = Command; //将指令放到数据总线上,并行端口,Commmand的8位可以直接放上去
	LCD_EN = 1;  //使能1-0,写入数据
	Delay1ms();
	LCD_EN = 0;	
	Delay1ms();
		
}


//RW写数据的驱动
void LCD1602_WriteData(unsigned char Data)
{
	LCD_RS = 1; //写入指令
	LCD_WR = 0; //写入数据
	LCD_DataPort = Data; //将指令放到数据总线上,并行端口,Commmand的8位可以直接放上去
	LCD_EN = 1;  //使能1-0,写入数据
	Delay1ms();
	LCD_EN = 0;	
	Delay1ms();
}

代码写数据写指令已经完成,接下我们就要根据LCD1602的相关寄存器配置进行我们需要的操作,下图表位LCD1602的相关操作配置指令(也是寄存器配置)

具体操作流程如下,对照指令集写的初始化函数和显示字符函数等(通过发送指令和数据函数完成)

(1)对功能指令的寄存器配置为0X38,  发送指令0x38    //八位数据接口,两行显示,5*7点阵

给出功能指令配置,其余指令配置请参考指令集,自行研究,也很容易!

初始化函数编写

//初始化
void LCD1602_Init(void)
{
	LCD1602_WriteCommand(0X38);//八位数据接口,两行显示,5*7点阵
	LCD1602_WriteCommand(0X0C);//显示开,光标关,闪烁关
	LCD1602_WriteCommand(0X06);//数据读写操作后,光标自动加一,画面不动
	LCD1602_WriteCommand(0X01);//光标复位,清屏
	
}


//光标位置
void LCD1602_SetCursor(unsigned char Line, unsigned char Column)
{
	if(Line == 1)
	{
		LCD1602_WriteCommand(0X80 | (Column-1));
		
	}
	else
	{
		LCD1602_WriteCommand(0X80 | (Column-1)+0X40);
	}
}

整体函数

LCD1602.c

#include <REGX52.H>

#include "LCD1602_W.h"


unsigned int LCD_Pow(unsigned char base, unsigned char exponent)
{
    unsigned int result = 1;
    while (exponent--)
    {
        result *= base;
    }
    return result;
}

//初始化
void LCD1602_Init(void)
{
	LCD1602_WriteCommand(0X38);//八位数据接口,两行显示,5*7点阵
	LCD1602_WriteCommand(0X0C);//显示开,光标关,闪烁关
	LCD1602_WriteCommand(0X06);//数据读写操作后,光标自动加一,画面不动
	LCD1602_WriteCommand(0X01);//光标复位,清屏
	
}

/*
行与地址映射
第一行地址起点:通常,LCD 屏幕的第一行的 DDRAM 地址从 0x00 开始。
第二行地址起点:第二行的 DDRAM 地址通常从 0x40 开始。
所以,如果我们想移动光标到显示屏的第一行的第 1 列,就需要发送的命令是 0x80 加上该列的偏移量(即 Column-1)。

解释 0x80 | (Column - 1)
0x80:

0x80 是一个命令位,表示将要设置光标的 DDRAM 地址。LCD 控制器的命令格式中,高位 1 用来表明我们要设置光标。
它是“设置地址”指令的标识符,告诉 LCD 控制器接下来传递的值是 DDRAM 的地址。
Column - 1:

Column 是用户输入的列数,它通常是从 1 开始的。然而,LCD 的内存地址是从 0 开始的(即第 1 列对应地址 0,第 2 列对应地址 1,以此类推)。
所以我们需要将 Column 减去 1,将它转换为从 0 开始的索引值,匹配 DDRAM 地址。
*/
//光标位置
void LCD1602_SetCursor(unsigned char Line, unsigned char Column)
{
	if(Line == 1)
	{
		LCD1602_WriteCommand(0X80 | (Column-1));
		
	}
	else
	{
		LCD1602_WriteCommand(0X80 | (Column-1)+0X40);
	}
}

//显示字符
void LCD1602_ShowChar(unsigned char Line, unsigned char Column,unsigned char Char)
{
	LCD1602_SetCursor(Line,Column); //光标位置
	LCD1602_WriteData(Char); //要显示的字符
}


//显示字符串
void LCD_DisplayString(unsigned char Line, unsigned char Column, char *str)
{
    // 将光标移动到指定的行和列
    LCD1602_SetCursor(Line, Column);
    
    // 循环显示字符串中的每个字符,直到遇到字符串结束符 '\0'
    while(*str != '\0')
    {
        LCD1602_WriteData(*str);// 显示当前字符
        str++;                // 移动到下一个字符
    }
}



// 显示16进制数字
void LCD1602_ShowHexNum(unsigned char Line, unsigned char Column, unsigned int Number, unsigned char Length)
{
    unsigned char i;
    unsigned char hexDigit;
    unsigned int divisor = LCD_Pow(16, Length - 1); // 初始除数为16的Length-1次方

    LCD1602_SetCursor(Line,Column);

    for (i = 0; i < Length; i++)
    {
        hexDigit = Number / divisor;          // 获取当前最高位的16进制数字
        Number %= divisor;                    // 计算剩余的数值
        divisor /= 16;                        // 更新除数以处理下一位
        
        if (hexDigit < 10)
        {
            LCD1602_WriteData(hexDigit + '0');    // 数字字符
        }
        else
        {
            LCD1602_WriteData(hexDigit - 10 + 'A'); // 字母字符
        }
    }
}


void LCD1602_ShowBinNum(unsigned char Line, unsigned char Column, unsigned int Number, unsigned char Length)
{
    unsigned char i;
    unsigned char hexDigit;
    unsigned int divisor = LCD_Pow(2, Length - 1); // 初始除数为16的Length-1次方

    LCD1602_SetCursor(Line,Column);

    for (i = 0; i < Length; i++)
    {
        hexDigit = Number / divisor;          // 获取当前最高位的16进制数字
        Number %= divisor;                    // 计算剩余的数值
        divisor /= 2;                        // 更新除数以处理下一位
        
        if (hexDigit < 10)
        {
            LCD1602_WriteData(hexDigit + '0');    // 数字字符
        }
        else
        {
            LCD1602_WriteData(hexDigit - 10 + 'A'); // 字母字符
        }
    }
}

// 显示数字字符
void LCD_ShowNumber(unsigned char Line, unsigned char Column, unsigned int Number, unsigned char Length)
{
    unsigned char i;
    unsigned char digit;
    unsigned char displayDigit[10]; // 用于存储每一位的数字字符

    // 计算每一位的数字字符
    for (i = 0; i < Length; i++)
    {
        digit = Number % 10; // 取当前最低位数字
        displayDigit[Length - i - 1] = digit + '0'; // 转换为字符并存储
        Number /= 10; // 处理下一个数字
    }

    // 显示每一位数字
    LCD1602_SetCursor(Line, Column); // 设置光标位置
    for (i = 0; i < Length; i++)
    {
        LCD1602_WriteData(displayDigit[i]); // 显示字符
    }
}


//指定位置显示有符号的数字
void LCD1602_DisplaySignedNum(unsigned char Line, unsigned char Column, int Number, unsigned char Length)
{
	unsigned char i;
	unsigned int Number1;
    unsigned char digit;
    unsigned char displayDigit[10]; // 用于存储每一位的数字字符

   
	LCD1602_SetCursor(Line, Column); // 设置光标位置
	
	if(Number > 0)
	{
		LCD1602_WriteData('+'); //写数据
		Number1 = Number;
	}
	else
	{
		LCD1602_WriteData('-'); //写数据
		Number1 = -Number;
	}
		
	// 计算每一位的数字字符
    for (i = 0; i < Length; i++)
    {
        digit = Number1 % 10; // 取当前最低位数字
        displayDigit[Length - i - 1] = digit + '0'; // 转换为字符并存储
        Number1 /= 10; // 处理下一个数字
    }

	for (i = 0; i < Length; i++)
    {
        LCD1602_WriteData(displayDigit[i]); // 显示字符
    }
}


// 显示流动字母的函数
void LCD1602_FlowLetters(unsigned char Line, unsigned char StartColumn, char *str, unsigned char Delay)
{
    unsigned char i, j;
    unsigned char length = 0;
	unsigned int delay;
    char buffer[17]; // 用于存储显示内容(16字符 + 1个终止符)

    // 计算字符串的长度
    while (str[length] != '\0')
    {
        length++;
    }

    // 将字符串末尾添加空格填充到屏幕宽度
    for (i = 0; i < 16 - length; i++)
    {
        buffer[length + i] = ' ';
    }
    for (i = 0; i < length; i++)
    {
        buffer[i] = str[i];
    }
    buffer[16] = '\0'; // 添加字符串结束符

    // 流动显示
    for (i = 0; i < length + (16 - length); i++)
    {
        LCD1602_SetCursor(Line, StartColumn); // 设置光标位置
        for (j = 0; j < 16; j++)
        {
            LCD1602_WriteData(buffer[j + i]); // 显示字符
        }

        // 等待一段时间
        for (delay = 0; delay < Delay * 1000; delay++);

        // 清屏
        LCD1602_WriteCommand(0x01);
    }
}






































LCD1602.h

#ifndef __LCD1602_H__
#define __LCD1602_H__

void LCD1602_Init(void); //初始化
void LCD1602_SetCursor(unsigned char Line, unsigned char Column); //设置光标的位置
void LCD1602_ShowChar(unsigned char Line, unsigned char Column,unsigned char Char); //显示字符
void LCD_DisplayString(unsigned char Line, unsigned char Column, char *str); //显示字符串
void LCD1602_ShowHexNum(unsigned char Line, unsigned char Column, unsigned int Number, unsigned char Length);// 显示16进制数字
void LCD1602_ShowBinNum(unsigned char Line, unsigned char Column, unsigned int Number, unsigned char Length); //显示二进制
void LCD_ShowNumber(unsigned char Line, unsigned char Column, unsigned int Number, unsigned char Length); // 显示数字字符
void LCD1602_DisplaySignedNum(unsigned char Line, unsigned char Column, int Number, unsigned char Length);  //显示有符号数字
void LCD1602_FlowLetters(unsigned char Line, unsigned char StartColumn, char *str, unsigned char Delay);//流动字母



#endif

LCD1602_W.h

#ifndef __LCD1602_W_H__
#define __LCD1602_W_H__


void LCD1602_WriteCommand(unsigned char Command); //写指令
void LCD1602_WriteData(unsigned char Data); //写数据


#endif

LCD1602_W.c

#include <REGX52.H>
#include "intrins.h"

//管脚定义
sbit LCD_WR = P2^5; //数据写入操作
sbit LCD_RS = P2^6; //指令输入
sbit LCD_EN = P2^7; //使能


#define LCD_DataPort	P0   //端口P0设置为数据位


void Delay1ms()		//@11.0592MHz
{
	unsigned char i, j;

	_nop_();
	i = 2;
	j = 199;
	do
	{
		while (--j);
	} while (--i);
}


//RS写指令的驱动
void LCD1602_WriteCommand(unsigned char Command)
{
	LCD_RS = 0; //写入指令
	LCD_WR = 0; //写入数据
	LCD_DataPort = Command; //将指令放到数据总线上,并行端口,Commmand的8位可以直接放上去
	LCD_EN = 1;  //使能1-0,写入数据
	Delay1ms();
	LCD_EN = 0;	
	Delay1ms();
		
}


//RW写数据的驱动
void LCD1602_WriteData(unsigned char Data)
{
	LCD_RS = 1; //写入指令
	LCD_WR = 0; //写入数据
	LCD_DataPort = Data; //将指令放到数据总线上,并行端口,Commmand的8位可以直接放上去
	LCD_EN = 1;  //使能1-0,写入数据
	Delay1ms();
	LCD_EN = 0;	
	Delay1ms();
}

后期调用都非常方便,都已经模块化。


http://www.kler.cn/a/315301.html

相关文章:

  • 逐行加载 HTML 内容并实时显示效果:使用 wxPython 的实现
  • 【Linux】HTTP协议和HTTPS加密
  • Vim 编辑器学习笔记
  • 初级数据结构——栈
  • zabbix搭建钉钉告警流程
  • 2023年MathorCup数学建模B题城市轨道交通列车时刻表优化问题解题全过程文档加程序
  • 数据结构-树(基础,分类,遍历)
  • JAVA基础:System类,Runtime类,Arrays类的常用方法,二分查找算法
  • C++竞赛初阶L1-16-第七单元-字符串(36~37课)559: T456513 统计数字字符个数
  • 基于Redis实现幂等判断
  • 异步请求的方法以及原理
  • MyBatis动态SQL中的`if`标签使用【后端 19】
  • C++ 条件变量:wait、wait_for、wait_until
  • 【开源大模型生态9】百度的文心大模型
  • 主播和礼品检测系统源码分享
  • 高速下载大模型文件
  • 【读点论文】Text Recognition in the Wild: A Survey 非常纯粹的OCR研究,专业细致,脉络清晰
  • Datawhale X 南瓜书 task01学习笔记
  • Vue3(一) Vite创建Vue3工程,选项式API与组合式API;setup的使用;Vue中的响应式ref,reactive
  • c语言练习题1(数组和循环)
  • python发送邮件 - email smtplib
  • vue2项目实现国际化(若依框架示例)
  • c语言习题
  • JS领域的AI工程利器分享
  • Spring Cloud Gateway组件
  • 如何在 Spring Boot中更改默认端口