南阳住房和城乡建设厅网站/广告软文范例

南阳住房和城乡建设厅网站,广告软文范例,wordpress添加外链图片,北京做网站定制价格什么?你把最近几届省赛真题做完已经无题可做了,那不妨来看看老古董第八届省赛的题目吧! 附件:第八届蓝桥杯单片机省赛 一、数码管 1.页面流转 以上的页面流转功能可以用下图总结: #mermaid-svg-38fdQpdydbMy5CyP {fo…

什么?你把最近几届省赛真题做完已经无题可做了,那不妨来看看老古董第八届省赛的题目吧!

附件:第八届蓝桥杯单片机省赛
在这里插入图片描述

一、数码管

1.页面流转

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
以上的页面流转功能可以用下图总结:

长按S4
松开S4
按下S7
按下S6
时间显示页面
温度显示页面
时钟设置
闹钟设置

这边给出一种实现方法:

  • 定义unsigned char型变量SetMode来控制三个主要页面(SetMode=0:时间显示页面、SetMode=1:时钟设置页面、SetMode=2:闹钟设置页面)
  • 然后定义bit 型变量SegMode在时间显示页面(SetMode=0)单独控制温度显示页面(SegMode=0:时间显示页面、SegMode=1:温度显示页面)

2.变量初定义

关于时钟设置和闹钟设置是在设置期间数据就生效还是退出到时间显示页面才生效这个问题,题目并没有明确指出,本篇文章默认时钟设置和闹钟设置在退出到时间显示页面才生效。

typedef unsigned char u8;
typedef unsigned int u16;
/* 页面参数 */	
idata u8 SetMode; //0-时间页面 1-时间设置 2-闹钟设置
idata bit SegMode;//0-时间显示 1-温度显示
/* 时钟、闹钟参数 */
idata u8 Index;//0-无 1-时 2-分 3-秒
pdata u8 Rtc[3] = {0x23,0x59,0x50};//时钟显示数据
pdata u8 RtcSet[3];//时钟设置时修改的数据
pdata u8 Alarm[3] = {0x00,0x00,0x00};//闹钟存放时间
pdata u8 AlarmSet[3];//闹钟设置时修改的数据
/* 温度 */
idata u8 tem;	
/* 老朋友  */
idata u8 SegPos;
pdata u8 SegBuf[8] = {10,10,10,10,10,10,10,10};
pdata u8 SegPoint[8] = {0,0,0,0,0,0,0,0};
pdata u8 ucLed[8] = {0,0,0,0,0,0,0,0};

3.时间显示页面

在这里插入图片描述

  • ds1302.h
#ifndef __ds1302_H__
#define __ds1302_H__void SetRtc(unsigned char *Rtc);
void GetRtc(unsigned char *Rtc);#endif
  • ds1302.c
#include <STC15F2K60S2.H>
#include <intrins.h>sbit SCK = P1^7;
sbit SDA = P2^3;
sbit RST = P1^3;void Write_Ds1302(unsigned  char temp) 
{unsigned char i;for (i=0;i<8;i++)     	{ SCK = 0;SDA = temp&0x01;temp>>=1; SCK=1;}
}   //
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )     
{RST=0;	_nop_();SCK=0;	_nop_();RST=1; 	_nop_();  Write_Ds1302(address);	Write_Ds1302(dat);		RST=0; 
}//
unsigned char Read_Ds1302_Byte ( unsigned char address )
{unsigned char i,temp=0x00;RST=0;	_nop_();SCK=0;	_nop_();RST=1;	_nop_();Write_Ds1302(address);for (i=0;i<8;i++) 	{		SCK=0;temp>>=1;	if(SDA)temp|=0x80;	SCK=1;} RST=0;	_nop_();SCK=0;	_nop_();SCK=1;	_nop_();SDA=0;	_nop_();SDA=1;	_nop_();return (temp);			
}code unsigned char DS1302[4] = {0x84,0x82,0x80,0x8E};void SetRtc(unsigned char *Rtc)
{unsigned char i;Write_Ds1302_Byte(DS1302[3],0x00);for(i = 0; i < 3; i++)Write_Ds1302_Byte(DS1302[i],Rtc[i]);Write_Ds1302_Byte(DS1302[3],0x80);
}
void GetRtc(unsigned char *Rtc)
{unsigned char i;for(i = 0; i < 3; i++)Rtc[i] = Read_Ds1302_Byte(DS1302[i]+1);
}
  • main.c
