STM32-GPIO的配置和使用
1.寄存器介绍
STM32 的每个 IO 端口都有 7 个寄存器来控制。他们分别是:配置模式的 2 个 32 位的端口配置寄存器CRL 和 CRH;2 个 32 位的数据寄存器IDR 和 ODR;1 个 32 位的置位/复位寄存器BSRR;一个 16 位的复位寄存器 BRR;1 个 32 位的锁存寄存器LCKR;这里我们仅介绍常用 的几个寄存器,我们常用的 IO 端口寄存器只有 4 个:CRL、CRH、IDR、ODR,即端口配置寄存器和数据寄存器。
1.1端口配置寄存器(CRL和CRH)
CRL:每个 IO 端口的位占用 CRL 的 4 个位,高两位为 CNF,用来配置端口的模式,低两位为 MODE,用来配置端口的最大输出速度(CRH 的作用和 CRL 完全一样,只是 CRL 控制的是低 8 位输出口,而 CRH 控制的是高 8位输出口)。
比如我们要配置端口n为"推挽输出、最大输出速度为10M",那就是CNFn[1:0]=00,MODEn[1:0]=01。
关于IO模式(转自不文东)
(1) 浮空输入_IN_FLOATING ——浮空输入,可以做KEY识别,RX1
(2)带上拉输入_IPU——IO内部上拉电阻输入
(3)带下拉输入_IPD—— IO内部下拉电阻输入
(4) 模拟输入_AIN ——应用ADC模拟输入,或者低功耗下省电
(5)开漏输出_OUT_OD ——IO输出0接GND,IO输出1,悬空,需要外接上拉电阻,才能实现输出高电平。当输出为1时,IO口的状态由上拉电阻拉高电平,但由于是开漏输出模式,这样IO口也就可以由外部电路改变为低电平或不变。可以读IO输入电平变化,实现C51的IO双向功能
(6)推挽输出_OUT_PP ——IO输出0-接GND, IO输出1 -接VCC,读输入值是未知的
(7)复用功能的推挽输出_AF_PP ——片内外设功能(I2C的SCL,SDA)
(8)复用功能的开漏输出_AF_OD——片内外设功能(TX1,MOSI,MISO.SCK.SS)
关于输出速度(转自wuyuzun)
I/O口输出模式下有三种输出速度可选(2MHz,10MHz,50MHz),这个速度是指I/O口驱动电路的响应速度;I/O管脚内部有多个响应不同的驱动电路,用户可以根据自己的需要选择合适的驱动电路。
高低频比较
高频驱动电路:输出频率高,噪音大,功耗高,电磁干扰强;
低频驱动电路:输出频率低,噪音小,功耗低,电磁干扰弱;提高系统EMI(电磁干扰)性能;总结:通过选择速度来选择不同的输出驱动模块,达到最佳的噪音控制和降低功耗的目的如果需要选择较高频率信号,但是却选择了低频驱动模块,很有可能会失真的输出信号;所以GPIO的引脚速度应与应用匹配。
举几个栗子:
1. 对于串口来说,加入最大波特率为115200,这样只需要用2M的GPIO的引脚速度就可以了,省电噪音又小;
2. 对于I2C接口,假如使用400 000波特率,若想把余量留大一些,2M的GPIO引脚速度或许是不够,这时可以选用10M的GPIO引脚速度;
3. 对于SPI接口,假如使用18M或9M的波特率,用10M的GPIO口也不够用了,需要选择呢50M的GPIO引脚速度
4. GPIO口设置为输入时,输出驱动电路与端口是断开的,所以这时配置输出速度是无意义的;
5. 在复位期间和刚复位后,复位功能未开启,I/O端口被配置成浮空输入模式;
6. 所有端口都有外部中断能力,当使用外部中断功能时,端口必须设置成输入模式;
7. GPIO的配置具有上锁的功能,当配置好GPIO后,可以通过程序锁住配置组合,知道下次芯片复位才能解开;
1.2.数据寄存器(IDR和ODR)
IDR 是一个端口输入数据寄存器,只用了低 16 位。该寄存器为只读寄存器,并且只能以16 位的形式读出. 要想知道某个 IO 口的状态,只要读这个寄存器,再看某个位的状态就可以了。
ODR 是一个端口输出数据寄存器,也只用了低 16 位。该寄存器为可读写,从该寄存器读出来的数据可以用于判断当前 IO 口的输出状态。而向该寄存器写数据,则可以控制某个 IO 口的输出电平。
1.3.BSRR和BRR寄存器
BSRR寄存器是端口位设置/清除寄存器,它和ODR寄存器类似。
BRR寄存器是端口位清除寄存器,与BSRR的高16位相同。
2.GPIO的代码实现(库函数)
GPIO配置函数主要在stm32f10x_gpio.h/c文件中,此外在使用GPIO之前要使能端口的时钟,相关函数在stm32f10x_rcc.h/c文件中。一般的端口配置中需要用到以下两个函数。
RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);//stm32f10x_rcc.h/c中GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);//stm32f10x_gpio.h/c中
这里需要了解一些STM32的系统时钟。我们大多数情况下用到的是APB1和APB2的时钟,其中APB1上连接的是低速外设,包括电源接口、备份接口、CAN、USB、I2C1、I2C2、UART2、UART3、等等。APB2上连接的是高速外设,包括UART1、SPI1、Timer1、ADC1、ADC2、GPIO、第二功能IO口等。当我们使用外设的时候,一定要知道这个外设使用的是哪个时钟,并且使能该时钟,才能使用该外设。
2.1 RCC_APB2PeriphClockCmd( )函数
RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);函数的可选参数
//RCC_APB2Periph可选参数(以APB2为时钟源的外设):
#define RCC_APB2Periph_AFIO ((uint32_t)0x00000001)
/*与AFIO(alternate function io)时钟相关的寄存器
1、 事件控制寄存器(AFIO_EVCR)
2、 复用重映射和du调试I/O 配置寄存器(AFIO_MAPR)
3、 外部中zhi断配置寄存器1(AFIO_EXTICR1)
4、 外部中断配置寄存器2(AFIO_EXTICR2)
5、 外部中断配置寄存器3(AFIO_EXTICR3)
6、 外部中断配置寄存器4(AFIO_EXTICR4)
对这些寄存器进行操作前要使能该时钟*/
#define RCC_APB2Periph_GPIOA ((uint32_t)0x00000004)
#define RCC_APB2Periph_GPIOB ((uint32_t)0x00000008)
#define RCC_APB2Periph_GPIOC ((uint32_t)0x00000010)
#define RCC_APB2Periph_GPIOD ((uint32_t)0x00000020)
#define RCC_APB2Periph_GPIOE ((uint32_t)0x00000040)
#define RCC_APB2Periph_GPIOF ((uint32_t)0x00000080)
#define RCC_APB2Periph_GPIOG ((uint32_t)0x00000100)
#define RCC_APB2Periph_ADC1 ((uint32_t)0x00000200)
#define RCC_APB2Periph_ADC2 ((uint32_t)0x00000400)
#define RCC_APB2Periph_TIM1 ((uint32_t)0x00000800)
#define RCC_APB2Periph_SPI1 ((uint32_t)0x00001000)
#define RCC_APB2Periph_TIM8 ((uint32_t)0x00002000)
#define RCC_APB2Periph_USART1 ((uint32_t)0x00004000)
#define RCC_APB2Periph_ADC3 ((uint32_t)0x00008000)
#define RCC_APB2Periph_TIM15 ((uint32_t)0x00010000)
#define RCC_APB2Periph_TIM16 ((uint32_t)0x00020000)
#define RCC_APB2Periph_TIM17 ((uint32_t)0x00040000)
#define RCC_APB2Periph_TIM9 ((uint32_t)0x00080000)
#define RCC_APB2Periph_TIM10 ((uint32_t)0x00100000)
#define RCC_APB2Periph_TIM11 ((uint32_t)0x00200000)//NewState参数
#define IS_FUNCTIONAL_STATE(STATE) (((STATE) == DISABLE) || ((STATE) == ENABLE))
2.2 GPIO_Init( )函数
GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
GPIO_TypeDef是一个GPIO结构体,里边定义了GPIO的寄存器(可以理解为GPIO的属性,有了这些属性,它就是了GPIO),库文件使用该结构体来定义GPIO外设,这里做一个了解。在使用的时候很简单,其参数为GPIOA~G。这个时候,我们就创建了一个GPIO的空壳子,有了属性,接下来还要对其属性进行配置。
typedef struct
{__IO uint32_t CRL;__IO uint32_t CRH;__IO uint32_t IDR;__IO uint32_t ODR;__IO uint32_t BSRR;__IO uint32_t BRR;__IO uint32_t LCKR;
} GPIO_TypeDef;#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE)
#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE)
#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE)
#define GPIOE ((GPIO_TypeDef *) GPIOE_BASE)
#define GPIOF ((GPIO_TypeDef *) GPIOF_BASE)
#define GPIOG ((GPIO_TypeDef *) GPIOG_BASE)
选择了GPIO之后,接下来就要对其参数进行配置了。GPIO_InitTypeDef是一个配置GPIO(寄存器)的结构体(配置CRL、CRH寄存器参数),这些参数包括具体的端口GPIO_Pin、端口速度GPIO_Speed、端口模式GPIO_Mode(GPIO端口的模式和速度见上文)。
typedef struct
{uint16_t GPIO_Pin; /*!< Specifies the GPIO pins to be configured.This parameter can be any value of @ref GPIO_pins_define */GPIOSpeed_TypeDef GPIO_Speed; /*!< Specifies the speed for the selected pins.This parameter can be a value of @ref GPIOSpeed_TypeDef */GPIOMode_TypeDef GPIO_Mode; /*!< Specifies the operating mode for the selected pins.This parameter can be a value of @ref GPIOMode_TypeDef */
}GPIO_InitTypeDef;
GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);函数的可选参数:
//GPIO_Pin
#define GPIO_Pin_0 ((uint16_t)0x0001) /*!< Pin 0 selected */
#define GPIO_Pin_1 ((uint16_t)0x0002) /*!< Pin 1 selected */
#define GPIO_Pin_2 ((uint16_t)0x0004) /*!< Pin 2 selected */
#define GPIO_Pin_3 ((uint16_t)0x0008) /*!< Pin 3 selected */
#define GPIO_Pin_4 ((uint16_t)0x0010) /*!< Pin 4 selected */
#define GPIO_Pin_5 ((uint16_t)0x0020) /*!< Pin 5 selected */
#define GPIO_Pin_6 ((uint16_t)0x0040) /*!< Pin 6 selected */
#define GPIO_Pin_7 ((uint16_t)0x0080) /*!< Pin 7 selected */
#define GPIO_Pin_8 ((uint16_t)0x0100) /*!< Pin 8 selected */
#define GPIO_Pin_9 ((uint16_t)0x0200) /*!< Pin 9 selected */
#define GPIO_Pin_10 ((uint16_t)0x0400) /*!< Pin 10 selected */
#define GPIO_Pin_11 ((uint16_t)0x0800) /*!< Pin 11 selected */
#define GPIO_Pin_12 ((uint16_t)0x1000) /*!< Pin 12 selected */
#define GPIO_Pin_13 ((uint16_t)0x2000) /*!< Pin 13 selected */
#define GPIO_Pin_14 ((uint16_t)0x4000) /*!< Pin 14 selected */
#define GPIO_Pin_15 ((uint16_t)0x8000) /*!< Pin 15 selected */
#define GPIO_Pin_All ((uint16_t)0xFFFF) /*!< All pins selected *///GPIO_Speed
typedef enum
{ GPIO_Speed_10MHz = 1,GPIO_Speed_2MHz, GPIO_Speed_50MHz
}GPIOSpeed_TypeDef;//GPIO_MODE
#define IS_GPIO_MODE(MODE) (((MODE) == GPIO_Mode_AIN) || ((MODE) == GPIO_Mode_IN_FLOATING) || \((MODE) == GPIO_Mode_IPD) || ((MODE) == GPIO_Mode_IPU) || \((MODE) == GPIO_Mode_Out_OD) || ((MODE) == GPIO_Mode_Out_PP) || \((MODE) == GPIO_Mode_AF_OD) || ((MODE) == GPIO_Mode_AF_PP))
2.3 GPIO配置实例
IO初始化实例:
void GPIO_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);//使能PC端口时钟GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; //PC.13 端口配置GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHzGPIO_Init(GPIOC, &GPIO_InitStructure); //根据设定参数初始化GPIOC.13
}
2.4 几个常用的操作GPIO的函数
另外还有几个常用的函数,主要用来操作几个关于端口数据的寄存器(BSRR、BRR、ODR、IDR)。从下列函数的名字就能看出来,前四个是写IO数据、后四个是读IO数据。需要说明的是,要清楚操作对象是"port "还是"pin",即清楚“写寄存器”和写“寄存器的某一位的区别”——下边几个函数凡是带bits的都是操作寄存器的某一位,对应的就是一个IO引脚(pin),否则就是操作寄存器(32的寄存器,但是只用了16位【一组GPIO有16个端口】,所以定义的参数是uint16_t 型),即对应的是一组GPIO(port )。
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//端口置1
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//端口清0
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);//向端口写BitVal
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);//向GPIOx写PortValuint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//读端口值(bit)
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);//读GPIO组值(16位)
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);/*** @brief Sets the selected data port bits.* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.* @param GPIO_Pin: specifies the port bits to be written.* This parameter can be any combination of GPIO_Pin_x where x can be (0..15).* @retval None*/
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{/* Check the parameters */assert_param(IS_GPIO_ALL_PERIPH(GPIOx));assert_param(IS_GPIO_PIN(GPIO_Pin));GPIOx->BSRR = GPIO_Pin;
}/*** @brief Clears the selected data port bits.* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.* @param GPIO_Pin: specifies the port bits to be written.* This parameter can be any combination of GPIO_Pin_x where x can be (0..15).* @retval None*/
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{/* Check the parameters */assert_param(IS_GPIO_ALL_PERIPH(GPIOx));assert_param(IS_GPIO_PIN(GPIO_Pin));GPIOx->BRR = GPIO_Pin;
}/*** @brief Sets or clears the selected data port bit.* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.* @param GPIO_Pin: specifies the port bit to be written.* This parameter can be one of GPIO_Pin_x where x can be (0..15).* @param BitVal: specifies the value to be written to the selected bit.* This parameter can be one of the BitAction enum values:* @arg Bit_RESET: to clear the port pin* @arg Bit_SET: to set the port pin* @retval None*/
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal)
{/* Check the parameters */assert_param(IS_GPIO_ALL_PERIPH(GPIOx));assert_param(IS_GET_GPIO_PIN(GPIO_Pin));assert_param(IS_GPIO_BIT_ACTION(BitVal)); if (BitVal != Bit_RESET){GPIOx->BSRR = GPIO_Pin;}else{GPIOx->BRR = GPIO_Pin;}
}/*** @brief Writes data to the specified GPIO data port.* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.* @param PortVal: specifies the value to be written to the port output data register.* @retval None*/
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal)
{/* Check the parameters */assert_param(IS_GPIO_ALL_PERIPH(GPIOx));GPIOx->ODR = PortVal;
}/*** @brief Reads the specified input port pin.* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.* @param GPIO_Pin: specifies the port bit to read.* This parameter can be GPIO_Pin_x where x can be (0..15).* @retval The input port pin value.*/
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{uint8_t bitstatus = 0x00;/* Check the parameters */assert_param(IS_GPIO_ALL_PERIPH(GPIOx));assert_param(IS_GET_GPIO_PIN(GPIO_Pin)); if ((GPIOx->IDR & GPIO_Pin) != (uint32_t)Bit_RESET){bitstatus = (uint8_t)Bit_SET;}else{bitstatus = (uint8_t)Bit_RESET;}return bitstatus;
}/*** @brief Reads the specified GPIO input data port.* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.* @retval GPIO input data port value.*/
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx)
{/* Check the parameters */assert_param(IS_GPIO_ALL_PERIPH(GPIOx));return ((uint16_t)GPIOx->IDR);
}/*** @brief Reads the specified output data port bit.* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.* @param GPIO_Pin: specifies the port bit to read.* This parameter can be GPIO_Pin_x where x can be (0..15).* @retval The output port pin value.*/
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{uint8_t bitstatus = 0x00;/* Check the parameters */assert_param(IS_GPIO_ALL_PERIPH(GPIOx));assert_param(IS_GET_GPIO_PIN(GPIO_Pin)); if ((GPIOx->ODR & GPIO_Pin) != (uint32_t)Bit_RESET){bitstatus = (uint8_t)Bit_SET;}else{bitstatus = (uint8_t)Bit_RESET;}return bitstatus;
}/*** @brief Reads the specified GPIO output data port.* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.* @retval GPIO output data port value.*/
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx)
{/* Check the parameters */assert_param(IS_GPIO_ALL_PERIPH(GPIOx));return ((uint16_t)GPIOx->ODR);
}
3.小结
3.1 理论总结
1.GPIO在APB2时钟下,使用前要使能该时钟。
2.GPIO的基本使用过程中的几个常用的寄存器:
端口配置寄存器(CRL和CRH)用来配置IO引脚(pin)的模式、速度。
数据寄存器(IDR和ODR)和端口置位/清除位寄存器(BSRR和BRR)用来设置pin、port的值和读取pin、port的值。
3.2 使用总结
1.调用RCC_APB2PeriphClockCmd( )函数使能IO时钟。
2.定义一个 GPIO_InitTypeDef 型结构体变量,并配置要初始化的IO参数。
3.通过GPIO_Init( )函数使用配置好的GPIO_InitTypeDef 类型的变量初始化IO。
4.使用2.4节的函数操作IO。
STM32-GPIO的配置和使用相关推荐
- STM32 GPIO的配置寄存器(CRL、CRH)输入输出模式配置
STM32 GPIO的配置寄存器(CRL.CRH)输入输出模式配置 1.学会使用寄存器设定所需IO的方向,学会配置CRL.CRH 2.理解如下代码的含义 //IO方向设置 #define DS18B2 ...
- STM32 GPIO的配置寄存器(CRL、CRH)快速学习
1.问题 在使用STM32的时候配置GPIO是最常见的操作,可以使用比较简单明白的库函数配置,但很繁杂.使用寄存器的方式可以快速配置,对于同一个IO口的输入输出都需要使用到的时候,比如IIC通讯的SD ...
- STM32 GPIO 寄存器配置
一.CRH和CRL的使用:fficeffice" /> CRH和CRL的使用基本相同,CRH用于控制GPIOX(X表示A---G)的高8位(Pin15---Pin8),而CRL用于控制 ...
- STM32 GPIO的原理、特性、选型和配置
目录 1.基本结构 2.4种输入模式 3.4种输出模式 4.GPIO选型和配置 1.基本结构 STM32 GPIO是通用输入/输出端口的英文简称,其可实现输入.输出.驱动.通信等功能,STM32的I/ ...
- STM32低功耗模式下GPIO如何配置最节能?
目录 1.将未使用的GPIO 配置为模拟输入模式 2.调节GPIO 速度 3.GPIO不使用时禁用寄存器时钟 4.避免悬空未使用的引脚 STM32低功耗模式下GPIO如何配置最节能,这里总结了一下四点 ...
- 关于STM32 GPIO配置基础概括
一.词汇表 1.介绍常用词的定义: 缩略词 包含定义 AMR 绝对最大额定值(ABSOLUTE MAXIMUM RATINGS 更多地人称为: ABS) GPIO 通用输入/输出 GP 通用 P 推挽 ...
- STM32——GPIO(2)
STM32--GPIO 宗旨:技术的学习是有限的,分享的精神是无限的. /* GPIO_InitTypeDef结构体 */ typedef enum {GPIO_Speed_10MHz = 1, // ...
- STM32——GPIO(1)
STM32--GPIO 宗旨:技术的学习是有限的,分享的精神是无限的. [对单片机的操作就是控制IO口] 一.GPIO(通用输入输出口) 1.选定需要的引脚(对应哪一个IO口): 2.配置需要的功能( ...
- stm32串口_【单片机】STM32串口基本配置
1 时钟使能(用到哪个串口和GPIO要把相应的时钟开启): 2 串口复位:(一般在系统刚开始配置外设的时候,都会先执行复位该外设的操作.) 3 GPIO口配置: 4 串口参数配置: 5 根据需要开启 ...
- STM32:GPIO配置说明
最近在看数据手册的时候,发现在Cortex-M3里,对于GPIO的配置种类有8种之多: (1)GPIO_Mode_AIN 模拟输入 (2)GPIO_Mode_IN_FLOATING 浮空输入 (3) ...
最新文章
- 第六周实践作业:软件测试和评估
- 边界都是1的最大正方形大小
- 10位IT领袖给应届毕业生的10条忠告
- 腾讯面试Android必问11题,我说的,不信就来看看
- layuimini 图标颜色便捷指定
- layui单选框verify_layui 单选框选中事件
- ss命令,显示socket状态
- 【小错误】ORA-00265: instance recovery required, cannot set ARCHIVELOG mode
- 在datasnap 中使用unidac 访问数据(客户端)
- 零基础学python实战-苦苦发愁学习Python?让你享受 7天 掌握Python的感觉
- Echarts 地图绘制
- 实现最小宽度的几种方法及CSS Expression
- 《数据结构》C语言版 (清华严蔚敏考研版) 全书知识梳理
- 连表时数据量翻倍问题
- 2022年web前端面试题
- 【软件体系结构】软件体系结构风格
- html中元素的几种居中方法
- mysql实现跨库多表查询
- 常见不透明度16进制转换
- ResultSet.next() 速度慢 怎么办
热门文章
- 腾讯随星播 v2.2.1 官方版​
- cheak之十一月最新版
- adb工具+使用adb安装apk
- arcgis栅格数据绘制等值线_ArcGIS教程:绘制等值线的工作原理
- 东北大学软件项目管理与过程改进题库——首字母排序
- c4d安装oc后打开计算机丢失,c4d+oc的安装及使用的全过程
- 数学建模系列--插值算法
- vue 3 引入百度地图api
- 火遍全网的2000款热门短视频剪辑素材+经典音效包素材来了,还不快收下
- linux中怎么粘贴复制文件路径,如何在Linux中复制文件和目录