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

C语言实现:C51单片机驱动LCD屏幕显示字符串(Proteus+Keil)

在Proteus中绘制电路原理图 

我使用的版本是Protues8.16 ,Protues特别擅长仿真单片机及其外围设备,支持多种类型的微控制器,如8051、HC11、PIC、AVR、ARM、MSP430等,也可以设计pcb板,还能3D建模

1.新建工程

Start 栏中点击 New Project ,随后为项目命名并挑选项目存放路径

 选择 DEFAULT 默认选项

选择 Do not create a PCB layout 不绘制PCB电路图

选择 No Firmware Project 无固件项目

 选择 Schematic 示意图

2.添加并调整组件 

 进入画图界面后点击黄色小三角 Component Mode ,再点击蓝色的 小P 添加组件

  

弹出的组件添加界面中,在左上角的 Keywords 中输入需要的元器件名称,双击名称即可添加元器件 

添加以下元器件:AT89C51(MCU芯片,C语言程序都烧录到这个芯片里面)、 CAP(电容) 、CAP-ELEC(电解电容)、 CRYSTAL(晶振)、 LM016L(1602屏幕)、 RES(电阻) 

 点击左下角的旋转箭头就可以更改元器件的方向了

点击双向的金色传说箭头符号 Terminals Mode 终端栏 就可以添加电源和地线了

 点击蓝色总线符号 Buses Mode 可以添加总线

 在绘制总线中需要注意一点,就是支线路的名称要一致,比如单片机的P1.0端口通过总线连接到屏幕的D0端口,需要两个端口连接到总线的支线名称完全一致。

在原理图中双击元器件即可修改元器件信息 

3.绘制原理图 

 这一部分是最小系统板,在这次练习中是可有可无的,但是我还是把它加上了诶

 这里单片机的P2.0/A8端口直接连接到屏幕的RW接口,P2.1/A9端口直接连接到屏幕的RS接口,P2.2/A10端口直接连接到屏幕的E接口

 这里附上LCD1602屏幕和AT89C51芯片的引脚名称和功能表格,可以多了解下硬件知识

LCD1602屏幕引脚含义
引脚编号引脚名称功能描述
1VSS电源地
2VDD电源正极(+5V)
3VEE通过连接一个可变电阻(如电位器)到VEE引脚,可以调整液晶显示的对比度。
4RS注册选择,高电平时选择数据寄存器、低电平时选择指令寄存器
5RW读/写信号线,高电平时进行读操作,低电平时进行写操作。当RS和RW共同为低电平时可以写入指令或者显示地址,当RS为低电平RW为高电平时可以读忙信号,当RS为高电平RW为低电平时可以写入数据
6E使能端,当E端由高电平跳变成低电平时,液晶模块执行命令
7D0并行数据输入端(0位)
8D1并行数据输入端(1位)
9D2并行数据输入端(2位)
10D3并行数据输入端(3位)
11D4并行数据输入端(4位)
12D5并行数据输入端(5位)
13D6并行数据输入端(6位)
14D7并行数据输入端(7位)
AT89C51芯片引脚含义 

在Proteus中,AT89C51可以看到有39只引脚 ,因为Proteus中默认给芯片上电,有两只引脚隐藏起来了

引脚号引脚名称含义
1P1.0端口1的第0位,双向I/O口
2P1.1端口1的第1位,双向I/O口
.........
8P1.7端口1的第7位,双向I/O口
9RST复位引脚,用于将单片机复位到初始状态
10P3.0/RXD端口3的第0位,双向I/O口,同时也是串行通信的接收端(RXD)
11P3.1/TXD端口3的第1位,双向I/O口,同时也是串行通信的发送端(TXD)
12P3.2/INT0端口3的第2位,双向I/O口,外部中断0输入
13P3.3/INT1端口3的第3位,双向I/O口,外部中断1输入
14P3.4/T0端口3的第4位,双向I/O口,定时器0的外部输入
15P3.5/T1端口3的第5位,双向I/O口,定时器1的外部输入
16P3.6/WR端口3的第6位,双向I/O口,外部数据存储器写使能
17P3.7/RD端口3的第7位,双向I/O口,外部数据存储器读使能
18XTAL2振荡器反相放大器的输出
19XTAL1振荡器反相放大器及内部时钟电路的输入
20P2.0端口2的第0位,双向I/O口
.........
27P2.7端口2的第7位,双向I/O口,在访问外部存储器时用作高8位地址总线
28PSEN外部程序存储器读选通信号输出
29ALE/PROG地址锁存使能端,编程时作为编程脉冲输入
30EA/VPP外部访问允许端,高电平时从外部程序存储器读取指令,低电平时从内部程序存储器读取指令;编程时作为编程电源输入
31P0.0端口0的第0位,双向I/O口,在访问外部存储器时还用作低8位地址/数据总线
.........
38P0.7端口0的第7位,双向I/O口,在访问外部存储器时还用作低8位地址/数据总线

 在Keil中编写程序代码 

