GPIO

GPIO:通用输入输出口;可配置8种输入输出模式

引脚电平:0V-3.3V,部分引脚可容忍5V也可认为高电平,但是对于输出而言,最大就只能输出3.3V,因为供电就只有3.3V,

能容忍5v的在以下的引脚定义下,I/O电平含FT的可以

输出模式下可控制端口输出高低电平,用以驱动LED、控制蜂鸣器、模拟通信协议输出时序等

输入模式下可读取端口的高低电平或电压,用于读取按键输入(最常用)、外接模块电平信号输入、ADC电压采集、模拟通信协议接收数据等

GPIO的基本结构:GPIO挂载在APB2上的

总共有16个引脚,一般称为PA0~PA15

GPIO分为不同的模块:用GPIOA、GPIOB来表示,主要包含了寄存器(是一段特殊的存储器,内核可以通过APB2总线对寄存器进行读写,从而完成对于的输入输出功能)和驱动器。

在模块内每一个位对于一个引脚,其中输出寄存器写1,对于的引脚就会输出高电平,写0就输出低电平,输入同理。

STM32为32位的寄存器,但是模块中的端口只有16位,所有这个寄存器只有低16位的端口

GPIO的电路图:

输入部分

  1. 引脚部分

这接入了两个保护二极管,目的是保护电路的:

  上面的二极管接VDD,3.3V:如果输入电压比3.3V还要高,则上方会被导通,输入电压产生的电流会流入VDD,从而保护电路;

下面的二极管接VSS,0V:同理;

补:VDD:代表总正极,常用于现代电子

        VCC:代表总正极,常用于三极管等

        VSS:代表总负极,在MOS管电路中更常用。

        GND:所有电路的公共回路

如果电流在0-3.3V中则两边都不接通,正常流入到电路中来

这里连接一个上拉电阻(连至VDD)和下拉电阻(连至VSS),这个开关是可以通过程序进行配置的:如果上面导通,下面断开,就是上拉输入模式(高电平模式),反之;如果两个都断开则为浮空模式;如果两者都接入,并不会同时生效,相互存在互斥,为了防止电源短路风险。

作用:为了给输入提供一个默认的输入电平,因为当输入电平时没有让引脚的输入为低电平或者是高电平时,电路也不知道它是什么状态,则会被其他外界的环境所干扰;目的是不影响正常的输入操作。

补:电路:由电子元器件(电阻、电容、晶体管等)和导线组成的闭合路径,用于传输电能或处理电信号

        电压:电势差(单位:伏特 V),表示电场中两点之间的能量差,驱动电流流动。

        电平:表示数字信号的状态(高电平或低电平),通常对应特定的电压范围。

        电流:电荷的定向流动(单位:安培 A),由电压驱动。

        电平信号:用电压表示的离散信号,通常用于数字通信。

  • 电压是电流的原因,电流是电压的结果

  • 电压是“推力”,电流是“流量”。

  • 开路(断路)时:电压可以存在(如电池两极),但电流为零。 短路时:电流可以很大,但电压可能接近零。

1.在电源(如电池)内部,化学反应将正电荷推到正极(+),负电荷推到负极(-),从而在两极之间建立一个静电场。

2.没有闭合回路,电子无法流动

  • 断路:断路是指电路中的某处断开,导致电流无法流通,但电源电压仍然存在。

  • 短路:短路是指电路中两点之间出现极低电阻(接近0Ω)的连接,导致电流极大,电压骤降。

肖特基(施密特)触发器:

对输入电压进行整形:如果是输入电压大于某一个阈值,输出就会瞬间变为高电平,反之;

例如:通常的引脚输入的模拟信号为波形模拟信号:

会通过施密特触发器对信号进行整形,中间留有流动范围,可以有效地避免因信号波动造成的是输出抖动现象

之后就可以通过输入寄存器输入数据了,我们再用程序去读取输入数据寄存器对于某一位的数据,就可以知道端口的输入电平;

是连接片上外设的一些端口:

模拟输入:连至ADC(模拟到数字转换器),因为它需要接受模拟数据量,所以接入在触发器之前的

复用功能输入:连接到其他需要读取端口的外设上的

输出部分

数字部分可以由输出寄存器和片上外设控制,两者方式通过数据选择器接到输出控制部分;

输出寄存器:

