51单片机应用开发(进阶)---定时器应用(电子时钟)
实现目标
1、巩固定时器的配置流程;
2、掌握按键、数码管与定时器配合使用;
3、功能1:(1)简单显示时间。显示格式:88-88-88(时-分-秒)
4、功能2:(1)K1功能键,按下按键选中时分秒进行调节;(2)K2:数值+1;(3)K3:数值-1;(4)K4:确认键,设置数值后按下确认,开始走时;(5)显示格式:88-88-88(时-分-秒)
5、功能3:(1)上面功能上,轮流显示年月日
一、电子时钟
电子时钟是一种使用电子技术来显示当前时间的设备。与传统的机械时钟不同,电子时钟通过电子电路和显示器来展示时间,通常具有更高的准确性和更多的功能。以下是关于电子时钟的简介:

1.1 基本结构
- 显示器:电子时钟的核心部分,用于显示时间。常见的显示器类型包括液晶显示屏(LCD)、发光二极管显示屏(LED)以及近年来逐渐兴起的有机发光二极管显示屏(OLED)。
- 电子电路:负责时间的计算、存储与显示。电子电路可以由模拟电路或数字电路构成,现代电子时钟多采用微处理器控制的数字电路。
- 电源:为电子时钟提供工作所需的电能。常见的电源类型包括电池、交流电源或两者的结合。
1.2 主要功能
- 时间显示:电子时钟可以准确显示当前的时间,包括小时、分钟和秒。
- 日期和星期显示:许多电子时钟还具备显示当前日期和星期的功能。
- 定时功能:可以设置闹钟或提醒功能,以便在特定时间发出声音或光信号。
- 其他功能:如温度显示、湿度显示、计时器、倒计时等附加功能,使电子时钟更加实用。
1.3 种类与特点
- 数字电子时钟:以数字形式显示时间,具有简洁明了的特点。数字电子时钟通常采用LED或LCD显示屏,易于读取且耗电量低。
- 模拟电子时钟:通过指针和表盘来模拟传统机械时钟的显示方式。模拟电子时钟通常具有更高的装饰性,适合追求复古或经典风格的用户。
- 智能电子时钟:结合了智能技术,如Wi-Fi连接、语音识别等,可以实现更多高级功能,如天气预报、音乐播放、智能家居控制等。智能电子时钟通常与智能手机或其他智能设备配合使用,提供更加个性化的用户体验。
1.4 技术原理
电子时钟的工作原理主要基于晶体振荡器产生的稳定频率信号。这个信号经过分频、计数等处理后,可以得到精确的时间信息。微处理器或专用的时间控制芯片会根据这些信息来控制显示器的显示内容,从而实现时间的准确显示。
1.5应用领域
电子时钟广泛应用于各个领域,包括家庭、办公室、公共场所等。由于其准确度高、功能丰富且易于携带,电子时钟已成为现代生活中不可或缺的时间测量工具。
二、原理图设计