准备工作

这里我使用得Keil4,大家在编写代码前一定要看一下是不是C51的版本。这里斌酱问我如何下载Keil4/5和C51 ,这里在官网下载就可以:Keil Product Downloads,ARM架构芯片下载ARM-MDK,C51系列下载C51就可以,32位51单片机下载C251.

安装过程中需要完成注册才能正常使用,在CSDN里有一大堆应对方法,无需淘宝付费购买,免费使得我像犀牛一样快乐。

在后续的新建项目中,要选择Atmel公司的AT89C51芯片 

头文件及c语言文件

LCD1602.h

#ifndef __LCD_H__  
#define __LCD_H__  #define LCD_GO_HOME               0x02         // 设置AC(地址计数器)为0,并返回HOME位置  // 地址计数器自动增减设置  
#define LCD_AC_AUTO_INCREMENT     0x06         // 写入数据后,地址计数器自动加1  
#define LCD_AC_AUTO_DECREASE      0x04         // 写入数据后,地址计数器自动减1  
#define LCD_MOVE_ENABLE           0x05         // 允许显示数据移动  
#define LCD_MOVE_DISENABLE        0x04         // 禁止显示数据移动  // 显示控制相关指令  
#define LCD_DISPLAY_ON            0x0C         // 显示开  
#define LCD_DISPLAY_OFF           0x08         // 显示关  
#define LCD_CURSOR_ON             0x0A         // 光标显示  
#define LCD_CURSOR_OFF            0x08         // 光标不显示  
#define LCD_CURSOR_BLINK_ON       0x09         // 光标闪烁  
#define LCD_CURSOR_BLINK_OFF      0x08         // 光标不闪烁  // 显示移动相关指令,影响DDRAM(显示数据RAM)  
#define LCD_LEFT_MOVE             0x18         // LCD显示左移一位  
#define LCD_RIGHT_MOVE            0x1C         // LCD显示右移一位  
#define LCD_CURSOR_LEFT_MOVE      0x10         // 光标左移一位  
#define LCD_CURSOR_RIGHT_MOVE     0x14         // 光标右移一位  // 显示模式设置  
#define LCD_DISPLAY_DOUBLE_LINE   0x38         // 双行显示模式  
#define LCD_DISPLAY_SINGLE_LINE   0x30         // 单行显示模式  void LCD_cls(void);               // 清屏函数  
void LCD_write_data(unsigned char); // 写入数据到LCD  
void LCD_initial(void);             // 初始化LCD  
void LCD_set_position(unsigned char); // 设置LCD显示位置  
void LCD_prints(unsigned char *);   // 在LCD上显示字符串  
void LCD_printc(unsigned char);     // 在LCD上显示单个字符  #endif

 LCD1602.c