为普通IO输出,写数据寄存器的某一位就可操作对于的某个端口;同时控制低16位端口,并且只能整体读写,

        所以如果想控制一个端口而不影响其他端口的话,需要特殊操作:

                        1.先读出这个寄存器,然后按位与&=和按位或|=的方式更改某一位。最后将更改的数据写回去;

                        2. (主要)设置位设置/清楚寄存器(可以单独拿操作输出数据寄存器的某一位,而不影响其他位),在位设置寄存器上的对于的位上修改为1即可,不修改的位置写0。如果想对一位进行清0的操作,在位清除寄存器上对应位写1即可;

                        3.读写STM32的位带区域(这段地址映射了RAM和外设寄存器所有的位);

两个Mos管,上面是P-MOS,下面N-MOS

MOS管就是一种电子开关,信号来控制开关的导通或关闭,开关负责将IO口接到VDD或者VSS。

推挽、开漏、关闭三种输出方式:

1.推挽

P-MOS和N-MOS均有效,数据寄存器为1时,上管导通,下官断开,输出直接接到VDD,输出高电平,反之;这种模式,高低电平均有较强的驱动能力,所以推挽模式也叫强输出模式。在此模式下STM32对IO口有着绝对的控制权。

2.开漏

P-MOS无效,N-MOS有效,数据寄存器为1时,下官断开,这是输出相当于断开,属于高阻模式;为0时,则是输出低电平;这种模式下只有低电平有驱动能力,作为通讯协议的模式。同时还可以用于输出5V电平信号

3.关闭

P-MOS和N-MOS均无效:当引脚配置为输入模式的时候,端口的电平由外部设备进行控制;

GPIO的8种工作模式:通过配置端口的配置寄存器

1.

电路结构基本一样,区别在与上拉电阻和下拉电阻的连接。在浮空输入模式下,端口一定要接一个连续的驱动源,从而不出现浮空的状态。

VDD 3.3V端口和VDD_FT 容忍5V端口

2.

ADC模数转换器的专属:

只有这个模式会关闭数字的输入功能

3.

区别是在高电平下的状态

可以发现输出情况下,输入是存在的,因为一个端口只有一个输出,可以有多个输入

4.

更多内容参考STM32F10xxx参考手册(中文)-第8章

GPIO的寄存器

每个端口的模式由4位进行配置

由端口配置低寄存器和端口配置高寄存器,具体配置在参考手册中

端口输入数据寄存器:,只用低16位

端口输出数据寄存器,同理

端口位设置/清除寄存器

端口位清除寄存器:为了与端口位设置/清除寄存器进行区别,此寄存器只进行位清除

端口位设置/清除寄存器,对端口的配置进行锁定,防止被更改

GPIO的外部设备和电路

LED和蜂鸣器:

LED:

发光二级管,正向通电点亮,反向通电不亮长脚为正极,内部里较小的是正极。

STM32的GPIO口驱动LED的电路

低电平驱动的电路

LED正极接入3.3V,负极通过一个限流电阻接到PA0上,当PA0输出低电平时,LED两端会产生电压差就会形成正向导通的电流,这样LED就点亮了。当PA0输出高电平时,因为LED两端都是3.3V电压,不会形成电流;限流电阻:防止LED电流过大而烧毁和调整LED的亮度;

补:此时的电压差解释:本质电压差:电路中两点之间的电压之差(即电势差);当PA0为低电平时,电压差=V正极​−V负极​=3.3V−0V=3.3V(不考虑电阻),故灯亮;当PA0为高电平时,电压差=V正极​−V负极​=3.3V−3.3V=0V,故灯灭

高电平驱动的电路

LED负极接入GND,正极通过一个限流电阻接到PA0上,反之;

至于这两种接入的选择,需靠考虑输入输出的驱动器,正如我们的STM32的GPIO的推挽模式下,低电平和高电平都具有较高的驱动能力,所以都可以使用,而对单片机或部分芯片中,都使用了高电平弱驱动,低电平高驱动的方法。

有源蜂鸣器:

内部自带振荡源,将正负极接上直流电压即可持续发声,频率固定。

电路中用了个三极管开关进行驱动,在VCC和GND上分别接上正负极的供电,中间的引脚2接入低电平,蜂鸣器就会响,高电平停止。

无源蜂鸣器:内部不带振荡源,需要控制器提供振荡脉冲才可发声,调整提供振荡脉冲的频率,可发出不同频率的声音

三极管可防止IO驱动使STM32负担过重:左边的是基极,带箭头的是发射极,剩下的是集电极

PNP三极管的驱动电路

电流方向:电流从发射极(E)流向集电极(C),基极(B)控制导通