三、程序设计
3.1 基本程序(不带按键功能)
#include <REGX52.H>//定义数码管位选信号控制脚
sbit LSA = P2^2;
sbit LSB = P2^3;
sbit LSC = P2^4;sbit K1 = P3^1;//按键K1
sbit K2 = P3^0;//按键K2char H = 22; //时计数
char M = 58; //分计数
char S = 45; //秒计数//共阴极数码管显示0~F的段码数据
unsigned char gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40};void delay_10us(int ten_us)
{while(ten_us--);
}unsigned int g_Count; //全局变量默认初始化为0void Timer1_Init(void)
{TMOD = 0x10; //设置定时器1 工作模式1 0001 0000 TR1 = 1; //开启定时器1TH1 = (65536-1000)/256; //设置定时初值,高8位TL1 = (65536-1000)%256; //设置定时初值,低8位ET1 = 1; //开启定时器1 中断EA = 1; //开启总中断
}void main(void)
{Timer1_Init(); //定时器1初始化while(1){LSC=1;LSB=1;LSA=1;P0 = gsmg_code[H/10];delay_10us(5);P0 = 0x00;//消影LSC=1;LSB=1;LSA=0;P0 = gsmg_code[H%10]; delay_10us(5);P0 = 0x00;//消影LSC=1;LSB=0;LSA=1;P0 = gsmg_code[16];delay_10us(5);P0 = 0x00;//消影LSC=1;LSB=0;LSA=0;P0 = gsmg_code[M/10]; delay_10us(5);P0 = 0x00;//消影 LSC=0;LSB=1;LSA=1;P0 = gsmg_code[M%10];delay_10us(5);P0 = 0x00;//消影LSC=0;LSB=1;LSA=0;P0 = gsmg_code[16];delay_10us(5);P0 = 0x00;//消影LSC=0;LSB=0;LSA=1;P0 = gsmg_code[S/10]; delay_10us(5);P0 = 0x00;//消影 LSC=0;LSB=0;LSA=0;P0 = gsmg_code[S%10];delay_10us(5);P0 = 0x00;//消影 }
}void Timer1_Rountine(void) interrupt 3 //1ms进一次中断
{TH1 = (65536-1000)/256; //TL1 = (65536-1000)%256; //重新赋初值才能保证下一次还是1msg_Count++;if(g_Count>=1000) // 1S 计时{g_Count = 0; //计数清零S++;if(S > 59)//1Min{S = 0;M++;if(M > 59)//1H{M = 0;H++;if(H > 23)//1H{H = 0; }}} }
}
3.2 带按键调值功能程序
#include <REGX52.H>//定义数码管位选信号控制脚
sbit LSA = P2^2;
sbit LSB = P2^3;
sbit LSC = P2^4;sbit K1 = P3^1;//按键K1
sbit K2 = P3^0;//按键K2
sbit K3 = P3^2;//按键K3
sbit K4 = P3^3;//按键K4char H = 22; //时计数
char M = 58; //分计数
char S = 45; //秒计数char mode = 0; //模式 //共阴极数码管显示0~F的段码数据
unsigned char gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40};void delay_10us(int ten_us)
{while(ten_us--);
}unsigned int g_Count; //全局变量默认初始化为0void Timer1_Init(void)
{TMOD = 0x10; //设置定时器1 工作模式1 0001 0000 TR1 = 1; //开启定时器1TH1 = (65536-1000)/256; //设置定时初值,高8位TL1 = (65536-1000)%256; //设置定时初值,低8位ET1 = 1; //开启定时器1 中断EA = 1; //开启总中断
}void main(void)
{Timer1_Init(); //定时器1初始化while(1){LSC=1;LSB=1;LSA=1;P0 = gsmg_code[H/10];delay_10us(5);P0 = 0x00;//消影LSC=1;LSB=1;LSA=0;P0 = gsmg_code[H%10]; delay_10us(5);P0 = 0x00;//消影LSC=1;LSB=0;LSA=1;P0 = gsmg_code[16];delay_10us(5);P0 = 0x00;//消影LSC=1;LSB=0;LSA=0;P0 = gsmg_code[M/10]; delay_10us(5);P0 = 0x00;//消影 LSC=0;LSB=1;LSA=1;P0 = gsmg_code[M%10];delay_10us(5);P0 = 0x00;//消影LSC=0;LSB=1;LSA=0;P0 = gsmg_code[16];delay_10us(5);P0 = 0x00;//消影LSC=0;LSB=0;LSA=1;P0 = gsmg_code[S/10]; delay_10us(5);P0 = 0x00;//消影 LSC=0;LSB=0;LSA=0;P0 = gsmg_code[S%10];delay_10us(5);P0 = 0x00;//消影 if(K1 == 0)//如果按键K1按下{while(!K1);//松手检测TR1 = 0;mode++;if(mode >3)mode = 1;}if(K4 == 0)//如果按键K4按下{while(!K4);//松手检测TR1 = 1; mode = 0;} if(K2 == 0)//如果按键K2按下{while(!K2);//松手检测switch (mode){case 1:H++;if(H > 23){H = 0; }break;case 2:M++;if(M > 59){M = 0; } break;case 3:S++;if(S > 59){S = 0; } break;}}if(K3 == 0)//如果按键K2按下{while(!K3);//松手检测switch (mode){case 1:H--;if(H < 0){H = 23; }break;case 2:M--;if(M < 0){M = 59; } break;case 3:S--;if(S < 0){S = 59; } break;}}}
}void Timer1_Rountine(void) interrupt 3 //1ms进一次中断
{TH1 = (65536-1000)/256; //TL1 = (65536-1000)%256; //重新赋初值才能保证下一次还是1msg_Count++;if(g_Count>=1000) // 1S 计时{g_Count = 0; //计数清零S++;if(S > 59)//1Min{S = 0;M++;if(M > 59)//1H{M = 0;H++;if(H > 23)//1H{H = 0; }}} }
}
3.3 轮换显示年月日功能程序
#include <REGX52.H>//定义数码管位选信号控制脚
sbit LSA = P2^2;
sbit LSB = P2^3;
sbit LSC = P2^4;sbit K1 = P3^1;//按键K1
sbit K2 = P3^0;//按键K2
sbit K3 = P3^2;//按键K3
sbit K4 = P3^3;//按键K4char H = 22; //时计数
char M = 58; //分计数
char S = 45; //秒计数char mode = 0; //模式
bit Display_falg = 0; //显示标志位
char S1 = 0; //秒计数
char S2 = 0; //秒计数
//共阴极数码管显示0~F的段码数据
unsigned char gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40};void delay_10us(int ten_us)
{while(ten_us--);
}unsigned int g_Count; //全局变量默认初始化为0void Timer1_Init(void)
{TMOD = 0x10; //设置定时器1 工作模式1 0001 0000 TR1 = 1; //开启定时器1TH1 = (65536-1000)/256; //设置定时初值,高8位TL1 = (65536-1000)%256; //设置定时初值,低8位ET1 = 1; //开启定时器1 中断EA = 1; //开启总中断
}void main(void)
{Timer1_Init(); //定时器1初始化while(1){if (Display_falg == 1){LSC=1;LSB=1;LSA=1;P0 = gsmg_code[2];delay_10us(5);P0 = 0x00;//消影LSC=1;LSB=1;LSA=0;P0 = gsmg_code[4]; delay_10us(5);P0 = 0x00;//消影LSC=1;LSB=0;LSA=1;P0 = gsmg_code[16];delay_10us(5);P0 = 0x00;//消影LSC=1;LSB=0;LSA=0;P0 = gsmg_code[1]; delay_10us(5);P0 = 0x00;//消影 LSC=0;LSB=1;LSA=1;P0 = gsmg_code[1];delay_10us(5);P0 = 0x00;//消影LSC=0;LSB=1;LSA=0;P0 = gsmg_code[16];delay_10us(5);P0 = 0x00;//消影LSC=0;LSB=0;LSA=1;P0 = gsmg_code[0]; delay_10us(5);P0 = 0x00;//消影 LSC=0;LSB=0;LSA=0;P0 = gsmg_code[8];delay_10us(5);P0 = 0x00;//消影 }else{LSC=1;LSB=1;LSA=1;P0 = gsmg_code[H/10];delay_10us(5);P0 = 0x00;//消影LSC=1;LSB=1;LSA=0;P0 = gsmg_code[H%10]; delay_10us(5);P0 = 0x00;//消影LSC=1;LSB=0;LSA=1;P0 = gsmg_code[16];delay_10us(5);P0 = 0x00;//消影LSC=1;LSB=0;LSA=0;P0 = gsmg_code[M/10]; delay_10us(5);P0 = 0x00;//消影 LSC=0;LSB=1;LSA=1;P0 = gsmg_code[M%10];delay_10us(5);P0 = 0x00;//消影LSC=0;LSB=1;LSA=0;P0 = gsmg_code[16];delay_10us(5);P0 = 0x00;//消影LSC=0;LSB=0;LSA=1;P0 = gsmg_code[S/10]; delay_10us(5);P0 = 0x00;//消影 LSC=0;LSB=0;LSA=0;P0 = gsmg_code[S%10];delay_10us(5);P0 = 0x00;//消影 }if(K1 == 0)//如果按键K1按下{while(!K1);//松手检测TR1 = 0;mode++;if(mode >3)mode = 1;}if(K4 == 0)//如果按键K4按下{while(!K4);//松手检测TR1 = 1; mode = 0;} if(K2 == 0)//如果按键K2按下{while(!K2);//松手检测switch (mode){case 1:H++;if(H > 23){H = 0; }break;case 2:M++;if(M > 59){M = 0; } break;case 3:S++;if(S > 59){S = 0; } break;}}if(K3 == 0)//如果按键K2按下{while(!K3);//松手检测switch (mode){case 1:H--;if(H < 0){H = 23; }break;case 2:M--;if(M < 0){M = 59; } break;case 3:S--;if(S < 0){S = 59; } break;}}}
}void Timer1_Rountine(void) interrupt 3 //1ms进一次中断
{TH1 = (65536-1000)/256; //TL1 = (65536-1000)%256; //重新赋初值才能保证下一次还是1msg_Count++;if(g_Count>=1000) // 1S 计时{g_Count = 0; //计数清零S++;if(++S1 == 5){S1 = 0;Display_falg = 1;}if(Display_falg == 1){if(++S2 == 2){S2 = 0;Display_falg = 0;}} if(S > 59)//1Min{S = 0;M++;if(M > 59)//1H{M = 0;H++;if(H > 23)//1H{H = 0; }}} }
}
四、实验效果
五、仿真实现

