我在高职教STM32——LCD液晶显示(3)

news2025/1/13 7:44:40

        大家好,我是老耿,高职青椒一枚,一直从事单片机、嵌入式、物联网等课程的教学。对于高职的学生层次,同行应该都懂的,老师在课堂上教学几乎是没什么成就感的。正因如此,才有了借助 CSDN 平台寻求认同感和成就感的想法。在这里,我准备陆续把自己花了很多心思的教学设计分享出来,主要面向广大师生朋友,单片机老鸟就略过吧。欢迎点赞+关注,各位的支持是本人持续输出的动力,多谢多谢!

        前边我们讲解了LED、按键和蜂鸣器的应用,这三类器件本身工作原理十分简单,因此我们的重点是放在STM32的GPIO上面。这一章我们来学习一下开发板配套的那块厚厚的液晶屏——LCD1602,聚焦的是这个器件本身的特点和工作时序。因此,我们需要熟读它的数据手册,因为手册里告诉了编程的要点、参数、时序等。阅读器件手册是做单片机和嵌入式开发必备的基本能力,我们就从这一章开始锻炼起来吧。为了不让篇幅太长,本章打算分四个部分来讲解,本文是第三部分。

【学习目标】

  1. 了解LCD1602的工作原理
  2. 掌握LCD1602的工作时序
  3. 领悟软件模拟时序的思路和方法

三、液晶静态显示实验

        本章的前两个部分花了不少篇幅,全方面的介绍了LCD1602以及与开发板之间的联系,传递出来的无非就是一个意思——吃透数据手册这别无他法,结合参考程序反复阅读手册,慢慢感悟,开发经验就是这么积累起来的。学完这个入门的液晶屏,后面还有更复杂的彩屏和触摸屏等着我们去学习,依然是“啃”数据手册。好了,下面我们就动手来写一个程序,把手册里的内容转换成代码,驱动LCD1602去显示我们想要的效果。

3.1 任务描述

        编写LCD1602驱动代码,上电之后可以在指定位置显示字符串信息,实验效果如图13所示。

图13 LCD1602静态显示实验效果

3.2 工程文件清单

        与之前的工程一样,控制一类新的硬件就增加一对与之匹配的驱动文件,即图14中的 lcd1602.clcd1602.h

图14 LCD1602工程文件

3.3 工程源码剖析

        这里为了突出源码的功能细节和排版之需,对源码进行了必要的分割处理。

3.3.1 lcd1602.h源码剖析

        该文件源码见代码清单4,主要是LCD1602端口操作的宏定义和驱动函数的声明,每个函数的功能和参数将在下面剖析 lcd1602.c 源码时解读。

//---------------------------------------------------------
// 代码清单4:lcd1602.h
//---------------------------------------------------------

#ifndef _LCD1602_H_
#define _LCD1602_H_
#include "stm32f10x.h"

//---------------------------------------------------------
// 端口操作宏定义
//---------------------------------------------------------
#define	 RS_H	GPIO_SetBits(GPIOC, GPIO_Pin_6)
#define  RS_L	GPIO_ResetBits(GPIOC, GPIO_Pin_6)
#define  RW_H	GPIO_SetBits(GPIOA, GPIO_Pin_11)
#define  RW_L	GPIO_ResetBits(GPIOA, GPIO_Pin_11)
#define  EN_H	GPIO_SetBits(GPIOB, GPIO_Pin_4)
#define  EN_L	GPIO_ResetBits(GPIOB, GPIO_Pin_4)
#define  READ_BUSY()	GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_2)

//通过直接配置寄存器来改变PC2是输入还是输出
//读液晶状态时是输入,写命令和写数据时是输出
//GPIOx->CRL寄存器描述见手册8.2.1小节(P113)
#define PC2_OUT()	{GPIOC->CRL&=0xFFFFF0FF; GPIOC->CRL|=0x00000300;}
#define PC2_IN()	{GPIOC->CRL&=0xFFFFF0FF; GPIOC->CRL|=0x00000800;}