void SegProc()
{unsigned char i;GetRtc(Rtc);//读取当前时间switch(SetMode){case 0:if(!SegMode){SegBuf[2] = SegBuf[5] = 11;for(i = 0; i < 3; i++){				SegBuf[3*i] = Rtc[i] / 16;SegBuf[3*i+1] = Rtc[i] % 16;}}break;}
}void main()
{SystemInit();Timer0_Init();SetRtc(Rtc);//上电时设置时间while(1){//...}
}

4.温度显示页面

在这里插入图片描述

  • ds18b20.h
#ifndef __ds18b20_H__
#define __ds18b20_H__float TemRead();#endif
  • ds18b20.c
#include <STC15F2K60S2.H>sbit DQ = P1^4;void Delay_OneWire(unsigned int t)  
{unsigned char i;while(t--){for(i=0;i<12;i++);}
}//
void Write_DS18B20(unsigned char dat)
{unsigned char i;for(i=0;i<8;i++){DQ = 0;DQ = dat&0x01;Delay_OneWire(5);DQ = 1;dat >>= 1;}Delay_OneWire(5);
}//
unsigned char Read_DS18B20(void)
{unsigned char i;unsigned char dat;for(i=0;i<8;i++){DQ = 0;dat >>= 1;DQ = 1;if(DQ){dat |= 0x80;}	    Delay_OneWire(5);}return dat;
}//
bit init_ds18b20(void)
{bit initflag = 0;DQ = 1;Delay_OneWire(12);DQ = 0;Delay_OneWire(80);DQ = 1;Delay_OneWire(10); initflag = DQ;     Delay_OneWire(5);return initflag;
}float TemRead()
{unsigned char tem_low, tem_hig;init_ds18b20();Write_DS18B20(0xcc);Write_DS18B20(0x44);init_ds18b20();Write_DS18B20(0xcc);Write_DS18B20(0xbe);tem_low = Read_DS18B20();tem_hig = Read_DS18B20();return ((tem_hig << 8) | tem_low) / 16.0;
}
  • main.c
