使用51单片机控制lcd1602字体显示

news2025/2/28 21:28:17

部分效果图:

准备工作:

51单片机(BST)+1602显示屏

基础知识:

注:X表示可以是0,也可以是1;

DL 1,

N 1,

F 0,

代码一: 要求显示字母‘a’

#include <reg52.h>

sbit E = P2^5; // enable 数据读写操作控制位 1: 写 0: 读
sbit RW = P1^1; // 读写控制线 0: 写操作, 1: 读操作
sbit RS = P1^0; // 数据和指令选择控制端, 0: 命令状态; 1:数据状态

Write_CMD(unsigned char x){
	int i = 1000;
	// 设置进入命令状态
	RS = 0;
	// 写操作
	RW = 0;
	// 0x01 清屏  0x38 设置 ......等指令内容
	P0 = x;
  // 打开指令读写操作控制允许
	E = 1;
	// 等待1秒
	while(i--);
	// 关闭指令读写操作控制允许
	E = 0;
}
Write_DATA(unsigned char x) {
	int i = 1000;
	// 设置进入数据状态
	RS = 1;
	// 写操作
	RW = 0;
	// 数据内容
	P0 = x;
  // 打开数据读写操作控制允许
	E = 1;
	// 等待1秒
	while(i--);
	// 关闭数据读写操作控制允许
	E = 0;
}
main(){
	
  // 清屏
	Write_CMD(0x01);
  // 设置16X2显示,5X7点阵,8位数据接口;
	Write_CMD(0x38);
  // 开显示,显示光标,光标闪烁;
	Write_CMD(0x0f);
	// 地址加1,当写入数据的时候光标右移:
	Write_CMD(0x06);
	// 写入字符a
	Write_DATA('a');
	while(1);
}

效果结果图:

代码优化一下:

#include <reg52.h>

sbit E = P2^5; // enable 数据读写操作控制位 1: 写 0: 读
sbit RW = P1^1; // 读写控制线 0: 写操作, 1: 读操作
sbit RS = P1^0; // 数据和指令选择控制端, 0: 命令状态; 1:数据状态

void Write_CMD(unsigned char x){
	int i = 1000;
	// 设置进入命令状态
	RS = 0;
	// 写操作
	RW = 0;
	// 0x01 清屏  0x38 设置 ......等指令内容
	P0 = x;
  // 打开指令读写操作控制允许
	E = 1;
	// 等待1秒
	while(i--);
	// 关闭指令读写操作控制允许
	E = 0;
}
void Write_DATA(unsigned char x) {
	int i = 1000;
	// 设置进入数据状态
	RS = 1;
	// 写操作
	RW = 0;
	// 数据内容
	P0 = x;
  // 打开数据读写操作控制允许
	E = 1;
	// 等待1秒
	while(i--);
	// 关闭数据读写操作控制允许
	E = 0;
}

// 初始化代码
void LCDinit(void){
  // 清屏
	Write_CMD(0x01);
  // 设置16X2显示,5X7点阵,8位数据接口;
	Write_CMD(0x38);
  // 开显示,显示光标,光标闪烁;
	Write_CMD(0x0f);
	// 地址加1,当写入数据的时候光标右移:
	Write_CMD(0x06);
}

main(){
	
// 初始化代码
	LCDinit();
	// 写入字符a
	Write_DATA('a');
	while(1);
}

例2: 从C7的位置显示字符“W”

#include <reg52.h>

sbit E = P2^5; // enable 数据读写操作控制位 1: 写 0: 读
sbit RW = P1^1; // 读写控制线 0: 写操作, 1: 读操作
sbit RS = P1^0; // 数据和指令选择控制端, 0: 命令状态; 1:数据状态

void Write_CMD(unsigned char x){
	int i = 1000;
	// 设置进入命令状态
	RS = 0;
	// 写操作
	RW = 0;
	// 0x01 清屏  0x38 设置 ......等指令内容
	P0 = x;
  // 打开指令读写操作控制允许
	E = 1;
	// 等待1秒
	while(i--);
	// 关闭指令读写操作控制允许
	E = 0;
}
void Write_DATA(unsigned char x) {
	int i = 1000;
	// 设置进入数据状态
	RS = 1;
	// 写操作
	RW = 0;
	// 数据内容
	P0 = x;
  // 打开数据读写操作控制允许
	E = 1;
	// 等待1秒
	while(i--);
	// 关闭数据读写操作控制允许
	E = 0;
}