//---------------------------------------------------------
// 驱动函数声明
//---------------------------------------------------------
_Bool Lcd1602_WaitReady(void);
void Lcd1602_SendByte(u8 byte);
void Lcd1602_WriteCmd(u8 byte);
void Lcd1602_WriteData(u8 byte);
void Lcd1602_ShowChar(u8 x, u8 y, u8 ch);
void Lcd1602_ShowStr(u8 x, u8 y, u8 *str);
void Lcd1602_Clear(u8 pos);
void Lcd1602_Init(void);
void Lcd1602_Printf(u8 x, u8 y, char *fmt, ...);

#endif

3.3.2 lcd1602.c源码剖析

        该文件就是所有LCD1602驱动函数的定义,下面就逐个进行剖析。

        1) 头文件部分

        首先,把必要的头文件都加进来,如代码清单5所示。

/*
 ************************************************************************
 * 代码清单5:lcd1602.c的头文件
 * 描    述:LCD1602初始化、驱动
 * 平    台:麒麟座V3.2
 * 作    者:老耿
 * 日    期:2024-04-09
 * 固 件 库:ST3.5.0
 * 版    本:V1.0
 * 修改记录:无
 ************************************************************************
*/

//必要的头文件
#include "delay.h"
#include "lcd1602.h"

//C库
#include <stdarg.h>
#include <stdio.h

        2) Lcd1602_WaitReady()函数源码

        该函数就是用来检测液晶是否准备好,返回1表示“忙”,返回“0”表示“不忙”。详细源码见如下代码清单6。

/*
************************************************************
*	代码清单6:	Lcd1602_WaitReady()函数
*	函数功能:	等待液晶准备好
*	入口参数:	无
*	返回参数:	1:忙,0:不忙
*	说明:
************************************************************
*/
_Bool Lcd1602_WaitReady(void)
{
	PC2_IN();		//PC2输入模式
	RS_L;			//拉低RS
	RW_H;			//拉高RW
	EN_L;			//
	delay_us(1);	//EN高脉冲
	EN_H;			//
	return (_Bool)READ_BUSY();	//返回PC2状态
}

        2) Lcd1602_SendByte()函数源码

        该函数把一个字节(参数byte)送上液晶的8位数据端口,高3位送到PC2 ~ PC0,低5位送上PB9 ~ PB5。送数的过程如代码清单7所示,有一点曲折,但各位可以从中好好体会一下C语言位操作的严谨和奇妙。

/*
************************************************************
*	代码清单7:	Lcd1602_SendByte()函数
*	函数功能:	向LCD1602写一个字节
*	入口参数:	byte:需要写入的数据
*	返回参数:	无
*	说明:		
************************************************************
*/
void Lcd1602_SendByte(u8 byte)
{
	u16 value = 0;
	value = GPIO_ReadOutputData(GPIOB);		//读取GPIOB的数据
	value &= ~(0x001F << 5);				//清除bit5~8
	value |= ((u16)byte & 0x001F) << 5;		//将要写入的数据取低5位并左移5位
	GPIO_Write(GPIOB, value);				//写入GPIOB
	
	value = GPIO_ReadOutputData(GPIOC);		//读取GPIOC的数据
	value &= ~(0x0007 << 0);				//清除bit0~2
	value |= ((u16)byte & 0x00E0) >> 5;		//将要写入的数据取高3位并右移5位
	GPIO_Write(GPIOC, value);				//写入GPIOC
	
	delay_us(10);
}

        首先,我们得清楚,要改变的只有PC2 ~ PC0、PB9 ~ PB5这8位,而这两组I/O的其他位是不能变的,因为其它I/O还连着别的硬件呢。所以,才有了先保存这组I/O的值。接下来,低5位的操作过程可以用图15来表示,这几句很好的诠释了C语言常见的位操作在嵌入式层面是如何应用的,希望各位能好好领悟。同理,高3位送到PC2~PC0,各位可以自己琢磨和推导一下。

图15 PB9~PB5的送数过程

        3) Lcd1602_WriteCmd()函数源码

        该函数实现写一个命令(参数byte)到LCD1602,就是按照数据手册上写命令的时序编写的,大家可以对照手册来阅读,源码见如下代码清单8。