基极给低电平,三极管则会导通,通过3.3V和GND可以给蜂鸣器提供驱动电流

基极给高电平,三极管停止,蜂鸣器没有电流

NPN三极管的驱动电路

电流方向:电流从集电极(C)流向发射极(E),基极(B)控制导通。

驱动逻辑与上分之

注:PNP的三极管最好接在上边,NPN的三极管最好接在下边:“上边”通常指靠近电源(VCC)的一侧“下边”指靠近地(GND)的一侧

    因为三级管的通断,是需要在发射极和基极产生一定的开启电压

面包板

当把元件的引脚插入面包板的孔里后,面包板内部的金属爪就会夹住引脚。

如果需要供电,就从上下的孔位,用跳线引出来即可;

如果中间部分的面包板,没有连接需要用跳线进行连接

点亮LED电路

操作GPIO,需要使用三个步骤:

  1. 使用RCC开启GPIO的时钟
  2. 使用GPIO_Init函数初始化GPIO
  3. 使用输出或输入的函数控制GPIO口

从库函数中找到RCC和GPIO两个外设相关的函数库:

stm32f10x_rcc和stm32f10x_gpio,通过查看其头文件。来找到我们需要的库函数stm32f10x_rcc:void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState);//RCC AHB外设时钟控制void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState); //RCC APB2外设时钟控制void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState); //RCC APB1外设时钟控制

跳到对应的函数里,查看调用信息:

注释上有对此函数的相关说明,以及相关参数:

stm32f10x_gpio.h:

void GPIO_DeInit(GPIO_TypeDef* GPIOx); //所指定的GPIO外设就会被复位void GPIO_AFIODeInit(void); //可以复位AFIO外设void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);//用结构体的参数来初始化GPIO口,需要手动配置一个结构体变量并赋值。void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct);  //把结构体变量赋值为一个默认值//以下四个为GPIO的读取函数uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);//以下四个为GPIO的写入函数:void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);  //可以指定的端口设置为高电平void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);  //可以指定的端口设置为低电平void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);  //根据三个参数的值,来设定此端口的电平void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);   //可以同时对16个端口进行写入操作

接线图:

LED闪烁

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
int main(void){RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//定义结构体变量GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//对其成员工作模式进行配置:推挽模式//GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD;//开漏输出模式GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;//GPIO的引脚位置配置为我们接入的A0引脚GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//默认为50mhzGPIO_Init(GPIOA,&GPIO_InitStructure);//注意此函数调用的是结构体指针,所以使用此函数时需要传递地址//输出函数//GPIO_ResetBits(GPIOA,GPIO_Pin_0);//向PA0输出低电压,灯亮(默认是低电平)GPIO_SetBits(GPIOA,GPIO_Pin_0);//反之//GPIO_WriteBit(GPIOA,GPIO_Pin_0, Bit_SET);//实现LED闪烁,新建System文件夹,相关配置之后,引入延时文件Delaywhile(1){//GPIO_SetBits(GPIOA,GPIO_Pin_0);//Delay_ms(500);//GPIO_ResetBits(GPIOA,GPIO_Pin_0);//Delay_ms(500);}
}

LED流水灯

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
int main(void){RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0 |GPIO_Pin_1|GPIO_Pin_2 |GPIO_Pin_3|GPIO_Pin_4 |GPIO_Pin_5|GPIO_Pin_6 |GPIO_Pin_7;GPIO_InitStructure.GPIO_Pin=GPIO_Pin_All;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);GPIO_SetBits(GPIOA,GPIO_Pin_0);while(1){/*使用GPIO_Write,同时设置GPIOA所有引脚的高低电平,实现LED流水灯,Write直接写入OCD寄存器中*/GPIO_Write(GPIOA, ~0x0001);	//0000 0000 0000 0001,PA0引脚为低电平,其他引脚均为高电平,注意数据有按位取反Delay_ms(100);				//延时100msGPIO_Write(GPIOA, ~0x0002);	//0000 0000 0000 0010,PA1引脚为低电平,其他引脚均为高电平Delay_ms(100);				//延时100msGPIO_Write(GPIOA, ~0x0004);	//0000 0000 0000 0100,PA2引脚为低电平,其他引脚均为高电平Delay_ms(100);				//延时100msGPIO_Write(GPIOA, ~0x0008);	//0000 0000 0000 1000,PA3引脚为低电平,其他引脚均为高电平Delay_ms(100);				//延时100msGPIO_Write(GPIOA, ~0x0010);	//0000 0000 0001 0000,PA4引脚为低电平,其他引脚均为高电平Delay_ms(100);				//延时100msGPIO_Write(GPIOA, ~0x0020);	//0000 0000 0010 0000,PA5引脚为低电平,其他引脚均为高电平Delay_ms(100);				//延时100msGPIO_Write(GPIOA, ~0x0040);	//0000 0000 0100 0000,PA6引脚为低电平,其他引脚均为高电平Delay_ms(100);				//延时100msGPIO_Write(GPIOA, ~0x0080);	//0000 0000 1000 0000,PA7引脚为低电平,其他引脚均为高电平Delay_ms(100);				//延时100ms}
}

