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

STM32-HAL库驱动DHT11温湿度传感器 --2024.9.28

目录

一、教程简介

二、驱动原理讲解

        (一)通信4步骤

        (二)传感器数据解析

三、CubeMX生成底层代码

        (一)基础配置

        (二)配置DHT11的驱动引脚

        (三)配置串口

四、Keil中编写代码

        (一)dht11.c 代码

        (二)dht11.h 代码

        (三)main.c 中调用

五、效果展示


一、教程简介

        DHT11是单片机开发常用的一个温湿度传感器,采用单总线通信,优点是单片机和传感器的连接只需要一根数据线,缺点则是对通信时序的要求较高。

        本教程用通俗易懂的语言和详细的操作过程截图,为开发者清除DHT11这只拦路虎,本教程还提供可以快速使用DHT11的驱动代码,只要跟着本教程操作,都可以正确读取到温湿度信息。

二、驱动原理讲解

        DHT11采用的是单总线的通信方式,系统中数据的交换、控制均由单总线完成。(注意:DHT11的数据引脚需要一个4.7K的上拉电阻,若使用的传感器是不带PCB的那种,请自己外加上拉电阻)。

   (一)通信4步骤

        步骤一:

        DHT11上电后(DHT11上电后要等待1S以越过不稳定状态在此期间不能发送任何指令),测试环境温湿度数据,并记录数据,同时DHT11的DATA数据线由上拉电阻拉高一直保持高电平;此时DHT11的DATA引脚处于输入状态,时刻检测外部信号。

        步骤二:

        微处理器的I/0设置为输出同时输出低电平,且低电平保持时间不能小于18ms(最大不得超过30ms),然后微处理器的I/0设置为输入状态,由于上拉电阻,微处理器的I/0即DHT11的DATA数据线也随之变高,等待DHT11作出回答信号。发送信号如下图所示:

        步骤三:

        DHT11的DATA引脚检测到外部信号有低电平时,等待外部信号低电平结束,延迟后DHT11的DATA引脚处于输出状态,输出83微秒的低电平作为应答信号,紧接着输出87微秒的高电平通知外设准备接收数据,微处理器的I/0此时处于输入状态,检测到I/0有低电平(DHT11回应信号)后,等待87微秒的高电平后的数据接收,发送信号如图5所示:

         步骤四:

         由DHT11的DATA引脚输出40位数据,微处理器根据I/0电平的变化接收40位数据,位数据“0”的格式为:54微秒的低电平和23-27微秒的高电平,位数据“1”的格式为:54微秒的低电平加68-74微秒的高电平。位数据“0”、“1”格式信号如图6所示:

        结束信号     

        DHT11的DATA引脚输出40位数据后,继续输出低电平54微秒后转为输入状态,由于上拉电阻随之变为高电平。但DHT11内部重测环境温湿度数据,并记录数据,等待外部信号的到来。

   (二)传感器数据解析

        传感器发送的40位数据分为5个部分,分别是:湿度高8位、湿度低8位、温度高8位、温度低8位、校验位。下面举例分析:

        示例一:接收到的40位数据为

0011 01010000 00000001 10000000 01000101 0001
湿度高8位湿度低8位温度高8位温度低8位校验位

        计算:                                                                                                                                        

        00110101 + 00000000 + 00011000 + 00000100 = 01010001                                                   

        校验正确,接收数据正确。                                                                                                        

        湿度:00110101(整数) = 0x35 = 53%   ,湿度小数为0。                                                         

                   所以湿度为: 53%                                                                                                          

        温度:00011000(整数) = 0x18 = 24 度  ,00000100(小数) = 0x04 = 0.4度                              

                   所以温度为:24 + 0.4 = 24.4 摄氏度                                                                              

三、CubeMX生成底层代码

(一)基础配置

        1、配置Debug

        2、配置外部高速晶振

        3、 配置时钟

(二)配置DHT11的驱动引脚

        将任意一个引脚配置为:输出模式、内部上拉、高速模式、重命名为DHT11

(三)配置串口

(四)生成工程文件

四、Keil中编写代码

(一)dht11.c 代码