void SegProc()
{tem = TemRead();switch(SetMode){case 0:if(!SegMode){//...}else//温度显示页面{SegBuf[0] = 10;SegBuf[1] = 10;SegBuf[2] = 10;SegBuf[3] = 10;SegBuf[4] = 10;SegBuf[5] = tem / 10;SegBuf[6] = tem % 10;SegBuf[7] = 12;//C}break;}
}

5.时钟设置页面

在这里插入图片描述
只显示时钟设置的数据:

for(i = 0; i < 3; i++)
{				SegBuf[3*i] = RtcSet[i] / 16;SegBuf[3*i+1] = RtcSet[i] % 16;
}

根据按键S7去选择待调整的时、分、秒,当前选择的显示单元以 1 秒为间隔亮灭。
可以通过Index来选择时、分、秒,选中后,定义计时变量idata u16 Time_1s;来计时1s让idata bit SegFlash;取反达到数码管闪烁的效果(和指示灯闪烁一样)。

idata u16 Time_1s;
idata bit SegFlash;void SegProc()
{//...switch(SetMode){case 0://...break;case 1://时钟设置页面SegBuf[2] = SegBuf[5] = 11;for(i = 0; i < 3; i++){				SegBuf[3*i] = (Index == i+1 && SegFlash) ? 10 : RtcSet[i] / 16;SegBuf[3*i+1] = (Index == i+1 && SegFlash) ? 10 : RtcSet[i] % 16;}break;}
}void Timer0_Isr(void) interrupt 1
{if(++SegPos == 8) SegPos = 0;SegDisp(SegPos,SegBuf[SegPos],SegPoint[SegPos]);if(++Time_1s == 1000){Time_1s = 0;SegFlash = !SegFlash;}
}

6.闹钟设置页面

在这里插入图片描述
闹钟设置页面不用考虑数码管闪烁

void SegProc()
{u8 i;switch(SetMode){case 2:SegBuf[2] = SegBuf[5] = 11;for(i = 0; i < 3; i++){				SegBuf[3*i] = AlarmSet[i] / 16;SegBuf[3*i+1] = AlarmSet[i] % 16;}break;}
}

7.数码管完整代码

typedef unsigned char u8;
typedef unsigned int u16;
/* 页面参数 */	
idata u8 SetMode; //0-时间页面 1-时间设置 2-闹钟设置
idata bit SegMode;//0-时间显示 1-温度显示
/* 时钟、闹钟参数 */
idata u8 Index;//0-无 1-时 2-分 3-秒
pdata u8 Rtc[3] = {0x23,0x59,0x50};//时钟显示数据
pdata u8 RtcSet[3];//时钟设置时修改的数据
pdata u8 Alarm[3] = {0x00,0x00,0x00};//闹钟存放时间
pdata u8 AlarmSet[3];//闹钟设置时修改的数据
/* 温度 */
idata u8 tem;	void SegProc()
{unsigned char i;tem = TemRead();GetRtc(Rtc);switch(SetMode){case 0:if(!SegMode){SegBuf[2] = SegBuf[5] = 11;for(i = 0; i < 3; i++){				SegBuf[3*i] = Rtc[i] / 16;SegBuf[3*i+1] = Rtc[i] % 16;}}else{SegBuf[0] = 10;SegBuf[1] = 10;SegBuf[2] = 10;SegBuf[3] = 10;SegBuf[4] = 10;SegBuf[5] = tem / 10;SegBuf[6] = tem % 10;SegBuf[7] = 12;}break;case 1:SegBuf[2] = SegBuf[5] = 11;for(i = 0; i < 3; i++){				SegBuf[3*i] = (Index == i+1 && SegFlash) ? 10 : RtcSet[i] / 16;SegBuf[3*i+1] = (Index == i+1 && SegFlash) ? 10 : RtcSet[i] % 16;}break;case 2:SegBuf[2] 	= SegBuf[5] = 11;for(i = 0; i < 3; i++){				SegBuf[3*i] = AlarmSet[i] / 16;SegBuf[3*i+1] = AlarmSet[i] % 16;}break;}
}void Timer0_Init(void)		//1毫秒@12.000MHz
{AUXR &= 0x7F;			//定时器时钟12T模式TMOD &= 0xF0;			//设置定时器模式TL0 = 0x18;			  //设置定时初始值TH0 = 0xFC;				//设置定时初始值TF0 = 0;				  //清除TF0标志TR0 = 1;				  //定时器0开始计时ET0 = 1;				  //使能定时器0中断EA = 1;
}void Timer0_Isr(void) interrupt 1
{if(++SegPos == 8) SegPos = 0;SegDisp(SegPos,SegBuf[SegPos],SegPoint[SegPos]);if(++Time_1s == 1000){Time_1s = 0;SegFlash = !SegFlash;}
}

二、按键

1.S4、S5

在这里插入图片描述
在设置时钟和闹钟的时候,由于要考虑参数的边界性,所以在加和减参数的时候要考虑最大值和最小值,防止数据越界,小时的范围是00 ~ 23,分钟的范围是00 ~ 59,秒钟的范围是00 ~ 59,这边需要注意的是,unsigned char的数据范围是0~255,假设参数减到0,再按下S4后,下一次的值是255。

void KeyProc()
{KeyVal = KeyDisp();KeyDown = KeyVal & ~KeyOld;KeyUp = ~KeyVal & KeyOld;KeyOld = KeyVal;switch(KeyDown){case 5:if(SetMode == 1)//时间设置{RtcSet[Index-1]++;if(RtcSet[0] == 24)RtcSet[0] = 23;if(RtcSet[1] == 60)RtcSet[1] = 59;if(RtcSet[2] == 60)RtcSet[2] = 59;}else if(SetMode == 2)//闹钟设置{AlarmSet[Index-1]++;if(AlarmSet[0] == 24)AlarmSet[0] = 23;if(AlarmSet[1] == 60)AlarmSet[1] = 59;if(AlarmSet[2] == 60)AlarmSet[2] = 59;}break;case 4:if(SetMode == 1){RtcSet[Index-1]--;if(RtcSet[Index-1] == 255)RtcSet[Index-1] = 0;}else if(SetMode == 2){AlarmSet[Index-1]--;if(AlarmSet[Index-1] == 255)AlarmSet[Index-1] = 0;}break;}
}

1.S6、S7

对于S6、S7。只需要在进入小时的设置时将原先的时钟/闹钟数据传给AlarmSet/AlarmSet,完成设置返回时间显示页面时再将AlarmSet/AlarmSet的值传回时钟/闹钟。

switch(KeyDown){case 6:Index++;if(Index == 1){SetMode = 2;memcpy(AlarmSet,Alarm,3);}if(Index == 4){SetMode = 0;memcpy(Alarm,AlarmSet,3);Index = 0;}break;case 7:Index++;if(Index == 1){SetMode = 1;memcpy(RtcSet,Rtc,3);}if(Index == 4){SetMode = 0;memcpy(Rtc,RtcSet,3);Index = 0;SetRtc(Rtc);}break;

3.完整代码

void KeyProc()
{KeyVal = KeyDisp();KeyDown = KeyVal & ~KeyOld;KeyUp = ~KeyVal & KeyOld;KeyOld = KeyVal;//长按S4进入温度显示页面,松手返回时间显示页面if(!SetMode){if(KeyOld == 4)SegMode = 1;if(KeyUp == 4)SegMode = 0;}switch(KeyDown){case 6:Index++;if(Index == 1){SetMode = 2;memcpy(AlarmSet,Alarm,3);}if(Index == 4){SetMode = 0;memcpy(Alarm,AlarmSet,3);Index = 0;}break;case 7:Index++;if(Index == 1){SetMode = 1;memcpy(RtcSet,Rtc,3);}if(Index == 4){SetMode = 0;memcpy(Rtc,RtcSet,3);Index = 0;SetRtc(Rtc);}break;case 5:if(SetMode == 1){RtcSet[Index-1]++;if(RtcSet[0] == 24)RtcSet[0] = 23;if(RtcSet[1] == 60)RtcSet[1] = 59;if(RtcSet[2] == 60)RtcSet[2] = 59;}else if(SetMode == 2){AlarmSet[Index-1]++;if(AlarmSet[0] == 24)AlarmSet[0] = 23;if(AlarmSet[1] == 60)AlarmSet[1] = 59;if(AlarmSet[2] == 60)AlarmSet[2] = 59;}break;case 4:if(SetMode == 1){RtcSet[Index-1]--;if(RtcSet[Index-1] == 255)RtcSet[Index-1] = 0;}else if(SetMode == 2){AlarmSet[Index-1]--;if(AlarmSet[Index-1] == 255)AlarmSet[Index-1] = 0;}break;}
}

三、指示灯

在这里插入图片描述
先实现闹钟响的时候L1以200ms为间隔闪烁,持续5s。

idata u8 Time_200ms;//闪烁间隔
idata u16 Time_5s;//定时5s
idata bit AlarmFlag;//闹钟响
idata bit LedFlash;//指示灯闪烁void LedProc()
{//闹钟响了if(Alarm[0] == Rtc[0] && Alarm[1] == Rtc[1] && Alarm[2] == Rtc[2])AlarmFlag = 1;ucLed[0] = LedFlash;LedDisp(ucLed);
}void Timer0_Isr(void) interrupt 1
{systick++;if(++SegPos == 8) SegPos = 0;SegDisp(SegPos,SegBuf[SegPos],SegPoint[SegPos]);if(AlarmFlag)//闹钟响{Time_5s++;//开始计时5sif(Time_5s == 5000)//计时到5s关闭闹钟{Time_5s = 0;AlarmFlag = 0;//关闭闹钟}else//还未计时5秒,L1闪烁{if(++Time_200ms == 200){Time_200ms = 0;LedFlash = !LedFlash;}}}elseLedFlash = 0;
}

接下来写在任意按键按下关闭闹钟

void KeyProc()
{//...if(AlarmFlag){if(KeyDown)//按键值不为0AlarmFlag = 0;//关闭闹钟//防止这次的按键干扰到其他功能按键,关闭闹钟直接退出不执行下面语句return;}
}

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

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

相关文章

win10电脑鼠标速度突然变的很慢?

电脑鼠标突然变很慢&#xff0c;杀毒检测后没问题&#xff0c;鼠标设置也没变&#xff0c;最后发现可能是误触鼠标的“DPI”调节键。 DPI调节键在鼠标滚轮下方&#xff0c;再次点击即可恢复正常鼠标速度。 如果有和-的按键&#xff0c;速度变快&#xff0c;-速度变慢。 图源&…

【解决哈希冲突】

哈希冲突 如果两个不同的 key 通过哈希函数得到了相同的索引&#xff0c;这种情况就叫做「哈希冲突」。 哈希冲突不可能避免&#xff0c;只能在算法层面妥善处理出现哈希冲突的情况。 哈希冲突是一定会出现的&#xff0c;因为这个 hash 函数相当于是把一个无穷大的空间映射到…

文件操作详解(万字长文)

C语言文件操作 一、为什么使用文件&#xff1f;二、文件分类三、文件的打开和关闭四、文件的顺序读写4.1fputc4.2fgetc4.3fputs4.4fgets4.5 fprintf4.6 fscanf4.7 fwrite4.8 fread 五、文件的随机读写5.1 fseek5.2 ftell和rewind六、文件读取结束的判定七、文件缓冲区 一、为什…

基于 JDBC 的后端与 MySQL 数据库交互 javaweb

一、了解JDBC 二、添加MySQL的JDBC驱动包 三、使用JDBC连接数据库应用&#x1f517; 3.1创建一个包 3.2 查找实例 3.3 修改添加删除实例 四、封装 &#x1f4e6; DBConnection.java MysqlUtil.java 测试使用一下 测试1 测试2 在后端开发中&#xff0c;与数据库进行交…

贪心算法--

1.柠檬水找零 link:860. 柠檬水找零 - 力扣&#xff08;LeetCode&#xff09; code class Solution { public:bool lemonadeChange(vector<int>& bills) {// 贪心算法&#xff0c; 优先花出大面额bill&#xff0c; 尽可能保护小面额billint five 0, ten 0;// 不…

基于YOLO11深度学习的电瓶车进电梯检测与语音提示系统【python源码+Pyqt5界面+数据集+训练代码】

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…

github生成badges的方法

在Github页面上生成类似下面这样的badge的方法 你可以通过以下步骤在GitHub个人主页的README中创建类似的技术栈徽章&#xff1a; 一、使用 Shields.io 生成徽章 Shields.io 是一个开源徽章生成工具&#xff0c;支持自定义文本、颜色、图标等参数。 1. 基础模板 https://…

vue3 二次封装uni-ui中的组件,并且组件中有 v-model 的解决方法

在使用uniappvue3开发中&#xff0c; 使用了uni-ui的组件&#xff0c;但是我们也需要自定义组件&#xff0c;比如我要自定一个picker 的组件&#xff0c; 是在 uni-data-picker 组件的基础上进行封装的 父组件中的代码 <classesselect :selectclass"selectclass"…

爬虫案例七Python协程爬取视频

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、Python协程爬取视频 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 爬虫案例七协程爬取视频 提示&#xff1a;以下是本篇文章正文…

Python 爬虫实战案例 - 获取拉勾网招聘职位信息

引言 拉勾网&#xff0c;作为互联网招聘领域的佼佼者&#xff0c;汇聚了海量且多样的职位招聘信息。这些信息涵盖了从新兴科技领域到传统行业转型所需的各类岗位&#xff0c;无论是初出茅庐的应届生&#xff0c;还是经验丰富的职场老手&#xff0c;都能在其中探寻到机遇。 对…

LM Studio 替换源的方式解决huggingface.co无法访问的问题

安装软件完成之后&#xff0c;不要打开&#xff0c;打开了就直接关闭 在安装目录下&#xff0c;比如我安装在E:\Program Files\LM Studio 下面三个文件中的huggingface.co全部替换为hf-mirror.com然后再打开即可。 E:\Program Files\LM Studio\resources\app\.webpack\rende…

【模拟CMOS集成电路设计】带隙基准(Bandgap)设计与仿真(基于运放的电流模BGR)

【模拟CMOS集成电路设计】带隙基准&#xff08;Bandgap&#xff09;设计与仿真 前言工程文件&部分参数计算过程&#xff0c;私聊~ 一、 设计指标指标分析&#xff1a; 二、 电路分析三、 仿真3.1仿真电路图3.2仿真结果(1)运放增益(2)基准温度系数仿真(3)瞬态启动仿真(4)静态…

微服务拆分-远程调用

我们在查询购物车列表的时候&#xff0c;它有一个需求&#xff0c;就是不仅仅要查出购物车当中的这些商品信息&#xff0c;同时还要去查到购物车当中这些商品的最新的价格和状态信息&#xff0c;跟购物车当中的快照进行一个对比&#xff0c;从而去提醒用户。 现在我们已经做了服…

P2P中NAT穿越方案(UDP/TCP)(转)

转自&#xff1a;P2P中NAT穿越方案&#xff08;UDP/TCP&#xff09;_udp反向链接-CSDN博客 同&#xff1a;P2P中NAT穿越方案&#xff08;UDP/TCP&#xff09; - 知乎 (zhihu.com) 本文介绍了传统基于udp的打洞方式&#xff0c;更进一步阐述了tcp打洞的原理&#xff0c;是对于…

算法 之 树形dp 树的中心、重心

文章目录 重心实践题目小红的陡峭值 在树的算法中&#xff0c;求解树的中心和重心是一类十分重要的算法 求解树的重心 树的重心的定义&#xff1a;重心是树中的一个节点&#xff0c;如果将这个点删除后&#xff0c;剩余各个连通块中点数的最大值最小&#xff0c;那么这个节点…

游戏引擎学习第146天

音高变化使得对齐读取变得不可能&#xff0c;我们可以支持循环声音了。 我们今天的目标是完成之前一段时间所做的音频代码。这个项目并不依赖任何引擎或库&#xff0c;而是一个教育项目&#xff0c;目的是展示从头到尾运行一个游戏所需要的全部代码。无论你对什么方面感兴趣&a…

深入理解MySQL主从原理

导读 高鹏&#xff08;网名八怪&#xff09;&#xff0c;《深入理解MySQL主从原理》系列文的作者。 本系列通过GTID、Event、主库、从库、案例分析&#xff0c;五大块来详细讲解主从原理。 这篇文章重在学习笔记整理&#xff01; 在学习《深入理解MySQL主从原理》一书时&…

Phi-4-multimodal:图、文、音频统一的多模态大模型架构、训练方法、数据细节

Phi-4-Multimodal 是一种参数高效的多模态模型&#xff0c;通过 LoRA 适配器和模式特定路由器实现文本、视觉和语音/音频的无缝集成。训练过程包括多阶段优化&#xff0c;确保在不同模式和任务上的性能&#xff0c;数据来源多样&#xff0c;覆盖高质量网络和合成数据。它的设计…

Unity--Cubism Live2D模型使用

了解LIVE2D在unity的使用--前提记录 了解各个组件的作用 Live2D Manuals & Tutorials 这些文件都是重要的控制动画参数的 Cubism Editor是编辑Live2D的工具&#xff0c;而导出的数据的类型&#xff0c;需要满足以上的条件 SDK中包含的Cubism的Importer会自动生成一个Pref…

Linux | Vim 鼠标不能右键粘贴、跨系统复制粘贴

注&#xff1a;本文为 “ Vim 中鼠标右键粘贴、跨系统复制粘贴问题解决方案” 相关文章合辑。 未整理去重。 Linux 入门&#xff1a;vim 鼠标不能右键粘贴、跨系统复制粘贴 foryouslgme 发布时间 2016 - 09 - 28 10:24:16 Vim基础 命令模式(command-mode)插入模式(insert-m…