/*
************************************************************
*	代码清单8:	Lcd1602_WriteCmd()函数
*	函数功能:	向LCD1602写命令
*	入口参数:	byte:需要写入的命令
*	返回参数:	无
*	说明:
************************************************************
*/
void Lcd1602_WriteCmd(u8 byte)
{
	while(Lcd1602_WaitReady());		//等到不忙
	PC2_OUT();						//PC2输出模式
	RS_L;							//拉低RS
	RW_L;							//拉低RW
	Lcd1602_SendByte(byte);			//准备命令码
	EN_H;							//拉高使能
	delay_us(20);					//保持一定时间
	EN_L;							//拉低使能
	delay_us(5);
}

        4) Lcd1602_WriteData()函数源码

        该函数与写命令函数是一个套路,就是通过拉高RS改成了数据模式,源码见代码清单9。

/*
************************************************************
*	代码清单9:	Lcd1602_WriteData()
*	函数功能:	向LCD1602写数据
*	入口参数:	byte:需要写入的数据
*	返回参数:	无
*	说明:
************************************************************
*/
void Lcd1602_WriteData(u8 byte)
{
	while(Lcd1602_WaitReady());		//等到不忙
	PC2_OUT();						//PC2输出模式
	RS_H;							//拉高RS
	RW_L;							//拉低RW
	Lcd1602_SendByte(byte);			//准备数据
	EN_H;							//拉高使能
	delay_us(20);					//保持一定时间
	EN_L;							//拉低使能
	delay_us(5);
}

        5) Lcd1602_SetCursor()函数源码

        该函数用来设置光标的位置,参数x和y是位置坐标,x是行坐标(0表示第一行,1表示第二行),y是列坐标(0~15),源码见如下代码清单10。

/*
************************************************************
*	代码清单10:	Lcd1602_SetCursor()函数
*	函数功能:	设置显示RAM地址地址,即光标位置
*	入口参数:	x:行坐标(0第一行,1第二行)
*				y:列坐标(0~15)
*	返回参数:	无
*	说明:
************************************************************
*/
void Lcd1602_SetCursor(u8 x, u8 y)
{
	u8 addr;
	
	if(x==0)				//第一行
		addr = 0x00 + y;
	else					//第二行
		addr = 0x40 + y;

	Lcd1602_WriteCmd(addr|0x80);	//写入地址
}

        6) Lcd1602_ShowChar()函数源码

        该函数用来显示单个字符,参数x和y与上面一样,确定在哪个位置显示,ch为字符内容,源码见如下代码清单11。

/*
************************************************************
*	代码清单11:	Lcd1602_ShowChar()函数
*	函数功能:	在液晶上显示单个字符
*	入口参数:	x和y:显示的坐标(同上)
*				ch:待显示的字符
*	返回参数:	无
*	说明:
************************************************************
*/
void Lcd1602_ShowChar(u8 x, u8 y, u8 ch)
{
	Lcd1602_SetCursor(x, y);	//设置坐标
	Lcd1602_WriteData(ch);		//显示字符
}

        7) Lcd1602_ShowStr()函数源码

        该函数用来显示字符串信息,参数x和y与上面一样,确定从哪个位置开始显示,*str指向待显示的字符串空间,源码见如下代码清单12。

/*
************************************************************
*	代码清单12:	Lcd1602_ShowStr()函数
*	函数功能:	在液晶上显示字符串
*	入口参数:	x和y:显示的起始坐标(同上)
*				str:字符串指针
*	返回参数:	无
*	说明:
************************************************************
*/
void Lcd1602_ShowStr(u8 x, u8 y, u8 *str)
{
	Lcd1602_SetCursor(x, y);
	
	//每写完一个字符,光标会自动指向下一个位置
	while(*str)		//字符串没结束就不停
	{
		Lcd1602_WriteData(*str);	//写入当前字符
		str++;						//指向下一个字符
	}
}

        8) Lcd1602_Clear()函数源码

        该函数用来清屏,参数pos可取值为0、1、2,分别表示清除第一行、第二行和整屏,源码见如下代码清单13。