#include "dht11.h"
/** DHT11引脚:输入/输出模式配置函数 * Mode = 0/INPUT  时 输入模式  * Mode = 1/OUTPUT 时 输出模式  */
void DHT11_PIN_Mode(int Mode)
{	if(Mode)   {GPIO_InitTypeDef GPIO_InitStruct = {0};							// 定义GPIO_InitTypeDef结构体 GPIO_InitStruct.Pin = DHT11_Pin;                    // 引脚选择GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;         // 引脚模式:输出模式GPIO_InitStruct.Pull = GPIO_NOPULL;                 // 配置内部上拉GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;       // 引脚速率:高速HAL_GPIO_Init(DHT11_GPIO_Port, &GPIO_InitStruct);}else{GPIO_InitTypeDef GPIO_InitStruct = {0};						// 定义GPIO_InitTypeDef结构体 GPIO_InitStruct.Pin = DHT11_Pin;				    				// 引脚选择GPIO_InitStruct.Mode = GPIO_MODE_INPUT;							// 引脚模式:输入模式GPIO_InitStruct.Pull = GPIO_NOPULL;									// 配置内部上拉HAL_GPIO_Init(DHT11_GPIO_Port, &GPIO_InitStruct);}
}  /**DHT11起始函数*根据DHT11时序图,主机要要发送起始信号,需要将总线电平拉低(18~30ms)*/
void DHT11_Start(void)
{DHT11_PIN_Mode(OUTPUT);DHT11_IO_SET;    				// 先让总线处于高电平状态HAL_Delay(1);DHT11_IO_RESET;  				// 拉低总线20ms,表示主机发送起始信号HAL_Delay(20);DHT11_IO_SET;    				// 将总线拉高等待传感器响应DHT11_Delay_us(30);
}/*** DHT11响应检测函数* 返回1:未检测到DHT11的存在* 返回0:存在出现由高到低的变化即可*/
uint8_t DHT11_Check(void)
{uint8_t retry = 0;DHT11_PIN_Mode(INPUT);              //将引脚切换为输入模式while(!DHT11_IO_Read && retry<100)  //单片机发送起始信号后,DHT11会将总线拉低83微妙{retry++;DHT11_Delay_us(1);}if(retry >= 100)return 1;else retry = 0;while(DHT11_IO_Read && retry<100)  //DHT11拉低后会再次拉高87微妙{retry++;DHT11_Delay_us(1);}if(retry >= 100) return 1;return 0;
}/*** 从DHT11读取一个位* 返回值:1/0*/
uint8_t DHT11_Read_Bit(void)
{DHT11_PIN_Mode(INPUT);while(!DHT11_IO_Read);DHT11_Delay_us(40);if(DHT11_IO_Read){while(DHT11_IO_Read);return 1;}else{return 0;}
}/***  读取一个字节数据 1byte / 8bit*  返回值是一个字节的数据*/
uint8_t DHT11_Read_Byte(void)
{uint8_t i,buf = 0;                             //  暂时存储数据for(i=0; i<8 ;i++){buf <<= 1;                                 if(DHT11_Read_Bit())                        //  1byte -> 8bit{buf |= 1;                              //  0000 0001}}return buf;
}/*** 读取温湿度传感器数据 5byte / 40bit* 使用方法:创建两个float变量,将变量地址传入函数* 注意:两次使用该函数的间隔需要大于2秒,否则会导致数据测量不准确*/
uint8_t data[5] = {0};uint8_t DHT11_READ_DATA(float *temp, float *humi)
{uint8_t i;DHT11_Start();                                 //  主机发送启动信号if(!DHT11_Check())                             //  如果DHT11应答     {  for(i=0; i<5; i++){                        data[i] = DHT11_Read_Byte();             //  读取 5byte}if(data[0] + data[1] + data[2] + data[3] == data[4]){*humi = data[0] + 0.1*data[1];*temp = data[2] + 0.1*data[3];return 1;                                //  数据校验通过}else return 0;                              //  数据校验失败}else return 2;                                 //  如果DHT11不应答
}/*** 微妙延时函数* 全系列通用,只需要将宏定义CPU_FREQUENCY_MHZ根据时钟主频修改即可。* 系统滴答定时器是HAL库初始化的,且必须有HAL库初始化。*/
#define CPU_FREQUENCY_MHZ   (int)(HAL_RCC_GetHCLKFreq()/1000000)		// 自动获取STM32时钟主频void DHT11_Delay_us(__IO uint32_t delay)  
{int last, curr, val;int temp;while (delay != 0){temp = delay > 900 ? 900 : delay;last = SysTick->VAL;curr = last - CPU_FREQUENCY_MHZ * temp;if (curr >= 0){do{val = SysTick->VAL;}while ((val < last) && (val >= curr));}else{curr += CPU_FREQUENCY_MHZ * 1000;do{val = SysTick->VAL;}while ((val <= last) || (val > curr));}delay -= temp;}
}

(二)dht11.h 代码

#include "main.h"#ifndef __DHT11_H_
#define __DHT11_H_
/**** 如果未用CubeMX配置引脚,可以将下面代码的注释取消,并替换后面的GPIOB以及GPIO_PIN_1 * 例如: 使用了PA5引脚,则应将 GPIOB 替换成 GPIOA ,将 GPIO_PIN_1 替换成 GPIO_PIN_5*
***/// #define DHT11_GPIO_Port GPIOB
// #define DHT11_Pin       GPIO_PIN_1#define DHT11_IO_Read   HAL_GPIO_ReadPin(DHT11_GPIO_Port,DHT11_Pin)                   //读DHT11引脚电平
#define DHT11_IO_SET    HAL_GPIO_WritePin(DHT11_GPIO_Port,DHT11_Pin,GPIO_PIN_SET)     //DHT11引脚置高电平
#define DHT11_IO_RESET  HAL_GPIO_WritePin(DHT11_GPIO_Port,DHT11_Pin,GPIO_PIN_RESET)   //DHT11引脚置低电平#define INPUT 0   //引脚输入模式
#define OUTPUT 1  //引脚输出模式void DHT11_Delay_us(__IO uint32_t delay);           // 微妙级延时函数
void DHT11_PIN_Mode(int Mode);  										// 引脚模式配置函数
void DHT11_Start(void);         										// 起始信号发送函数
uint8_t DHT11_Check(void);      										// DHT11应答检测函数
uint8_t DHT11_Read_Bit(void);   										// 读取一个数据位(bit),8 bit = 1 byte
uint8_t DHT11_Read_Byte(void);  										// 读取一个字节的数据
uint8_t DHT11_READ_DATA(float *temp, float *humi);  // 温湿度数据读取函数#endif

 (三)main.c 中调用

       注意: 在main.c中需要包含dht11.h、stdio.h两个头文件,声明两个浮点变量和一个串口发送缓冲数组。使用的时候不需要初始化,直接放while里面循环读取就可,但必须要加上延时。        

/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "gpio.h"/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "dht11.h"
#include "stdio.h"
/* USER CODE END Includes *//* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
float Humi,Temp;
char  DHT11_TX[40];
/* USER CODE END PTD *//* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD *//* USER CODE END PD *//* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM *//* USER CODE END PM *//* Private variables ---------------------------------------------------------*//* USER CODE BEGIN PV *//* USER CODE END PV *//* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP *//* USER CODE END PFP *//* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 *//* USER CODE END 0 *//*** @brief  The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initializes the Flash interface and the Systick. */HAL_Init();/* USER CODE BEGIN Init *//* USER CODE END Init *//* Configure the system clock */SystemClock_Config();/* USER CODE BEGIN SysInit *//* USER CODE END SysInit *//* Initialize all configured peripherals */MX_GPIO_Init();MX_USART1_UART_Init();/* USER CODE BEGIN 2 *//* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){HAL_Delay(2000);DHT11_READ_DATA(&Temp,&Humi);sprintf(DHT11_TX,"温度:%0.1f 度	湿度:%0.1f %%\r\n",Temp,Humi);HAL_UART_Transmit(&huart1,(uint8_t*)DHT11_TX,40,200);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}

五、效果展示

相关文章:

STM32-HAL库驱动DHT11温湿度传感器 --2024.9.28

目录 一、教程简介 二、驱动原理讲解 &#xff08;一&#xff09;通信4步骤 &#xff08;二&#xff09;传感器数据解析 三、CubeMX生成底层代码 &#xff08;一&#xff09;基础配置 &#xff08;二&#xff09;配置DHT11的驱动引脚 &#xff08;三&#xff09;配置串口 四…...

使用C语言获取iostat中的await值的方法和方案

使用C语言获取iostat中的await值的方法和方案 1. 准备工作2. 调用iostat命令并获取输出3. 解析iostat输出4. 完整实现和错误处理5. 注意事项在Linux系统中,iostat命令是sysstat软件包的一部分,用于监控系统的CPU、网卡、tty设备、磁盘、CD-ROM等设备的活动情况和负载信息。其…...

阿里云域名解析和备案

文章目录 1、域名解析2、新手引导3、ICP备案 1、域名解析 2、新手引导 3、ICP备案...

gitee公钥设置、创建库及使用

简介 一、如何安装git 使用gitee&#xff0c;需要先安装git工具。 工具网站地址&#xff1a;https://git-scm.com/downloads 安装完成后&#xff0c;在terminal命令行输入git --version可以查看到git的版本。 二、登录gitee 我们先在 gitee上注册账号并登录。gitee官网&#x…...

融媒体服务中PBO进行多重采样抗锯齿(MSAA)

如果不理解pbo 那先去了解概念&#xff0c;在此不再解释&#xff0c;这是我为了做融合服务器viewpointserver做的一部分工作&#xff0c;融合服务器的功能是将三维和流媒体&#xff0c;AI融合在一起&#xff0c;viewpointserver会直接读取三维工程的文件&#xff0c;同时融合rt…...

说说BPMN概念及应用

BPMN&#xff08;Business Process Modeling and Notation&#xff09;即业务流程建模与标注&#xff0c;是一种由OMG&#xff08;Object Management Group&#xff0c;对象管理组织&#xff09;制定的业务流程建模语言。以下是对BPMN标准的详细解释&#xff1a; 一、BPMN的起…...

【微服务】初识(day1)

基础概念 集群 集群是将一个系统完整的部署到多个服务器&#xff0c;每个服务器提供系统的所有服务&#xff0c;多个服务器可以通过负载均衡完成任务&#xff0c;每个服务器都可以称为集群的节点。 分布式 分布式是将一个系统拆分为多个子系统&#xff0c;多个子系统部署在…...

15分钟学 Python 第40天:Python 爬虫入门(六)第一篇

Day40 &#xff1a;Python 爬取豆瓣网前一百的电影信息 1. 项目背景 在这个项目中&#xff0c;我们将学习如何利用 Python 爬虫技术从豆瓣网抓取前一百部电影的信息。通过这一练习&#xff0c;您将掌握网页抓取的基本流程&#xff0c;包括发送请求、解析HTML、存储数据等核心…...

分层解耦-05.IOCDI-DI详解

一.依赖注入的注解 在我们的项目中&#xff0c;EmpService的实现类有两个&#xff0c;分别是EmpServiceA和EmpServiceB。这两个实现类都加上Service注解。我们运行程序&#xff0c;就会报错。 这是因为我们依赖注入的注解Autowired默认是按照类型来寻找bean对象的进行依赖注入…...

HCIP-HarmonyOS Application Developer 习题(六)

&#xff08;多选&#xff09;1、Harmonyos多窗口交互能力提供了以下哪几种交互方式? A. 平行视界 B.全局消息通知 C.分屏 D.悬浮窗 答案&#xff1a;ACD 分析&#xff1a;系统提供了悬浮窗、分屏、平行视界三种多窗口交互&#xff0c;为用户在大屏幕设备上的多任务并行、便捷…...

【电路基础 · 3】实际电压源 实际电流源;两种电源的等效情况;戴维南模型 诺顿模型(自用)

总览 1.实际电源的两种模型和它们的等效变换 2.两种电源的等效情况 3.戴维南模型 && 诺顿模型 一、实际电源的两种模型和它们的等效变换 1.实际电压源 实际电压源不允许短路。因为它的内阻太小&#xff0c;如果短路&#xff0c;电流很大&#xff0c;可能会烧毁电源…...

案例-猜数字游戏

文章目录 效果展示初始画面演示视频 代码区 效果展示 初始画面 演示视频 猜数字游戏 代码区 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width,…...

POI数据的处理与分析

POI概念 POI&#xff08;Point of Interest&#xff0c;兴趣点&#xff09;数据指的是地理空间数据中的一类&#xff0c;表示某一具体地点或位置的信息。通常&#xff0c;这些数据包含位置坐标&#xff08;经纬度&#xff09;、名称、地址、类别和其他相关信息。POI 数据广泛应…...

ansible部分模块学习

ansible模块学习 copy模块 copy模块srcsource 源⽂件destdestination ⽬标backupbackupyes 则会在覆盖前进⾏备份mode修改权限owner修改为指定所有者group修改为指定⽤户组 案例1&#xff1a;传输/root/work/scripts/net-tools-install.sh⽂件到/opt/net-tools-install.sh …...

数据库(MySQL):使用命令从零开始在Navicat创建一个数据库及其数据表(二).设置主键自增等特点

前言 在上一节中&#xff0c;主要介绍了 Navicat Premium 17 的使用以及创建一个基础的表格。当时只设置了给数据表补充字段&#xff0c;没有设置给数据表删除字段。现在补充一下。 ALTER TABLE student ADD test int(4); 给名为 student 的数据表添加 test 列&#xf…...

SQL第13课——创建高级联结

本课讲另外一些联结&#xff08;含义和使用方法&#xff09;&#xff0c;如何使用表别名&#xff0c;如何对被联结的表使用聚集函数。 13.1 使用表别名 第7课中使用别名引用被检索的表列&#xff0c;给列起别名的语法如下&#xff1a; SQL除了可以对列名和计算字段使用别名&a…...

订阅ROS2中相机的相关话题并保存RGB、深度和点云图

系统&#xff1a;Ubuntu22.04 ROS2版本&#xff1a;ROS2 humble 1.订阅ROS2中相机的相关话题并保存RGB图、深度图和点云图 ros2 topic list/stellar_1/rgb/image_raw /camera/depth/image_raw /stellar_1/points2CMakeLists.txt cmake_minimum_required(VERSION 3.15) projec…...

Open WebUI | 自托管的类 ChatGPT 网站

Open WebUI 是一个扩展性强、功能丰富且用户友好的自托管 WebUI&#xff0c;旨在完全离线操作。它支持各种 LLM 服务&#xff0c;包括 Ollama 和 OpenAI 兼容的 API。该项目在 GitHub 上已有 38k 星&#xff0c;非常受欢迎。 功能介绍 废话不多说&#xff0c;上图&#xff01;…...

【Python】Python知识总结浅析

Python是一种高级编程语言&#xff0c;由Guido van Rossum于1991年首次发布。它以简洁的语法和强大的功能著称&#xff0c;适用于多种应用场景&#xff0c;包括Web开发、数据分析、人工智能、自动化脚本等。 易于学习和使用&#xff1a;Python的语法简洁明了&#xff0c;适合初…...

c#代码介绍23种设计模式_20策略者模式

目录 1、策略模式的定义 2、策略模式的结构 3、涉及到三个角色: 4、策略者模式在.NET中应用 5、策略者模式的适用场景 6、策略者模式的优缺点 7、实现思路 在现实生活中,策略模式的例子也非常常见,例如,中国的所得税,分为企业所得税、外商投资企业或外商企业所得税…...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中&#xff0c;结构体可以嵌套使用&#xff0c;形成更复杂的数据结构。例如&#xff0c;可以通过嵌套结构体描述多层级数据关系&#xff1a; struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序

一、开发环境准备 ​​工具安装​​&#xff1a; 下载安装DevEco Studio 4.0&#xff08;支持HarmonyOS 5&#xff09;配置HarmonyOS SDK 5.0确保Node.js版本≥14 ​​项目初始化​​&#xff1a; ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

代理篇12|深入理解 Vite中的Proxy接口代理配置

在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机

这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机&#xff0c;因为在使用过程中发现 Airsim 对外部监控相机的描述模糊&#xff0c;而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置&#xff0c;最后在源码示例中找到了&#xff0c;所以感…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)

RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发&#xff0c;后来由Pivotal Software Inc.&#xff08;现为VMware子公司&#xff09;接管。RabbitMQ 是一个开源的消息代理和队列服务器&#xff0c;用 Erlang 语言编写。广泛应用于各种分布…...

Razor编程中@Html的方法使用大全

文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...

LRU 缓存机制详解与实现(Java版) + 力扣解决

&#x1f4cc; LRU 缓存机制详解与实现&#xff08;Java版&#xff09; 一、&#x1f4d6; 问题背景 在日常开发中&#xff0c;我们经常会使用 缓存&#xff08;Cache&#xff09; 来提升性能。但由于内存有限&#xff0c;缓存不可能无限增长&#xff0c;于是需要策略决定&am…...

Monorepo架构: Nx Cloud 扩展能力与缓存加速

借助 Nx Cloud 实现项目协同与加速构建 1 &#xff09; 缓存工作原理分析 在了解了本地缓存和远程缓存之后&#xff0c;我们来探究缓存是如何工作的。以计算文件的哈希串为例&#xff0c;若后续运行任务时文件哈希串未变&#xff0c;系统会直接使用对应的输出和制品文件。 2 …...