07现在完成时

本文深入解析英语现在完成时的用法,对比一般过去时,讲解完成时的结构、时间段应用及动词转换,辅以例句加深理解。

结构: have done或者has done
现在完成时是“过去的动作或状态持续到现在并且已经完成”。要和一般过去时区分

一、现在完成时与一般过去时的区分

1. 特点对比

时态
一般过去时(一般)没特点纯叙述仅表示之前发生的动作
现在完成时(完成)强调完成对之后的事情有影响过去的动作或状态持续到现在并且已经完成
  • 注意:
    现在完成时句子中一般会有 ‘已经’ ‘还没’ ‘过’
    Already、yet、ever、never、just、before、once、twice、three times
  • 对比:
    ① 我吃了一个汉堡
    我已经吃了一个汉堡了(你不用再给我买了)
    ② 我看了一部电影
    我已经看过这部电影了(咱要不换部别的看)
    ③ 我没给他打了个电话
    我还没给他打电话(等会咱俩一起打吧)

2. 时间对比

时态
一般过去时(过去)表示过去的一个时间段,与现在无关一般接过去的时间
现在完成时(现在)从过去开始一直延续到现在的时间段
  • 注意:
    ① 首先判断是时间段还是时间点
    ② 如果是时间点,判断其特点是仅表示之前发生的动作,还是强调已经完成
    ③ 如果是时间段,判断这个时间段是动词完全延续这个时间段到现在

3. 例句:句中时间段时间点判断

  • 他昨天就已经走了 【时间点】
  • 我已经在这里住一辈子了 【时间段】
  • 我2007年告诉的他 【时间点】
  • 我已经告诉他两天了 【时间段】
  • 他上个星期走了 【时间点】
  • 他走了一个星期了 【时间段】
  • 他那个夏天这里住过 【时间点】他在这里住了一个夏天 【时间段】
  • 他之前在这里住过仨月 【时间段】

二、结构

have + done (过去分词) 或者 has + done (过去分词)

  • 训练
    一般疑问句 he和you 造句,特殊疑问句when-he、when-you
    在这里插入图片描述

三、时间段

1. 对于一个时间段的提问和回答要用how long和for或since

例句:How long have you known him? I have known him for 3 years.

2. 疑问句用how long 提问,陈述句中用for回答

-How long have you known him? 或 How long has it been since you knew him?
-I have known him for 3 years.

3. 区别现在完成时和一般过去式

过去到现在的时间段用现在完成时,过去的时间段用一般过去式
在这里插入图片描述
你之前在这里住过多久了(与现在没有关系)
-how long did you live here?
-I lived here for two years before.

  • 区分(红色用一般过去式表示)
    在这里插入图片描述

四、现在完成时+时间段中动词的运用

1.完成时+时间段 动词变延续性
用完成时后面加上一段时间动词要用可延续动词,如非续动词要变成可延续的谓语动词或系动词+n.a.adv.介短

  • 例句 come是非延续性动词,要变成be here
    How long have you been here? I have been here for 30mins.
    如下图所示:
    在这里插入图片描述
    2. 非延续性动词的转化
    在这里插入图片描述
    3. 穿衣服的区别
    你穿这件衣服多久了?
    • 可以翻译成,衣服在你身上,主语是衣服,用on.
      How long has this piece of clothing been on you?

    • 也可以翻译成,你在衣服里面,主语是你,用in.
      How long have you been in this piece of clothing?

    • 也可以用wear(穿,可延续性动词,过去式和过去分词分别是wore和worn)
      how long have you worn this piece of clothing?

五、无法变成延续性的表达方式

用since从句,从句的时态是一般过去式
例句

  • 你找到钥匙多久了 How long has it been since you found the key?
  • 你吃了多久了 How long has it been since you ate it?
  • 你告诉他多久了 How long has it been since you told him?
  • 你开除他多久了 How long has it been since you fired him?

额外知识点

  • 现在完成时可以加时间点或者时间段,只有在表示时间段时,动词需要变延续。
  • when提问时间点,一般都用一般过去时;how long 提问时间段
  • have been to 表示去过某地,现在已经不在那了
    have gone to 表示已经去了某地,现在在路上或者已经到了
    have been in 表示一直在这,从未离开

六、练习

在这里插入图片描述