总结
相关文章:
51单片机应用开发(进阶)---定时器应用(电子时钟)
实现目标 1、巩固定时器的配置流程; 2、掌握按键、数码管与定时器配合使用; 3、功能1:(1)简单显示时间。显示格式:88-88-88(时-分-秒) 4、功能2:(1&#…...
JavaScript中的对象-栈内存和堆内存以及this指向的两种情况(后续会出进阶)
1.1 栈内存和堆内存 我们知道程序是需要加载到内存中来执行的,我们可以将内存划分为两个区域:栈内存和堆内存 原始类型占据的空间是在栈内存中分配的对象类型占据的空间是在堆内存中分配的 1.1.1 值类型和引用类型 原始类型的保存方式:在变量中保存的是…...
shell脚本使用curl上传FTP
背景:要求使用curl通过shell脚本实现上传文件到FTP的功能,同时对远程目录不存在的时候,主动创建目录并上传文件,shell脚本如下: #!/bin/bash# FTP服务器的地址 FTP_SERVER"ftp://1.1.1.1:2121" # FTP用户名…...
【漏洞分析】Fastjson最新版本RCE漏洞
01漏洞编号 CVE-2022-25845CNVD-2022-40233CNNVD-202206-1037二、Fastjson知多少 万恶之源AutoType Fastjson的主要功能是将Java Bean序列化为JSON字符串,这样得到的字符串就可以通过数据库等方式进行持久化了。 但是,Fastjson在序列化及反序列化的过…...
【项目开发 | 跨域认证】JSON Web Token(JWT)
未经许可,不得转载。 文章目录 JWT设计背景:跨域认证JWT 原理JWT 结构JWT 使用方式注意JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案,本文介绍它的原理、结构及用法。 JWT设计背景:跨域认证 互联网服务的用户认证流程是现代应用中的核心组成部分,通常的流程…...
杨中科 .Net Core 笔记 DI 依赖注入2
ServiceCollection services new ServiceCollection();//定义一个承放服务的集合 services.AddScoped<iGetRole, GetRole>();using (ServiceProvider serviceProvider services.BuildServiceProvider()) {var list serviceProvider.GetServices(typeof(iGetRole));//获…...
微信版产品目录如何制作?
微信作为我国最流行的社交媒体平台,拥有庞大的用户群体。许多企业都希望通过微信来推广自己的产品,提高品牌知名度。制作一份精美、实用的微信版产品目录,是企业微信营销的重要手段。微信版产品目录的制作方法,帮助您轻松入门。 …...
使用HTML、CSS和JavaScript创建动态圣诞树
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 ✨特色专栏:…...
机器学习-35-提取时间序列信号的特征
文章目录 1 特征提取方法1.1 特征提取过程1.2 两类特征提取方法2 基于数据驱动的方法2.1 领域特定特征提取2.2 基于频率的特征提取2.2.1 模拟信号2.2.2 傅里叶变换2.2.3 抽取最大幅值对应特征2.2.4 抽取峰值幅值对应特征2.3 基于统计的特征提取2.4 基于时间的特征提取3 参考附录…...
【软件测试】设计测试用例的万能公式
文章目录 概念设计测试用例的万能公式常规思考逆向思维发散性思维万能公式水杯测试弱网测试如何进行弱网测试 安装卸载测试 概念 什么是测试用例? 测试⽤例(Test Case)是为了实施测试⽽向被测试的系统提供的⼀组集合,这组集合包…...
【MySQL 保姆级教学】事务的自动提交和手动提交(重点)--上(13)
目录 1. 什么是事务?2. 事务的版本支持3. 事务提交的方式3.1 事务提交方式的分类3.2 演示的准备的工作3.2.1 创建表3.2.2 MySQL的服务端和客户端3.2.3 调低事务的隔离级别 4. 手动提交4.1 手动提交的命令说明4.2 示例一4.3 示例二4.4 示例三4.5 示例四 5. 自动提交5…...
CUDA 核心与科学计算 :NVIDIA 计算核心在计算服务器的价值
在现代科学计算领域,NVIDIA GPU 的计算能力是突破研究瓶颈的关键力量,而其中的 CUDA 核心与科学计算有着紧密的联系。 CUDA 核心于 2007 年开发,是一款基于单指令多线程 (SIMT) 模型的多功能通用核心。它在处理并行计算任务方面能力卓越&…...
架构师之路-学渣到学霸历程-58
Nginx的反向代理实验 今天分享的实验其实就是一个变形;变形uri看看nginx的配置有什么区别; 这个就更加绕,是比较不同的配置路径会有什么的区别? 来看看这个变形会得出什么的效果 1.首先配置后端服务器的资源 首页资源–>1…...
qq相册为啥越来越糊
电子存储衰退的原因 存储设备的失真通常和 存储介质的老化、数据退化、电荷泄漏 等问题有关。尤其是对闪存类存储(如SSD、U盘)来说,随着时间的推移,存储在其中的电荷可能会流失,导致数据损坏。而对于传统的机械硬盘&am…...
<有毒?!> 诺顿检测:这篇 CSDN 文章有病毒
NAS(qnap)中安装git服务(gogs),硬件为TS-453Bmini,固件版本:QTS 5.1.2.2533_qnap git服务器-CSDN博客 https://estar.blog.csdn.net/article/details/134138932 威胁名称:JS:Downloader-GEG [Trj]威胁类型:特洛伊木马…...
matlab实现主成分分析方法图像压缩和传输重建
原创 风一样的航哥 航哥小站 2024年11月12日 15:23 江苏 为了研究图像的渐进式传输技术,前文提到过小波变换,但是发现小波变换非常适合传输缩略图,实现渐进式传输每次传输的数据量不一样,这是因为每次变换之后低频成分大约是上一…...
18.UE5怪物视野、AI感知、攻击范围、散弹技能
2-20 怪物视野、AI感知、攻击范围、散弹技能_哔哩哔哩_bilibili 目录 1.AI感知组件 2.AI感知更新的函数 3.攻击范围 4.散弹技能 4.1创建发射物i 4.2创建远程攻击方式 4.3散弹自定义事件的实现 4.4动画通知实现攻击 1.AI感知组件 为怪物蓝图添加AI感知组件,…...
【 ElementUI 组件Steps 步骤条使用新手详细教程】
本文介绍如何使用 ElementUI 组件库中的步骤条组件完成分步表单设计。 效果图: 基础用法 简单的步骤条。 设置 active 属性,接受一个 Number,表明步骤的 index,从 0 开始。 需要定宽的步骤条时,设置 space 属性即…...
MQTT从入门到精通之 MQTT 客户端编程
MQTT 客户端编程 1 在VUE中使用MQTT 具体步骤如下所示: 1、初始化vue项目 // 创建一个使用vite构建的前端项目 npm create vitelatest// 进入到项目中,执行如下命令安装项目依赖 npm install 2、安装element plus // 安装element plus npm install …...
数据结构-集合
一.集合的表示 一个重要的操作是查某个元素属于哪个集合,另一个操作是合并操作 从这个树的节点去找树根也就是从下往上找,要把树并起来只需把两个根并在一起就可以了 不存在已知一个节点去找孩子节点,根重要的是已知一个节点找它的父亲节点,与之前的二…...
万物识别在智能体(Skills Agent)中的集成应用
万物识别在智能体(Skills Agent)中的集成应用 想象一下,你正在开发一个智能客服机器人,用户发来一张照片,里面是自家厨房水槽下漏水的一堆零件。用户问:“这是什么东西坏了?我该买什么配件?” 传统的文本对…...
EasyAnimateV5-7b-zh-InP一键部署教程:基于Linux系统的快速安装指南
EasyAnimateV5-7b-zh-InP一键部署教程:基于Linux系统的快速安装指南 1. 引言 想快速在Linux系统上部署一个强大的视频生成模型吗?EasyAnimateV5-7b-zh-InP是一个22GB的图生视频模型,支持多分辨率视频生成,还能用中英文双语进行预…...
【论文】信息系统项目管理师范围管理要点
本资料摘自《科科过论文集分析》,底部附PDF图片版记忆。项目管理中范围管理的六大核心环节,旨在为专业写作提供具体的实践指导与案例素材。文档强调在描述规划、需求收集和范围定义时,应避免枯燥的理论堆砌,转而通过真实的业务场景…...
Qwen3-TTS开源大模型效果展示:俄文/葡萄牙文/意大利文等小语种高自然度语音生成
Qwen3-TTS开源大模型效果展示:俄文/葡萄牙文/意大利文等小语种高自然度语音生成 你听过AI用俄语讲普希金的诗吗?或者用意大利语念一段歌剧台词?过去,想让AI生成地道的小语种语音,要么音色机械,要么口音奇怪…...
数字孪生通信层开发:C#实现OPC UA到Unity3D的实时数据映射(2026年工业级实战指南)
引言:通信层不是“锦上添花”,而是“数字孪生的血脉” 在2026年的工业数字孪生战场上,OPC UA到Unity3D的数据映射延迟是决定孪生体“活”与“死”的关键。IDC 2026年工业物联网报告显示:76%的数字孪生项目因通信层延迟>100ms失…...
AI读脸术多国面孔适配:跨种族识别优化部署实战
AI读脸术多国面孔适配:跨种族识别优化部署实战 1. 引言 你有没有遇到过这样的情况:一个在亚洲人脸识别上表现不错的AI模型,拿到一张欧洲人或非洲人的照片时,识别结果就开始"犯迷糊"了?性别判断出错&#x…...
intv_ai_mk11部署教程:supervisorctl status/restart/log三命令掌握服务运维全链路
intv_ai_mk11部署教程:supervisorctl status/restart/log三命令掌握服务运维全链路 1. 服务概述与核心功能 intv_ai_mk11是一款基于Llama架构的AI对话机器人(7B参数),部署在GPU服务器上,能够提供智能对话服务。这个A…...
Umi-OCR技术解密:离线文字识别的3大创新与全行业实践指南
Umi-OCR技术解密:离线文字识别的3大创新与全行业实践指南 【免费下载链接】Umi-OCR Umi-OCR: 这是一个免费、开源、可批量处理的离线OCR软件,适用于Windows系统,支持截图OCR、批量OCR、二维码识别等功能。 项目地址: https://gitcode.com/G…...
LANDrop局域网文件传输:3分钟快速上手跨平台文件共享神器
LANDrop局域网文件传输:3分钟快速上手跨平台文件共享神器 【免费下载链接】LANDrop Drop any files to any devices on your LAN. 项目地址: https://gitcode.com/gh_mirrors/la/LANDrop 还在为不同设备间传输文件而烦恼吗?🤔 LANDrop…...
Octomap在二维导航地图转换中的常见问题与优化策略
1. Octomap二维地图转换的核心挑战 第一次接触Octomap进行三维到二维地图转换时,我被它强大的空间建模能力吸引,但实际操作中踩了不少坑。最典型的就是发现生成的二维地图要么全是噪点,要么和实际环境对不上。后来才明白,这背后涉…...