蜂鸣器

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
int main(void){RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0 |GPIO_Pin_1|GPIO_Pin_2 |GPIO_Pin_3|GPIO_Pin_4 |GPIO_Pin_5|GPIO_Pin_6 |GPIO_Pin_7;GPIO_InitStructure.GPIO_Pin=GPIO_Pin_12;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOB,&GPIO_InitStructure);GPIO_SetBits(GPIOB,GPIO_Pin_12);while(1){GPIO_ResetBits(GPIOB,GPIO_Pin_12);Delay_ms(100);GPIO_SetBits(GPIOB,GPIO_Pin_12);Delay_ms(100);GPIO_ResetBits(GPIOB,GPIO_Pin_12);Delay_ms(100);GPIO_SetBits(GPIOB,GPIO_Pin_12);Delay_ms(700);}
}

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

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

相关文章

Linux系统学习2之磁盘管理

了解磁盘内容:df:df -a (-a是列出所有,-k以kb显示,-h以Gb显示,-m以Mbyte显示,-H为用1000b代替1024b,-t为显示文件类型,-i为用inode显示容量):&a…

北大、蚂蚁三个维度解构高效隐私保护机器学习:前沿进展+发展方向

在数据隐私日益重要的 AI 时代,如何在保护用户数据的同时高效运行机器学习模型,成为了学术界和工业界共同关注的难题。北大团队最新完成的综述《Towards Efficient Privacy-Preserving Machine Learning: A Systematic Review from Protocol, Model, and…

计算机网络:如何在实际网络中进行子网划分