/*
************************************************************
*	代码清单13:	Lcd1602_Clear()函数
*	函数功能:	LCD1602清除指定行
*	入口参数:	pos:指定的行
*	返回参数:	无
*	说明:		0-第一行		1-第二行		2-两行
************************************************************
*/
void Lcd1602_Clear(u8 pos)
{
	switch(pos)
	{
		case 0:
			Lcd1602_ShowStr(0, 0 , "                ");
			break;
		case 1:
			Lcd1602_ShowStr(1, 0 , "                ");
			break;		
		case 2:
			Lcd1602_WriteCmd(0x01);	//清屏命令
			break;
		default:
			break;
	}
}

        9) Lcd1602_Init()函数源码

        该函数完成LCD1602上电之后的初始化,一方面将所连接的I/O口全部初始化,另一方面按照数据手册交待的复位步骤对液晶进行初始化,源码见如下代码清单14。

/*
************************************************************
*	代码清单14:	Lcd1602_Init()函数
*	函数功能:	LCD1602初始化
*	入口参数:	无
*	返回参数:	无
*	说明:		RW-PA11		RS-PC6		EN-PC3
*				D7~D5 - PC2~PC0		D4~D0 - PB9~PB5
************************************************************
*/
void Lcd1602_Init(void)
{
	GPIO_InitTypeDef gpio_initstruct;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | \
						   RCC_APB2Periph_GPIOB | \
						   RCC_APB2Periph_GPIOC, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);	//禁止JTAG功能
	
	gpio_initstruct.GPIO_Mode = GPIO_Mode_Out_PP;
	gpio_initstruct.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | \
							   GPIO_Pin_6 | GPIO_Pin_7 | \
							   GPIO_Pin_8 | GPIO_Pin_9;
	gpio_initstruct.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &gpio_initstruct);
	
	gpio_initstruct.GPIO_Pin = GPIO_Pin_11;
	GPIO_Init(GPIOA, &gpio_initstruct);
	
	gpio_initstruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | \
							   GPIO_Pin_2 | GPIO_Pin_6;
	GPIO_Init(GPIOC, &gpio_initstruct);
			
    Lcd1602_WriteCmd(0x38);	//16*2显示,5*7点阵,8位数据接口
    Lcd1602_WriteCmd(0x0C);	//开显示,光标关闭
    Lcd1602_WriteCmd(0x06);	//字符不动,光标移动
    Lcd1602_WriteCmd(0x01);	//清屏
}

        LCD1602液晶手册提供了一个初始化过程,由于不检测“忙”位,所以程序比较复杂,如图16所示。而我们编写的程序已经将检测“忙”位的功能嵌入到写操作里面了,所以只用了最后4行语句就完成了同样效果,更加简易方便。手册上描述的那个,大家仅作了解即可。以后在别的资料里看到了与我们这类不一样的初始化也不要困惑,注意跟我们这里联系和对比。

图16 数据手册上的初始化过程

3.3.3 main.c源码剖析

        主程序比较简单,完成初始化之后就调用显示函数在屏上指定的位置显示指定的字符串,源码见如下代码清单15。

/**
 ******************************************************
 * 代码清单15:main.c
 * 项    目:LCD1602液晶显示
 * 任务描述:静态显示
 * 实验平台:OneNET STM32开发板V3.2
 * 作    者:老耿
 * 日    期:yyyy/mm/dd
 ******************************************************
**/
 
//-----------------------------------------------------
// 必要的头文件
//-----------------------------------------------------
#include "delay.h"
#include "lcd1602.h"

int main()
{
	delay_init();				//Systick初始化,用于普通的延时
	Lcd1602_Init();				//LCD1602初始化
	
	Lcd1602_ShowStr(0, 3, "KylinV3.2");		//第一行第4个字符开始显示字符串
	Lcd1602_ShowStr(1, 2, "STM32 Board");	//第二行第3个字符开始显示字符串

	while(1);
}

3.3.4 验证与测试

        程序下载前,接好液晶屏和电源适配器,并将电源拨动开关置于OFF处(如图17所示)。程序下载后,电源开关拨至ON,即可实现实验效果。

图17 实验效果与电源拨动开关

(第三部分完,共四部分) 

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

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

相关文章