// 初始化代码
void LCDinit(void){
  // 清屏
	Write_CMD(0x01);
  // 设置16X2显示,5X7点阵,8位数据接口;
	Write_CMD(0x38);
  // 开显示,显示光标,光标闪烁;
	Write_CMD(0x0f);
	// 地址加1,当写入数据的时候光标右移:
	Write_CMD(0x06);
}

main(){
	
  //初始化代码
	LCDinit();
	// 指令显示从C7位置开始写字母
	Write_CMD(0xC7);
	// 写入字符W
	Write_DATA('W');
	while(1);
}

例子三,输出“I Love China !”

#include <reg52.h>

sbit E = P2^5; // enable 数据读写操作控制位 1: 写 0: 读
sbit RW = P1^1; // 读写控制线 0: 写操作, 1: 读操作
sbit RS = P1^0; // 数据和指令选择控制端, 0: 命令状态; 1:数据状态

void Write_CMD(unsigned char x){
	int i = 1000;
	// 设置进入命令状态
	RS = 0;
	// 写操作
	RW = 0;
	// 0x01 清屏  0x38 设置 ......等指令内容
	P0 = x;
  // 打开指令读写操作控制允许
	E = 1;
	// 等待1秒
	while(i--);
	// 关闭指令读写操作控制允许
	E = 0;
}
void Write_DATA(unsigned char x) {
	int i = 1000;
	// 设置进入数据状态
	RS = 1;
	// 写操作
	RW = 0;
	// 数据内容
	P0 = x;
  // 打开数据读写操作控制允许
	E = 1;
	// 等待1秒
	while(i--);
	// 关闭数据读写操作控制允许
	E = 0;
}

// 初始化代码
void LCDinit(void){
  // 清屏
	Write_CMD(0x01);
  // 设置16X2显示,5X7点阵,8位数据接口;
	Write_CMD(0x38);
  // 开显示,显示光标,光标闪烁;
	Write_CMD(0x0f);
	// 地址加1,当写入数据的时候光标右移:
	Write_CMD(0x06);
}

main(){
	int i;
	char a[] = {"I Love China !"};
  //初始化代码
	LCDinit();
  for(i = 0; i < 14; i++){
	  // 指令显示从C1位置开始写字母
		Write_CMD(0xC1 + i);
		// 写入字符
		Write_DATA(a[i]);
	}
	while(1);
}

附官方提供的示例代码:


/**********************BST-V51实验开发板例程************************
*  平台:BST-V51 + Keil U3 + STC89C52
*  名称:LCD1602模块实验
*  公司:深圳市XXXX科技有限公司        
*  日期:2013-11
*  晶振:11.0592MHZ
*  说明:免费开源,不提供源代码分析.
******************************************************************/
//实验目的:
/*-----------------------------------------------
  名称:LCD1602
  内容:通过标准程序静态显示字符
  引脚定义如下:1-VSS 2-VDD 3-V0 4-RS 5-R/W 6-E 7-14 DB0-DB7 15-BLA 16-BLK
------------------------------------------------*/
#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#include<intrins.h>
#include<string.h>

#define uchar unsigned char

sbit RS = P1^0;   //定义端口 
sbit RW = P1^1;
sbit EN = P2^5;
sbit DU = P2^0;
sbit WE = P2^1;

#define RS_CLR RS=0 
#define RS_SET RS=1

#define RW_CLR RW=0 
#define RW_SET RW=1 

#define EN_CLR EN=0
#define EN_SET EN=1

#define DataPort P0

/*协议定义*/
bit startBit = 0;  				//串口接收开始标志位
bit newLineReceived = 0; 		//串口一帧协议包接收完成
unsigned char inputString[50];  //接收数据协议
/*------------------------------------------------
                 串口初始化函数
------------------------------------------------*/
void init_com(void)
{
	TMOD|=0x20;		   //设T0为方式1,GATE=1;
	SCON=0x50;
	TH1=0xFD;
	TL1=0xFD;
	TR1=1;			   //开启定时器
	//TI=1;
	EA=1;			   //开启总中断
	ES=1;			   //串口中断打开
}


void cmg88()//关数码管,点阵函数
{
	DU=1;  
	P0=0X00;
	DU=0;
}
/*------------------------------------------------
 uS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
 长度如下 T=tx2+5 uS 
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{   
	while(--t);
}
/*------------------------------------------------
 mS延时函数,含有输入参数 unsigned char t,无返回值
 unsigned char 是定义无符号字符变量,其值的范围是
 0~255 这里使用晶振12M,精确延时请使用汇编
------------------------------------------------*/
void DelayMs(unsigned char t)
{
     
 while(t--)
 {
     //大致延时1mS
     DelayUs2x(245);
	 DelayUs2x(245);
 }
}
/*------------------------------------------------
              判忙函数
------------------------------------------------*/
 bit LCD_Check_Busy(void) 
 { 
	 DataPort= 0xFF; 
	 RS_CLR; 
	 RW_SET; 
	 EN_CLR; 
	 _nop_(); 
	 EN_SET;
	 return (bit)(DataPort & 0x80);
 }