在实际网络中,子网划分是通过“借位”将一个大的IP网络分割为多个小的子网,以提高IP地址利用率、增强网络安全性和简化管理。以下是具体的实施步骤、原理和注意事项: 一、子网划分的核心目的 提高IP利用率:避免大网络中IP地址的浪费(例如一个C类地址默认支持254台主机,若…

《第五篇》基于RapidOCR的图片和PDF文档加载器实现详解

基于RapidOCR的图片和PDF文档加载器实现详解 引言 在构建知识库时,我们经常需要处理包含图片和PDF文档的数据。这些文档中的文本信息通常以图像形式存在,需要通过OCR技术来提取。本文将详细介绍如何使用RapidOCR技术实现图片和PDF文档的文本提取加载器。 核心概念 RapidO…

[硬件电路-122]:模拟电路 - 信号处理电路 - 模拟电路与数字电路、各自的面临的难题对比?

数字电路和模拟电路是电子技术的两大基础分支,它们分别处理不同类型的信号,并在设计方法、元件特性、应用场景等方面存在显著差异。以下是两者的详细定义及异同对比:一、定义与核心概念1. 模拟电路(Analog Circuit)定义…

Linux多线程——线程控制

目录 1.线程知识补充 1.1 线程私有资源 1.2 线程共享资源 1.3 原生线程库 2、线程控制接口 2.1 线程创建 2.1.1 一批线程 2.2 线程等待 2.3 线程终止 2.4 线程实战 2.5 其他接口 2.5.1 关闭线程pthread_cancel 2.5.2 获取线程 ID pthread_self 2.5.3 线pthread_de…

Python爬虫实战:研究spiderfoot工具,构建网络情报收集系统

1. 引言 1.1 研究背景 在数字化时代,互联网公开信息已成为国家治理、企业决策与学术研究的战略资源。据 Statista 统计,2023 年全球互联网数据总量突破 120ZB,其中可通过公开渠道获取的情报信息占比超 30%。传统人工信息收集方式受限于效率与广度,难以应对海量数据处理需…

在路由器openwrt上安装openclas

在路由器openwrt上安装openclas 名词解释 las: lash 运行效果图 安装 安装教程参考: 官方:github.com 官方2:openclas.net 如果安装完成后菜单上没有,重启路由后在“服务”菜单下 点击运行会提示下载内核,按提示…

HIVE 窗口函数处理重复数据

窗口函数row_number(),结合OVER子句中的PARTITION BY和ORDER BY,为数据分组内的每一行生成一个唯一的序号。具体分析如下:函数作用:row_number():为每个分组内的行分配一个唯一的连续序号(从1开始&#xff…

自动驾驶控制算法——MPC控制算法

自动驾驶控制算法——MPC控制算法 文章目录自动驾驶控制算法——MPC控制算法一、MPC 是什么?1.1 定义与核心思想1.2 MPC 与传统控制器(如 PID)的区别1.3 自动驾驶中 MPC 的典型应用场景🚗 轨迹跟踪控制(Trajectory Tra…

【DL学习笔记】各种卷积操作总结(深度可分离、空洞、转置、可变形)

Vanilla Convolution 普通卷积 卷积通道数: 卷积核的数量决定输出的张量的通道数nnn,输入的张量和每一个核Kernel做卷积运算得到一个channel的输出。输入通道数CinC_{in}Cin​决定每一个卷积核的通道数 卷积输出feature map的尺寸的计算公式&#xff1…

【Ubuntu】请问,`ip -a`显示的“wlo1”是什么呀?

商量AI wlo1 是 Linux 系统中 无线网络接口(Wi-Fi 网卡)的名称,其命名遵循现代 Linux 的 可预测网络接口命名规则(Predictable Network Interface Names)。以下是详细解析:命名规则拆解 wlo1 的结构由三部分…

Excel商业智能分析报表 【销售管理分析仪】

1.销售漏斗(Sales Funnel)分析🌟🌟 销售漏斗定义:科学反映商机状态及销售效率的销售管理模型。适用场景:关系型销售运营(需长期维护客户关系的销售模式)。核心功能:按销售…

【论文阅读|V2M: VISUAL 2-DIMENSIONAL MAMBA FOR IMAGE REPRESENTATION LEARNING】

论文题目:V2M: VISUAL 2-DIMENSIONAL MAMBA FOR IMAGE REPRESENTATION LEARNING 年份:2024 期刊会议: arXiv 代码链接:https://github.com/wangck20/V2M 目录 现阶段存在的问题 1. 二维结构信息丢失 2. 一维 Mamba 架构的局限性 3. 提升视觉任务表现 相关研究 方法 二维…

服务器数据安全:利用阿里云OSS/腾讯云COS实现网站数据自动备份

更多云服务器知识,尽在hostol.com你的网站,就像一座你亲手在数字海滩上堆砌起来的、精美绝伦的“沙堡”。你为它设计了独特的风格,添置了丰富的内容,吸引了越来越多的游客前来参观。每一篇文章,每一条评论,…

AdGuard 安卓修改版:全方位广告拦截与隐私保护专家

AdGuard 安卓版是一款功能强大的广告拦截软件,能够有效阻止网页和应用程序中的广告和跟踪器,提升用户的浏览体验。它不仅提供了广泛的广告拦截功能,还通过多种隐私保护功能,确保用户的个人信息安全。以下是 AdGuard 安卓版的详细介…

Mysql中的锁到底是什么?锁的是什么?

MySQL InnoDB 的锁:一次从“守卫”到“交通指挥中心”的深度之旅 MySQL InnoDB 的锁。这个概念常常让人觉得复杂抽象,但我们需要抓住它的底层设计哲学 忘记那些代码和术语定义,我们先从最底层的问题开始思考: 思考一:为…

CVE-2020-24557

一、漏洞原理 CVE-2020-24557 是 D-Link 路由器(如 DIR-816L2) 中存在的一个 命令注入(Command Injection) 漏洞,其核心原理为: ①路由器的管理界面(Web 或 CGI 接口)在处理某些用户…

proxychains——Linux代理工具

简介 ProxyChains是一个UNIX程序,通过预加载动态库(dlsym(),LD_PRELOAD)劫持动态链接程序中与网络相关的libc函数,将连接重定向至SOCKS4a/5或HTTP代理。仅支持TCP协议(不支持UDP/ICMP等)。它的工作方式基本…

精确调控建筑环境,楼宇自控系统大幅提升居住舒适度

在现代城市化进程中,建筑环境的舒适度已成为衡量生活质量的重要指标。随着科技的飞速发展,楼宇自控系统(Building Automation System, BAS)正以前所未有的精准度重新定义人与空间的互动关系。这套集成了物联网、大数据和人工智能的…