【Linux详解】冯诺依曼架构 | 操作系统设计 | 斯坦福经典项目Pintos

目录 一. 冯诺依曼体系结构 (Von Neumann Architecture) 注意事项 存储器的意义&#xff1a;缓冲 数据流动示例 二. 操作系统 (Operating System) 操作系统的概念 操作系统的定位与目的 操作系统的管理 系统调用和库函数 操作系统的管理&#xff1a; sum 三. 系统调…

数据类型 运算符

基本数据类型与引用数据类型的区分 存储内容&#xff1a; 基本数据类型&#xff1a;直接存储实际的数据值&#xff0c;如整数、浮点数、字符等。引用数据类型&#xff1a;存储对象的引用&#xff08;内存地址&#xff09;&#xff0c;而不是对象本身。 内存分配&#xff1a; 基…

Qt——系统

目录 概述 事件 鼠标事件 进入、离开事件 按下事件 释放事件 双击事件 移动事件 滚轮事件 按键事件 单个按键 组合按键 定时器 QTimerEvent QTimer 窗口事件 文件 输入输出设备 文件读写类 文件和目录信息类 多线程 常用API 线程安全 互斥锁 条件变量…

matplotlib之常见图像种类

Matplotlib 是一个用于绘制图表和数据可视化的 Python 库。它支持多种不同类型的图形&#xff0c;以满足各种数据可视化需求。以下是一些 Matplotlib 支持的主要图形种类&#xff1a; 折线图&#xff08;Line Plot&#xff09;&#xff1a; 用于显示数据随时间或其他连续变量的…

珈和科技和比昂科技达成战略合作,共创智慧农业领域新篇章

6月14日&#xff0c;四川省水稻、茶叶病虫害监测预警与绿色防控培训班在成都蒲江举办。本次培训班由四川省农业农村厅植物保护站主办&#xff0c;蒲江县农业农村局、成都比昂科技筹办。四川省农业农村厅植物保护站及四川省14个市州36个县植保站负责人进行了观摩学习。 武汉珈…

Python中的性能分析和优化

在前几篇文章中&#xff0c;我们探讨了Python中的异步编程和并发编程&#xff0c;以及如何结合使用这些技术来提升程序性能。今天&#xff0c;我们将深入探讨如何分析以及优化Python代码的性能&#xff0c;确保应用程序的高效运行&#xff01; 性能分析的基本工具和方法 在进…

[系统运维|Xshell]宿主机无法连接上NAT网络下的虚拟机进行维护?主机ping不通NAT网络下的虚拟机,虚拟机ping的通主机!解决办法

遇到的问题&#xff1a;主机ping不通NAT网络下的虚拟机&#xff0c;虚拟机ping的通主机 服务器&#xff1a;Linux&#xff08;虚拟机&#xff09; 主机PC&#xff1a;Windows 虚拟机&#xff1a;vb&#xff0c;vm测试过没问题&#xff0c;vnc没测试不清楚 虚拟机网络&#xff1…

cve-2015-3306-proftpd-vulfocus

1.原理 proftp是用于搭建基于ftp协议的应用软件 ProFTPD是ProFTPD团队的一套开源的FTP服务器软件。该软件具有可配置性强、安全、稳定等特点。 ProFTPD 1.3.5中的mod_copy模块允许远程攻击者通过站点cpfr和site cpto命令读取和写入任意文件。任何未经身份验证的客户端都可以…

牛客周赛Round48

第一题 A-小红的整数自增 链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 小红拿到了三个正整数。她准备进行若干次操作&#xff0c;每次操作选择一个元素加1。小红希望最终三个数相等&#xff0c;请你帮小红求出最小的操作次数。 思路&#x…

Spring Boot + WebSocket 实现 IM 即时通讯

文章目录 1. 项目环境准备2. 配置WebSocket3. 创建消息处理器4. 创建消息类5. 创建前端页面6. 启动应用并测试7. 分析与扩展结论 &#x1f389;欢迎来到SpringBoot框架学习专栏~ ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x1f379;✨博客主页&#xff1a;IT陈寒的博客&#x1f388;…

优选算法刷题笔记 2024.6.10-24.6.20