你是基于单片机的远程控制系统设计实验的AI助教,现在你要协助完成该实验的目标编程任务。 --- ### **题目重述** 根据《实验六 基于单片机的远程控制系统设计》文档内容,需完成以下编程目标: 1. 实现HMI站(上位机)与本地电机控制站(下位机)之间的**RS-485串口通信**,使用**自定义报文协议**进行数据交换。 2. 报文格式包含:同步字符(`SYN=0x66666666`)、数据长度(`LEN`)、功能码(`FUC`)、数据域(`DATA`)、异或校验(`XOR`)、累加校验(`ADD`)。 3. HMI站通过按键发送控制命令(正转、反转、停止),并通过LCD1602显示当前电机状态(运行模式、运行状态)。 4. 本地控制站接收命令,控制模拟电机行为(可用LED或LCD表示状态),并每0.5秒向上位机发送一次状态数据。 5. 若通信异常(超未收到响应),本地站应自动停机。 6. 使用**外部中断+查询法**识别多个自复位按钮的输入。 7. 在Keil中编写C语言程序,在Proteus中实现双机联合仿真。 --- ### **给出答案(答案为带注释的代码块)** #### **HMI站(上位机)代码(Keil C51)** ```c #include <reg52.h> #define uchar unsigned char #define uint unsigned int // LCD1602引脚定义 sbit RS = P2^0; sbit RW = P2^1; sbit E = P2^2; sbit BT_INT = P3^3; // 外部中断1 输入 uchar btn_flag = 0; // 按键中断标志 uchar cmd = 0; // 当前命令:1=正转, 2=反转, 0=停止 // LCD数据口接P0 #define LCD_Data P0 // 函数声明 void DelayMs(uint ms); void LCD_Init(); void LCD_WriteCmd(uchar cmd); void LCD_WriteData(uchar dat); void LCD_DisplayStr(uchar line, uchar col, uchar *str); void UART_Init(); void Send_Packet(uchar fuc, uchar data); bit Receive_Packet(); void Parse_Status(uchar stat); // 全局变量 uchar status_byte; bit comm_ok = 1; // 主函数 void main() { UART_Init(); LCD_Init(); EX1 = 1; // 使能外部中断1 IT1 = 1; // 下降沿触发 EA = 1; // 开总中断 LCD_DisplayStr(0, 0, "Mode: Remote"); LCD_DisplayStr(1, 0, "Status: Standby"); while (1) { if (btn_flag) { // 按键被按下 uchar key = P1 & 0x07; // 查询P1.0~P1.2 DelayMs(20); // 消抖 if (key == 0x01) cmd = 1; // 正转 else if (key == 0x02) cmd = 2; // 反转 else if (key == 0x04) cmd = 0; // 停止 Send_Packet(1, cmd); btn_flag = 0; } if (Receive_Packet()) { Parse_Status(status_byte); comm_ok = 1; } else { if (!comm_ok) { LCD_DisplayStr(1, 0, "Status: Comm Err"); } } DelayMs(500); } } // 外部中断服务函数:检测按键 void ext_int1() interrupt 2 { btn_flag = 1; } // 发送报文函数 void Send_Packet(uchar fuc, uchar data) { uchar len = 2; // FUC + DATA uchar xor_chk = len ^ fuc ^ data; uchar add_chk = len + fuc + data + xor_chk; SBUF = 0x66; while(!TI); TI=0; SBUF = 0x66; while(!TI); TI=0; SBUF = 0x66; while(!TI); TI=0; SBUF = 0x66; while(!TI); TI=0; // SYN同步头 SBUF = len; while(!TI); TI=0; SBUF = fuc; while(!TI); TI=0; SBUF = data; while(!TI); TI=0; SBUF = xor_chk; while(!TI); TI=0; SBUF = add_chk; while(!TI); TI=0; } // 接收状态包(简化版轮询) bit Receive_Packet() { uchar buf[8], i; uchar syn_cnt = 0; for (i = 0; i < 8; i++) buf[i] = 0; while (RI == 0); buf[0] = SBUF; RI = 0; if (buf[0] != 0x66) return 0; for (i = 1; i < 8; i++) { while (RI == 0); buf[i] = SBUF; RI = 0; } // 检查同步头 if (!(buf[0]==0x66 && buf[1]==0x66 && buf[2]==0x66 && buf[3]==0x66)) return 0; uchar len = buf[4]; if (len != 1) return 0; // 状态数据长度为1 uchar fuc = buf[5]; if (fuc != 1) return 0; // 上行应为状态数据 status_byte = buf[6]; // 校验 uchar xor_chk = len ^ fuc ^ status_byte; uchar add_chk = len + fuc + status_byte + xor_chk; if (buf[7] != add_chk || buf[6+1] != add_chk) return 0; return 1; } void Parse_Status(uchar stat) { uchar mode = (stat & 0x01) ? "Remote" : "Local"; uchar status_str[10]; if ((stat & 0x06) == 0x02) strcpy(status_str, "CW"); else if ((stat & 0x06) == 0x04) strcpy(status_str, "CCW"); else if (stat & 0x02) strcpy(status_str, "Running"); else strcpy(status_str, "Standby"); LCD_DisplayStr(0, 0, "Mode: "); LCD_DisplayStr(0, 6, mode); LCD_DisplayStr(1, 0, "Status:"); LCD_DisplayStr(1, 7, status_str); } // UART 初始化(波特率9600,11.0592MHz晶振) void UART_Init() { TMOD |= 0x20; TH1 = 0xFD; // 9600bps TL1 = 0xFD; TR1 = 1; SM0 = 0; SM1 = 1; // 方式1 REN = 1; } // LCD初始化 void LCD_Init() { DelayMs(15); LCD_WriteCmd(0x38); // 8位数据,双行显示,5x7字体 DelayMs(5); LCD_WriteCmd(0x38); DelayMs(5); LCD_WriteCmd(0x38); DelayMs(5); LCD_WriteCmd(0x0C); // 开显示,无光标 DelayMs(5); LCD_WriteCmd(0x01); // 清屏 DelayMs(5); } void LCD_WriteCmd(uchar cmd) { RS = 0; RW = 0; LCD_Data = cmd; E = 1; DelayMs(1); E = 0; DelayMs(2); } void LCD_WriteData(uchar dat) { RS = 1; RW = 0; LCD_Data = dat; E = 1; DelayMs(1); E = 0; DelayMs(2); } void LCD_DisplayStr(uchar line, uchar col, uchar *str) { uchar addr = line ? 0x40 : 0x00; addr += col; LCD_WriteCmd(0x80 | addr); while (*str) { LCD_WriteData(*str++); } } void DelayMs(uint ms) { uint i, j; for (i = ms; i > 0; i--) for (j = 110; j > 0; j--); } ``` --- #### **本地控制站(下位机)代码片段(补充核心逻辑)** ```c // 在main循环中定发送状态 void Timer0_Init() { TMOD |= 0x01; TH0 = (65536 - 50000) / 256; TL0 = (65536 - 50000) % 256; ET0 = 1; TR0 = 1; EA = 1; } void timer0_isr() interrupt 1 { static uchar cnt = 0; cnt++; if (cnt >= 10) { // 每500ms cnt = 0; Send_Status(); } } void Send_Status() { uchar mode = P3_2; // 假设P3.2为模式选择 uchar run = P2_0; uchar cw = P2_1; uchar ccw = P2_2; uchar stat = 0; stat |= (mode << 0); stat |= (run << 1); stat |= (cw << 2); stat |= (ccw << 3); Send_Packet(1, stat); // 功能码1:状态上报 } ``` --- ### **代码解析** 1. **通信协议实现**: - 使用`0x66666666`作为同步头,确保帧对齐。 - `XOR`校验从`LEN`到`DATA`逐字节异或,`ADD`校验包含`XOR`结果,增强可靠性。 - 上行报文每0.5秒发送一次状态字节。 2. **HMI输入处理**: - 利用外部中断INT1检测任意按键按下,再通过读取P1口低3位确定具体按键(消抖后)。 - 将按键映射为控制命令(0:停止, 1:正转, 2:反转),封装成下行报文发送。 3. **LCD显示更新**: - 初始化LCD1602,设置双行显示。 - 根据接收到的状态字节解析模式和运行状态,动态刷新屏幕。 4. **串口通信**: - 波特率设为9600bps,晶振11.0592MHz,保证误差最小。 - 发送逐字节写入SBUF,等待TI置位;接收采用查询RI方式。 5. **故障保护机制**: - 若连续两次未收到状态包,判定通信失败,显示“Comm Err”并停止输出。 --- ### **知识点** - **串行通信异步传输原理**:通过起始位、数据位、停止位实现非同步钟下的可靠传输,依赖双方波特率一致。 - **RS-485差分信号优势**:利用A/B双线差压传值,抗干扰强,支持长距离(>1km)多点通信。 - **LCD1602指令集控制**:通过RS/RW/E序配合写入指令或数据,实现清屏、光标定位、字符显示等功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值