/*------------------------------------------------
              写入命令函数
------------------------------------------------*/
 void LCD_Write_Com(unsigned char com) 
 {  
	 while(LCD_Check_Busy()); //忙则等待
	 RS_CLR; 
	 RW_CLR; 
	 EN_SET; 		
	 DataPort= com; 
	 _nop_(); 
	 EN_CLR;
 }
/*------------------------------------------------
              写入数据函数
------------------------------------------------*/
 void LCD_Write_Data(unsigned char Data) 
 { 
	 while(LCD_Check_Busy()); //忙则等待
	 RS_SET; 
	 RW_CLR; 
	 EN_SET; 
	 DataPort= Data; 
	 _nop_();
	 EN_CLR;
 }

/*------------------------------------------------
                清屏函数
------------------------------------------------*/
 void LCD_Clear(void) 
 { 
	 LCD_Write_Com(0x01); 
	 DelayMs(5);
 }
/*------------------------------------------------
              写入字符串函数
------------------------------------------------*/
 void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s) 
 {     
	 if (y == 0) 
	 {     
		 LCD_Write_Com(0x80 + x);     //表示第一行
	 }
	 else 
	 {      
	 	LCD_Write_Com(0xC0 + x);      //表示第二行
	 }        
	 while (*s) 
	 {     
		 LCD_Write_Data( *s);     
		 s ++;     
	 }
 }
/*------------------------------------------------
              写入字符函数
------------------------------------------------*/
 void LCD_Write_Char(unsigned char x,unsigned char y,unsigned char Data) 
 {     
 	if (y == 0) 
 	{     
 		LCD_Write_Com(0x80 + x);     
 	}    
 	else 
 	{     
 		LCD_Write_Com(0xC0 + x);     
 	}        
 	LCD_Write_Data( Data);  
 }
/*------------------------------------------------
              初始化函数
------------------------------------------------*/
void LCD_Init(void) 
{
   LCD_Write_Com(0x38);    /*显示模式设置*/ 
   DelayMs(5); 
   LCD_Write_Com(0x38); 
   DelayMs(5); 
   LCD_Write_Com(0x38); 
   DelayMs(5); 
   LCD_Write_Com(0x38);  
   LCD_Write_Com(0x08);    /*显示关闭*/ 
   LCD_Write_Com(0x01);    /*显示清屏*/ 
   LCD_Write_Com(0x06);    /*显示光标移动设置*/ 
   DelayMs(5); 
   LCD_Write_Com(0x0C);    /*显示开及光标设置*/
}
   
/*------------------------------------------------
                    主函数
------------------------------------------------*/ 
void main(void) 
{ 
	uchar temp[17] = {0};
	cmg88();//关数码管,点阵函数
	LCD_Init(); 
	LCD_Clear();//清屏
	init_com();
	
	LCD_Write_Char(7,0,'o');
	LCD_Write_Char(8,0,'k');
	LCD_Write_String(1,1,"I Love TT");
	while (1) 
	{  
		//开始解析协议 $51,LCD1602,1,0123456789abcdef# 第一行	 $51,LCD1602,2,0123456789abcdef# 第二行
		while (newLineReceived)  //协议数据接收完毕一包
		{
			//判断是否是51的协议
			if(inputString[1] != '5' || inputString[2] != '1')
			{
			 	newLineReceived = 0;  
		   		memset(inputString, 0x00, sizeof(inputString)); 
				break; 
			}
			//判断是否是1602的协议数据
		 	if(inputString[4] != 'L' || inputString[5] != 'C' || inputString[6] != 'D'
			|| inputString[7] != '1'|| inputString[8] != '6'|| inputString[9] != '0'|| inputString[10] != '2')
			{
				newLineReceived = 0;  
	   			memset(inputString, 0x00, sizeof(inputString)); 
				break;	
			}
		
			//开始取数据  位置12 开始  $51,HS00ff3003#
			if(inputString[12] == '0') //清屏
			{
				LCD_Clear();//清屏	
			}
			if(inputString[12] == '1') //显示第一行
			{
				memcpy(temp, inputString+14, 16);
				LCD_Write_String(0, 0, temp);
			}		
			if(inputString[12] == '2') //显示第二行
			{
				memcpy(temp, inputString+14, 16);
				LCD_Write_String(0, 1, temp);
			}

		 	newLineReceived = 0;  
	   		memset(inputString, 0x00, sizeof(inputString)); 
			break;
		}
	
	}
}