一、双指针算法(快慢指针,对撞指针) 艹&#xff0c;CSDN吞了我是十三题笔记&#xff01;&#xff01;&#xff01; 二、滑动窗口(滑动窗口) 1、找到字符串中所有字母异位词 class Solution {public List<Integer> findAnagrams(String s, String p) {int[] hash1 new in…

示例:WPF中应用DependencyPropertyDescriptor监视依赖属性值的改变

一、目的&#xff1a;开发过程中&#xff0c;经常碰到使用别人的控件时有些属性改变没有对应的事件抛出&#xff0c;从而无法做处理。比如TextBlock当修改了IsEnabled属性我们可以用IsEnabledChanged事件去做对应的逻辑处理&#xff0c;那么如果有类似Background属性改变我想找…

Kimichat使用案例026:AI翻译英语PDF文档的3种方法

文章目录 一、介绍二、腾讯交互翻译TranSmart https://transmart.qq.com/三、沉浸式翻译三、谷歌网页翻译一、介绍 短的文章,直接丢进kimichat、ChatGPT里面很快就可以翻译完成,而且效果很佳。但是,很长的PDF文档整篇需要翻译,怎么办呢? 二、腾讯交互翻译TranSmart https…

Kafka中的数据本身就是倾斜的,使用FlinkSQL该如何处理

又是经历了一段不太平的变动&#xff0c;最近算是稳定了点&#xff0c;工作内容又从后端开发转换成了sql boy&#xff0c;又要开始搞大数据这一套了。不同的是之前写实时任务的时候都是用的java代码&#xff0c;新环境却更加偏向与使用flink sql 解决&#xff0c;所以记录下使用…

Rsync未授权访问-vulfocus

1.原理 Rsync是linux上文件传输的协议&#xff0c;如果有返回直接可以看到&#xff0c;部分主机使用协议的时候不会加密码&#xff0c;就容易造成未授权访问漏洞 2.复现 打开vulfocus.io,搜索rsync关键字&#xff0c;打开环境 在自己的主机上去连接远程服务器&#xff1a; r…

BFS:解决多源最短路问题

文章目录 什么是多源最短路问题&#xff1f;1.矩阵2.飞地的数量3.地图的最高点4.地图分析总结 什么是多源最短路问题&#xff1f; 多源最短路问题&#xff08;Multi-Source Shortest Path Problem&#xff0c;MSSP&#xff09;是图论中的一个经典问题&#xff0c;它的目标是在…

正则表达式,linux文本三剑客

正则表达式匹配的是文本内容&#xff0c;linux的文本三剑客都是针对文本内容&#xff0c;按行进行匹配 文本三剑客&#xff1a; grep 过滤文本内容 sed 针对文本内容进行增删改查 awd 按行取列 一.grep命令 作用就是使用正则表达式来匹配文本内容 -m 数字&#xff1a;匹配…

VMware与windows的共享文件夹没找到怎么办?

如果这样子添加&#xff0c;在ubuntu中还是没能找到。开机后有的时候仍然未发现共享文件夹。 二、解决办法 使用如下指令&#xff1a; sudo mount -t fuse.vmhgfs-fuse .host:/ /mnt/hgfs -o allow_other /mnt/hgfs/ 是挂载点&#xff0c;也可以指定其它挂载点 -o allow_other…

第14章. GPIO简介

目录 0. 《STM32单片机自学教程》专栏 14.1 GPIO基本结构 14.1.1 保护二极管 14.1.2 上拉、下拉电阻 14.1.3 施密特触发器 14.1.4 P-MOS 管和 N-MOS 管 14.1.5 输出数据寄存器 14.1.6 输入数据寄存器 14.2 GPIO工作模式 14.2.1 输入模式 14.2.1.1 输入浮空模式 1…

Nginx自定义错误页面配置

Nginx错误页面包括404 403 500 502 503 504等页面&#xff0c;只需要在server中进行如下配置即可&#xff1a; error_page 404 500 502 503 504 /50x.html;location /50x.html {root /usr/share/nginx/html;}注意&#xff1a; /usr/local/nginx/html/ 路径下必须有50x.ht…