#include "hardware.h"  
#include "lcd1602.h"  // 检查LCD是否忙碌,若忙碌则等待其空闲  
void LCD_check_busy(void)  
{  while(1)  {  LCD_EN = 0;  LCD_RS = 0;  LCD_RW = 1;  LCD_DATA = 0xff;  LCD_EN = 1;  if (!LCD_BUSY) break; // 若LCD不忙碌,则跳出循环  }  LCD_EN = 0;  
}  // 清屏函数,用于清除LCD上的显示内容  
void LCD_cls(void)  
{  LCD_check_busy(); // 首先检查LCD是否忙碌  LCD_RS = 0;  LCD_RW = 0;  LCD_DATA = 1;     // 发送清屏指令  LCD_EN = 1;  LCD_EN = 0;  
}  // 向LCD写入指令  
void LCD_write_instruction(unsigned char LCD_instruction)  
{  LCD_check_busy(); // 检查LCD是否忙碌  LCD_RS = 0;  LCD_RW = 0;  LCD_DATA = LCD_instruction; // 设置要写入的指令  LCD_EN = 1;  LCD_EN = 0;  
}  // 向LCD写入数据  
void LCD_write_data(unsigned char LCD_data)  
{  LCD_check_busy(); // 检查LCD是否忙碌  LCD_RS = 1;  LCD_RW = 0;  LCD_DATA = LCD_data; // 设置要写入的数据  LCD_EN = 1;  LCD_EN = 0;  
}  // 设置LCD的显示位置  
void LCD_set_position(unsigned char x)  
{  LCD_write_instruction(0x80 + x); // 通过写入指令来设置显示位置  
}  // 向LCD打印单个字符  
void LCD_printc(unsigned char lcd_data)  
{  LCD_write_data(lcd_data); // 写入要打印的字符数据  
}  // 向LCD打印字符串  
void LCD_prints(unsigned char *lcd_string)  
{  unsigned char i = 0;  while (lcd_string[i] != 0x00) // 遍历字符串,直到遇到结束符'\0'  {  LCD_write_data(lcd_string[i]); // 写入字符串中的每个字符  i++;  }  
}  // 初始化LCD  
void LCD_initial(void)  
{  LCD_write_instruction(LCD_AC_AUTO_INCREMENT | LCD_MOVE_DISENABLE); // 设置地址计数器自动增加,禁止显示移动  LCD_write_instruction(LCD_DISPLAY_ON | LCD_CURSOR_OFF); // 开启显示,关闭光标  LCD_write_instruction(LCD_DISPLAY_DOUBLE_LINE); // 设置为双行显示模式  LCD_cls(); // 清屏  
}

 hardware.h

#include <reg51.h>	#ifndef __HARDWARE_H__ 
#define __HARDWARE_H__  #define LCD_DATA P1 // 将LCD的数据线定义为P1端口  sbit LCD_BUSY=LCD_DATA^7;  // 将LCD的BUSY位定义为P1.7,用于检测LCD是否忙碌  
sbit LCD_RW=P2^0;          // 将LCD的读写控制位定义为P2.0,用于控制读写操作  
sbit LCD_RS=P2^1;          // 将LCD的寄存器选择位定义为P2.1,用于选择数据寄存器或指令寄存器  
sbit LCD_EN=P2^2;          // 将LCD的使能位定义为P2.2,用于控制LCD的使能信号  #endif

main.c

#include<reg51.h>
#include<LCD1602.h> void main(void)
{LCD_initial();LCD_set_position(0);LCD_printc('G');LCD_prints("hello gayboys");LCD_set_position(0x40);LCD_printc('G');while(1){;}
}
 构建Hex文件

在构建之前需要先确定下有没有将文件正确导入到项目中,双击下项目文件夹即可

 随后即可点击魔法棒图标,将 Create HEX File 构建hex文件

Project 栏点击 Build target 对项目进行构建

构建成功  ! 

运行项目 

 这时候就可以回到Proteus中了,双击AT89C51芯片,在 Program File 中添加刚刚构建的hex文件

点击左下角的小箭头运行项目

 运行成功!Gay Away !!! 

相关文章:

C语言实现:C51单片机驱动LCD屏幕显示字符串(Proteus+Keil)

在Proteus中绘制电路原理图 我使用的版本是Protues8.16 ,Protues特别擅长仿真单片机及其外围设备&#xff0c;支持多种类型的微控制器&#xff0c;如8051、HC11、PIC、AVR、ARM、MSP430等&#xff0c;也可以设计pcb板&#xff0c;还能3D建模 1.新建工程 在 Start 栏中点击 …...

暄桐好作业之《临沈周〈东庄图册〉局部》

暄桐是一间传统美学教育教室&#xff0c;创办于2011年&#xff0c;林曦是创办人和授课老师&#xff0c;教授以书法为主的传统文化和技艺&#xff0c;皆在以书法为起点&#xff0c;亲近中国传统之美&#xff0c;以实践和所得&#xff0c;滋养当下生活。      其中“暄桐好作…...

Qt3D创建3D物体步骤

使用Qt3D接口创建3D物体的步骤大致有以下几步: 1.创建一个3D窗口 2.创建根实体 3.创建物体实体,父指针为根实体 4.创建立体图形,即物体网格,设置物体的属性 5.给立体图形添加材质,添加坐标位置,添加纹理,添加其他效果 6.创建摄像头,设置摄像头的属性,父指针为根…...

UDP程序设计

UDP协议概述 UDP&#xff0c;User Datagram Protocol&#xff0c;用户数据报协议&#xff0c;是一个简单的面向数据报(package-oriented)的传输层协议&#xff0c;规范为&#xff1a;RFC 768。 UDP提供数据的不可靠传递&#xff0c;它一旦把应用程序发给网络层的数据发送出去…...

计算机网络—电路、分组、报文交换—图文详解

计算机网络—电路、分组、报文交换 计算机网络中的数据传输方式可以根据数据的处理方式和网络资源的使用方式分为电路交换、分组交换和报文交换三种类型。 这些方式在网络设计和数据传输过程中起到了不同的作用和效果。 1. 电路交换&#xff08;Circuit Switching&#xff0…...

linux下交叉编译licensecc

本文章只做个人笔记用 下载地址&#xff1a; #https://github.com/open-license-manager/licensecc.git #下面地址下不下来就是用第一个去官网下载git clone --recursive https://github.com/open-license-manager/licensecc.git 编译前准备3个库&#xff1a;openssl&#x…...

模型剪枝综述

目录 1 深度神经网络的稀疏性&#xff1a; 2 剪枝算法分类&#xff1a; 3 具体的剪枝方法包括&#xff1a; 4 剪枝算法流程&#xff1a; 5 几种常见的剪枝算法&#xff1a; 6 结构化剪枝和非结构化剪枝各有其优缺点&#xff1a; 7 剪枝算法对模型精度的影响 8 影响剪枝…...

破解监控难题,局域网电脑监控软件哪家强?

现在的环境&#xff0c;企业要想茁壮成长&#xff0c;员工的高效工作那可是关键中的关键。但不少老板都发现了一个头疼的问题&#xff0c;员工上班老是偷懒&#xff0c;这可怎么行&#xff1f;今天&#xff0c;就来给大家详细说道说道几款出色的局域网电脑监控软件&#xff0c;…...

Linux--Socket编程TCP

前文&#xff1a;Socket套接字编程 TCP的特点 面向连接&#xff1a;TCP 在发送数据之前&#xff0c;必须先建立连接。可靠性&#xff1a;TCP 提供了数据传输的可靠性。面向字节流&#xff1a;TCP 是一个面向字节流的协议&#xff0c;这意味着 TCP 将应用程序交下来的数据看成是…...

Android Studio导入源码

在有源码并且编译环境可用的情况下&#xff1a; 1.生成导入AS所需的配置文件 在源码的根目录执行以下命令&#xff1a; source build/ensetup.sh lunch 要编译的项目 make idegen //这一步会生成out/host/linux-x86/framework/idegen.jar development/tools/idegen/idegen.sh…...

UE5 UE4 使用python进行编辑器操作

使用UE 4.25以上版本后&#xff0c;python代码改动相对较少。 如下类库在4.20/21/22等早起版本不适用&#xff0c;建议查询UE的python文档 unreal.EditorAssetLibrary 1.获取当前选中的资源&#xff08;Content中&#xff09; # 获取当前选中的资产selected_assets unreal.E…...

区块链技术在智能城市中的创新应用探索

随着全球城市化进程的加速和信息技术的快速发展&#xff0c;智能城市成为了未来城市发展的重要方向。在智能城市建设中&#xff0c;区块链技术作为一种去中心化、安全和透明的分布式账本技术&#xff0c;正逐渐展现出其在优化城市管理、提升公共服务和增强城市安全性方面的潜力…...

解决mysql事件调度器重启服务后自动失效的问题

前段时间为通过mysql事件生成测试数据&#xff0c;今天发现数据在10:57后停止了CREATE EVENT IF NOT EXISTS insert_random_data ON SCHEDULE EVERY 10 SECOND DO INSERT INTO test (createtime, random_number) VALUES (NOW(), FLOOR(RAND() * 100));检查事件状态&#…...

mybatis开启二级缓存

例子 mybatis-config.xml <configuration><settings><setting name"cacheEnabled" value"true"/></settings><environments default"development"><environment id"development"><transacti…...

Oracle大型数据库管理(一)Oracle大型数据库管理全面指南

文章目录 Oracle大型数据库管理全面指南引言1. Oracle数据库概述1.1 什么是Oracle数据库1.2 Oracle数据库的主要特点 2. Oracle数据库部署2.1 安装前的准备工作2.1.1 操作系统要求2.1.2 硬件要求2.1.3 软件环境要求 2.2 Oracle数据库的安装2.2.1 用户和目录的创建2.2.2 安装Ora…...

Arcgis中查找空间距离范围内字段相等的数据

背景 目前有两份空间点数据&#xff0c;需要通过点数据1查找100米空间距离范围内点数据2中与点数据1某个字段相同的数据 步骤 1、arcgis中加载数据 2、空间连接 结果&#xff0c;从下面这两个字段可以看出&#xff0c;点数据1在100米空间距离范围内有多个点数据2 3、选择数…...

js中map属性

JavaScript中的Map对象保存键值对&#xff0c;并且能够记住键的原始插入顺序 以下是关于如何在JavaScript中使用Map对象的博客文章概要&#xff1a; 一、创建和初始化Map对象 使用new Map()构造函数可以创建一个新的Map对象。你还可以在构造函数中传入一个可迭代对象&#x…...

CS224W—03 GNN

CS224W—03 GNN 回顾 快速回顾一下上一讲的内容。我们学到的关键概念是节点嵌入&#xff08;Node Embedding&#xff09;。我们的直觉是将网络中的节点编码到低维向量空间中。我们希望学习一个接受输入图的函数 f f f&#xff0c;并将其嵌入到低维节点嵌入空间中。在这里&am…...

库存超卖问题解决方式

文章目录 超卖问题解决方式什么是库存超卖问题&#xff1f;乐观锁和悲观锁的定义超卖问题解决方式一、悲观锁1.jvm单机锁2.通过使用mysql的行锁&#xff0c;使用一个sql解决并发访问问题3.使用mysql的悲观锁解决4. 使用redis分布式锁来解决 二、乐观锁解决1.版本号2. CAS法&…...

30岁决心转行,AI太香了

今天是一篇老学员的经历分享&#xff0c;此时的王同学在大洋彼岸即将毕业&#xff0c;手握多家北美大厂offer&#xff0c;一片明媚。谁能想到王同学的转码之路竟始于一场裁员&#xff0c;这场访谈拉开了他的回忆。 最近总刷到一些关于转行的话题&#xff0c;很多刚毕业的同学喜…...

Java 语言特性(面试系列1)

一、面向对象编程 1. 封装&#xff08;Encapsulation&#xff09; 定义&#xff1a;将数据&#xff08;属性&#xff09;和操作数据的方法绑定在一起&#xff0c;通过访问控制符&#xff08;private、protected、public&#xff09;隐藏内部实现细节。示例&#xff1a; public …...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)

船舶制造装配管理现状&#xff1a;装配工作依赖人工经验&#xff0c;装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书&#xff0c;但在实际执行中&#xff0c;工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...

Linux系统部署KES

1、安装准备 1.版本说明V008R006C009B0014 V008&#xff1a;是version产品的大版本。 R006&#xff1a;是release产品特性版本。 C009&#xff1a;是通用版 B0014&#xff1a;是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存&#xff1a;1GB 以上 硬盘&#xf…...

深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向

在人工智能技术呈指数级发展的当下&#xff0c;大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性&#xff0c;吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型&#xff0c;成为释放其巨大潜力的关键所在&…...

【UE5 C++】通过文件对话框获取选择文件的路径

目录 效果 步骤 源码 效果 步骤 1. 在“xxx.Build.cs”中添加需要使用的模块 &#xff0c;这里主要使用“DesktopPlatform”模块 2. 添加后闭UE编辑器&#xff0c;右键点击 .uproject 文件&#xff0c;选择 "Generate Visual Studio project files"&#xff0c;重…...

Xcode 16 集成 cocoapods 报错

基于 Xcode 16 新建工程项目&#xff0c;集成 cocoapods 执行 pod init 报错 ### Error RuntimeError - PBXGroup attempted to initialize an object with unknown ISA PBXFileSystemSynchronizedRootGroup from attributes: {"isa">"PBXFileSystemSynchro…...