/******************************************************************/
/* 串口中断程序*/
/******************************************************************/
void UART_SER () interrupt 4
{
	unsigned char n; 	//定义临时变量
	static int num = 0;

	if(RI) 		//判断是接收中断产生
	{
		RI = 0; 	//标志位清零
		n = SBUF; //读入缓冲区的值

		//control=n;
	    if(n == '$')
	    {
	      startBit = 1;
		  num = 0;
	    }
	    if(startBit == 1)
	    {
	       inputString[num] = n; 
		   num++;    
	    }  
	    if (startBit == 1 && n == '#') 
	    {
	       newLineReceived = 1; 
	       startBit = 0;
		   num = 0;
	    }
		
		if(num >= 50)
		{
			num = 0;
			startBit = 0;
			newLineReceived	= 0;
		}
	}

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1504371.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【力扣白嫖日记】1164.指定日期的产品价格

前言 练习sql语句&#xff0c;所有题目来自于力扣&#xff08;https://leetcode.cn/problemset/database/&#xff09;的免费数据库练习题。 今日题目&#xff1a; 1164.指定日期的铲平价格 表&#xff1a;Products 列名类型product_idintnew_priceintchange_datedate (pr…

如何进入Windows 11的安全模式?这里提供详细步骤

序言 如果你在启动Windows 11 PC时遇到问题,则重新启动到安全模式可能会有所帮助,该模式会暂时禁用驱动程序和功能,以使你的PC更稳定。下面是如何做到这一点。 在Windows 7和更早版本中,通常可以在打开电脑后按功能键(如F8)启动安全模式。Microsoft从Windows 8中删除了…

CSS3基础2

CSS3 用户界面 resize 示例 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title>…

基于Spring Boot+Vue的论坛网站

末尾获取源码作者介绍&#xff1a;大家好&#xff0c;我是墨韵&#xff0c;本人4年开发经验&#xff0c;专注定制项目开发 更多项目&#xff1a;CSDN主页YAML墨韵 学如逆水行舟&#xff0c;不进则退。学习如赶路&#xff0c;不能慢一步。 目录 一、项目简介 二、开发技术与环…

回溯算法09-子集II(Java/子集问题的去重方法)

9.子集II 题目描述 给你一个整数数组 nums &#xff0c;其中可能包含重复元素&#xff0c;请你返回该数组所有可能的子集&#xff08;幂集&#xff09;。 解集 不能 包含重复的子集。返回的解集中&#xff0c;子集可以按 任意顺序 排列。 示例 1&#xff1a; 输入&#xf…

PyQt5实现远程更新exe可执行文件

PyQt5实现远程下载更新exe可执行文件 1、实现流程 1、获取远程http地址 2、获取需要更新的exe文件 3、点击更新 4、把exe强关闭 5、下载文件 6、更新2、效果图 3、示例代码 conf.ini配置文件&#xff1a; {"http_address_edit_value": "http://xxx.com/xxx/…

【敬伟ps教程】文字处理工具

文章目录 文字工具使用方式文字图层文字工具选项字符面板段落面板文字工具使用方式 文字工具(快捷键T),包含横排和直排两种类型 创建文本两种类型:点式文本、段落文本 创建文字方式 1、在画面上单击,出现文字光标,可输入文字,然后需要在工具栏中点击“√”或者 Ctrl+…

【二十九】springboot高并发示例

本章演示在springboot项目中的高并发demo&#xff0c;演示导致的问题&#xff0c;以及单机部署下的解决方案和集群部署下的解决方式以及分布式下的解决方案。 目录 一、单机模式下高并发问题 二、集群模式下高并发问题 一、单机模式下高并发问题 前提&#xff1a;先写一个减扣…

枚举赋值及强制转换问题

对枚举进行字符赋值&#xff0c;需要进行强制类型转换之后&#xff0c;才能得到想要的值&#xff0c;如下 typedef enum data {DIRECTION_X X,DIRECTION_Y Y,DIRECTION_Z Z,DIRECTION_T T }NumData;int main() {NumData numdata DIRECTION_Y;count <<"num is&…

Qt开发QHostInfo主机地址查询组件

Qt 是一个跨平台C图形界面开发库&#xff0c;利用Qt可以快速开发跨平台窗体应用程序&#xff0c;在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置&#xff0c;实现图形化开发极大的方便了开发效率&#xff0c;本章将重点介绍如何运用QHostInfo组件实现对主机地址查询功能…

数据库-第十一章 并发控制【期末复习|考研复习】

前言 总结整理不易&#xff0c;希望大家点赞收藏。 给大家整理了一下数据库系统概论中的重点概念&#xff0c;以供大家期末复习和考研复习的时候使用。 参考资料是王珊老师和萨师煊老师的数据库系统概论(第五版)。 数据库系统概论系列文章传送门&#xff1a; 第一章 绪论 第二/…

机器学习第29周周报 Beyond Dropout

文章目录 week29 Beyond Dropout摘要Abstract一、泛化理论二、文献阅读1. 题目2. abstract3. 网络架构3.1 特征图失真3.2 失真优化 4. 文献解读4.1 Introduction4.2 创新点4.3 实验过程4.3.1 全连接层实验4.3.2 卷积网络上的实验 4.4 结论 小结参考文献 week29 Beyond Dropout …

visualization_msgs::Marker 的pose设置,map坐标系的3d box显示问题

3D框显示 3D框显示可以使用visualization_msgs::Marker::LINE_LIST或者LINE_STRIP&#xff0c;前者使用方法需要指明线的两个端点&#xff0c;后者自动连接相邻两个点。 姿态问题 网上看了一些&#xff0c;没有涉及到朝向设置&#xff0c;Pose.orientation默认构造为4个0 至…

Spring官网中查看MongoDB的API文档的详细步骤

目录 Spring官网中查看MongoDB的API文档的详细步骤1、进入 Spring 官网2、选择 Mongodb的文档介绍3、点击API文档4、进入文档查询页面 Spring官网中查看MongoDB的API文档的详细步骤 1、进入 Spring 官网 首先进入Spring的官网&#xff0c;然后点击【Spring Data】 2、选择 Mon…

JAVA实战开源项目:大学兼职教师管理系统(Vue+SpringBoot)

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容三、界面展示3.1 登录注册3.2 学生教师管理3.3 课程管理模块3.4 授课管理模块3.5 课程考勤模块3.6 课程评价模块3.7 课程成绩模块3.8 可视化图表 四、免责说明 一、摘要 1.1 项目介绍 大学兼职教师管理系统&#xff0c;旨…

王阳明:在心里中一个春天!吃好喝好不等于吃饱喝足,出租屋的第二个周末——早读(逆天打工人爬取热门微信文章解读)

种一个春天&#xff0c;等下一个天亮 引言Python 代码第一篇 霸王别坤第二篇 &#xff08;跳&#xff09;洞见 王阳明&#xff1a;人生若是太苦寒&#xff0c;在心里种一个春天第三篇 人民日报 来了&#xff01;新闻早班车要闻社会政策 结尾 屋宽不如心宽&#xff0c;物整亦是心…

模拟框图的表示

微分方程的建立 目的&#xff1a;为建立LTI系统的数学模型&#xff0c;需要列写微分方程式。 以RLC电路为例&#xff1a; 以Us为输入&#xff0c;Uc为输入&#xff0c;则可以得出以下微分方程式&#xff1a; 抽去物理意义后&#xff0c;得到一般的常微分线性方程&#xff1a;…

YOLOv5-Openvino-ByteTrack【CPU】

纯检测如下&#xff1a; YOLOv5-Openvino和ONNXRuntime推理【CPU】 YOLOv6-Openvino和ONNXRuntime推理【CPU】 YOLOv8-Openvino和ONNXRuntime推理【CPU】 YOLOv9-Openvino和ONNXRuntime推理【CPU】 注&#xff1a;YOLOv5和YOLOv6代码内容基本一致&#xff01; 全部代码Github&…

思维调试:为什么FormatMessage提示找不到资源?

在不调试的情况下解决下面的问题&#xff0c;说明你的思维调试能力又进阶了。 问题 我在调用 FormatMessage 函数加载一个插入的资源字符串&#xff0c;由于某种未知的原因&#xff0c;它没能按预期那样工作。 我要加载的字符串类似于这样的 “Blah blah blah %1. Blah blah …

VIM编译器的安装

文章目录 前言一、VIM软件安装二、遇到问题三、VIM使用1.文档创建命令touch2.VIM编译器输入模式3.VIM编译器指令模式3.VIM编译器底行模式4.VIM编译器使用小技巧 前言 &#x1f4a6; 我们如果要在终端模式下进行文本编辑或者修改文件就可以使用 VIM 编辑器&#xff0c;VIM 编辑…