【小项目】STM32环境监测 | MQ2可燃气体传感器+雨滴传感器+DHT11温湿度传感器+OLED屏幕
目录
- 概述
- 固件编写
- DHT11温湿度传感器
- 概述
- 代码
- MQ2可燃气体传感器和雨滴传感器
- 概述
- ADC外设
- 代码
- OLED屏幕
- 概述
- 代码
- main.c文件
- 概述
- 代码
- 总结
- 项目代码下载
概述
前些阵子参加了广东省电赛,因为疫情的原因比赛不能在线下进行,甚至连回学校调试也不行,于是乎就水了一个省三。
备赛的时候,队长给我布置了这个小项目,说有可能会用在比赛的作品中,但实际就不知道了,所以在这里分享一下代码。
固件编写
这个需求对性能要求不高,像人见人爱、人手一个的STM32F103C8T6也能胜任,但因为我没带回家,所以用了野火的霸道V2开发板。
这块开发板用的是STM32F103ZET6芯片。
DHT11温湿度传感器
概述
温湿度传感器玩过单片机的小伙伴都应该特别熟悉了,在这里就不再赘述了。但还是放几张时序图解释一下。
总体来说DHT11是串行通信,只用一根数据线进行通信,通信的形式有点像IIC,都是先给一个响应信号,然后传感器应答后开始传输数据,直到从机或主机发送结束信号。
下面是主机发送响应信号的时序。
从机接收到主机的响应信号后会按以下时序产生应答信号,表示接受响应。
实际发送的数据都是以一低一高的形式表示,“0”和“1”的区别在于高电平的持续时间,利用这一点主机可以区分“0”和“1”比特。
代码
下面是接收一个字节和接收温湿度数据的代码:
/* * 从DHT11读取一个字节,MSB先行*/
static uint8_t DHT11_ReadByte ( void )
{uint8_t i, temp=0;for(i=0;i<8;i++) { /*每bit以50us低电平标置开始,轮询直到从机发出 的50us 低电平 结束*/ while(DHT11_Dout_IN() == RESET);/*DHT11 以26~28us的高电平表示“0”,以70us高电平表示“1”,*通过检测 x us后的电平即可区别这两个状 ,x 即下面的延时 */DHT11_DELAY_10US(4); //延时x us 这个延时需要大于数据0持续的时间即可 if(DHT11_Dout_IN() == SET)/* x us后仍为高电平表示数据“1” */{/* 等待数据1的高电平结束 */while(DHT11_Dout_IN() == SET);temp|=(uint8_t)(0x01<<(7-i)); //把第7-i位置1,MSB先行 }else // x us后为低电平表示数据“0”{ temp&=(uint8_t)~(0x01<<(7-i)); //把第7-i位置0,MSB先行}}return temp;}/** 一次完整的数据传输为40bit,高位先出* 8bit 湿度整数 + 8bit 湿度小数 + 8bit 温度整数 + 8bit 温度小数 + 8bit 校验和 */
uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef *DHT11_Data)
{ /*输出模式*/DHT11_Mode_Out_PP();/*主机拉低*/DHT11_Dout_0;/*延时18ms*/DHT11_DELAY_MS(18);/*总线拉高 主机延时30us*/DHT11_Dout_1; DHT11_DELAY_10US(3); //延时30us/*主机设为输入 判断从机响应信号*/ DHT11_Mode_IPU();/*判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行*/ if(DHT11_Dout_IN() == RESET) {/*轮询直到从机发出 的80us 低电平 响应信号结束*/ while(DHT11_Dout_IN() == RESET);/*轮询直到从机发出的 80us 高电平 标置信号结束*/while(DHT11_Dout_IN() == SET);/*开始接收数据*/ DHT11_Data->humi_int= DHT11_ReadByte();DHT11_Data->humi_deci= DHT11_ReadByte();DHT11_Data->temp_int= DHT11_ReadByte();DHT11_Data->temp_deci= DHT11_ReadByte();DHT11_Data->check_sum= DHT11_ReadByte();/*读取结束,引脚改为输出模式*/DHT11_Mode_Out_PP();/*主机拉高*/DHT11_Dout_1;/*检查读取的数据是否正确*/if(DHT11_Data->check_sum == DHT11_Data->humi_int + DHT11_Data->humi_deci + DHT11_Data->temp_int+ DHT11_Data->temp_deci)return SUCCESS;else return ERROR;}elsereturn ERROR;}
MQ2可燃气体传感器和雨滴传感器
概述
因为可燃气体检测和雨滴感应的传感器原理较相似,所以放到一起讲了。
可燃气体传感器用的是MQ2。
下面是雨滴模块的样子(简单到连名字都没有)
两个模块都是用模拟信号通信,所以使用STM32的ADC外设就可以轻松读取数据。
ADC外设
根据STM32的用户手册知道我们使用的这款芯片有3个ADC外设,为了让单片机能更快处理转换模拟信号,所以使用了双ADC模式;为了让我们能随时调整采样的时间,我还使用了ADC外设的外部触发功能;为了保证数据传输的效率我还使用了DMA进行传输。
解释一下双ADC模式,通俗讲就是正常是一个ADC处理2个模拟信号的转换,现在2个ADC分别负责2个模拟信号的转换,并且是硬件控制同时开始转换的,因此效率会高很多。
STM32支持的双ADC模式有好几个,具体可参考用户文档,在这里我们使用最常用的同步规则模式即可。
但需要注意的是双ADC模式只能使用ADC1和ADC2外设
代码
接下来放核心代码吧,对于STM32的ADC玩法还挺多的,计划在另外写一篇文章来讲一下。
adc.c文件:
#include "adc/adc.h"static uint32_t ADC_RAW_DATA = 0;void ADC_Config(void)
{/* DMA初始化 */DMA_InitTypeDef DMA_Init_Struct = {0};RCC_AHBPeriphClockCmd(DMA_PERI_CLK_PORT, ENABLE);DMA_DeInit(ADC_DMA_CHAL);DMA_Init_Struct.DMA_PeripheralBaseAddr = ADC1_DR_Address; // 外设基地址DMA_Init_Struct.DMA_MemoryBaseAddr = (uint32_t)&ADC_RAW_DATA; // 内存基地址DMA_Init_Struct.DMA_DIR = DMA_DIR_PeripheralSRC; // 外设到内存DMA_Init_Struct.DMA_BufferSize = 1; // 数据块数量DMA_Init_Struct.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 关闭外设地址自增DMA_Init_Struct.DMA_MemoryInc = DMA_MemoryInc_Disable; // 关闭内存地址自增DMA_Init_Struct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; // 字DMA_Init_Struct.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; // 字DMA_Init_Struct.DMA_Mode = DMA_Mode_Circular; // 循环模式DMA_Init_Struct.DMA_Priority = DMA_Priority_High; // 优先级高DMA_Init_Struct.DMA_M2M = DMA_M2M_Disable; // 关闭内存至内存模式DMA_Init(ADC_DMA_CHAL, &DMA_Init_Struct);DMA_Cmd(ADC_DMA_CHAL, ENABLE);DMA_ClearFlag(DMA1_FLAG_TC1);/* 初始化计时器 */TIM_TimeBaseInitTypeDef TIM_BaseInit_Struct = {0};RCC_APB1PeriphClockCmd(TIM_PERI_CLK_PORT, ENABLE);TIM_BaseInit_Struct.TIM_ClockDivision = TIM_CKD_DIV1; // 输入捕获才用到,默认值即可TIM_BaseInit_Struct.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数TIM_BaseInit_Struct.TIM_Period = TIM_PERIOD_VAL; // 周期,即在(1 / 2kHz) * (TIM_PERIOD_VAL + 1) = CONV_TIME(ms)后产生上溢,这也是ADC的触发周期TIM_BaseInit_Struct.TIM_Prescaler = (36000 - 1); // 预分频,即分频后的时钟频率为72Mhz / (35999 + 1) = 2kHzTIM_BaseInit_Struct.TIM_RepetitionCounter = 0; // 不使用重装载寄存器TIM_TimeBaseInit(TIM_PORT, &TIM_BaseInit_Struct);TIM_SelectOutputTrigger(TIM_PORT, TIM_TRGOSource_Update); // 使能输出触发TIM_ClearFlag(TIM_PORT, TIM_FLAG_Update);/* 初始化ADC */ADC_InitTypeDef ADC_Init_Struct = {0};RCC_APB2PeriphClockCmd(MQ2_ADC_PERI_CLK_PORT | WaterSensor_ADC_PERI_CLK_PORT, ENABLE);RCC_ADCCLKConfig(RCC_PCLK2_Div6); // ADC 6分频,即采样频率为72 / 6 = 12MHzADC_Init_Struct.ADC_ContinuousConvMode = DISABLE; // 关闭连续采样模式ADC_Init_Struct.ADC_DataAlign = ADC_DataAlign_Right; // 数据右对齐ADC_Init_Struct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T3_TRGO; // ADC1外部触发,由计时器3 TRGO事件负责ADC_Init_Struct.ADC_Mode = ADC_Mode_RegSimult; // 同步扫描模式ADC_Init_Struct.ADC_NbrOfChannel = 1; // 1个通道ADC_Init_Struct.ADC_ScanConvMode = DISABLE; // 关闭扫描模式ADC_Init(MQ2_ADC_PORT, &ADC_Init_Struct);ADC_Init_Struct.ADC_ContinuousConvMode = DISABLE; // 关闭连续采样模式ADC_Init_Struct.ADC_DataAlign = ADC_DataAlign_Right; // 数据右对齐ADC_Init_Struct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // ADC2关闭外部触发ADC_Init_Struct.ADC_Mode = ADC_Mode_RegSimult; // 同步扫描模式ADC_Init_Struct.ADC_NbrOfChannel = 1; // 1个通道ADC_Init_Struct.ADC_ScanConvMode = DISABLE; // 关闭扫描模式ADC_Init(WaterSensor_ADC_PORT, &ADC_Init_Struct);ADC_DMACmd(MQ2_ADC_PORT, ENABLE); // 使能ADC DMA功能ADC_Cmd(MQ2_ADC_PORT, ENABLE);ADC_Cmd(WaterSensor_ADC_PORT, ENABLE);ADC_ExternalTrigConvCmd(MQ2_ADC_PORT, ENABLE); // 使能ADC1外部触发转换ADC_ExternalTrigConvCmd(WaterSensor_ADC_PORT, ENABLE); // 使能ADC2外部触发转换/* 转换时间 (1 / 12MHz) * (55.5 + 12.5) ≈ 5.7us */ADC_RegularChannelConfig(MQ2_ADC_PORT, MQ2_ADC_CHAL, 1, ADC_SampleTime_55Cycles5);ADC_RegularChannelConfig(WaterSensor_ADC_PORT, WaterSensor_ADC_CHAL, 1, ADC_SampleTime_55Cycles5);ADC_ResetCalibration(MQ2_ADC_PORT); // 复位ADC1while(ADC_GetResetCalibrationStatus(MQ2_ADC_PORT));ADC_StartCalibration(MQ2_ADC_PORT); // 校正ADC1while(ADC_GetCalibrationStatus(MQ2_ADC_PORT));ADC_ResetCalibration(WaterSensor_ADC_PORT); // 复位ADC2while(ADC_GetResetCalibrationStatus(WaterSensor_ADC_PORT));ADC_StartCalibration(WaterSensor_ADC_PORT); // 校正ADC2while(ADC_GetCalibrationStatus(WaterSensor_ADC_PORT));TIM_Cmd(TIM_PORT, ENABLE); // 开启计时器,开启ADC转换
}uint16_t ADC_GetMQ2RawData(void)
{uint32_t tmp = ADC_RAW_DATA;return (uint16_t)(tmp & 0x0000ffff);
}uint16_t ADC_GetWaterSensorRawData(void)
{uint32_t tmp = ADC_RAW_DATA;return (uint16_t)(tmp >> 16);
}
adc.h文件:
/* 相关配置 */
#define CONV_TIME 100 // 采样周期,单位ms/* 其他宏定义 */
#define TIM_PERIOD_VAL (CONV_TIME * 2 - 1)/* 管脚宏定义 */
#define TIM_PORT TIM3
#define TIM_PERI_CLK_PORT RCC_APB1Periph_TIM3#define DMA_PERI_CLK_PORT RCC_AHBPeriph_DMA1
#define ADC1_DR_Address ((uint32_t)0x4001244C)
#define ADC_DMA_CHAL DMA1_Channel1void ADC_Config(void);
uint16_t ADC_GetMQ2RawData(void);
uint16_t ADC_GetWaterSensorRawData(void);
OLED屏幕
概述
OLED屏幕应该也有很多小伙伴玩过了。
这个屏幕的通信方式有挺多种的,比如说8080时序、IIC、SPI,具体是哪种通信方式要看买的时候商家的说明。
我买的这个是IIC的接口,我使用了硬件IIC对其通信。
代码
简单贴一下代码:
碍于篇幅就只放初始化和传输一个字节的代码吧。
/*** @brief 初始化OLED针脚* @param None* @retval None*/
static void OLED_GPIO_Init(void)
{GPIO_InitTypeDef GPIO_Init_Struct;RCC_APB2PeriphClockCmd(OLED_PERI_CLK, ENABLE);GPIO_Init_Struct.GPIO_Mode = GPIO_Mode_AF_OD;GPIO_Init_Struct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init_Struct.GPIO_Pin = OLED_SCL_PIN;GPIO_Init(OLED_SCL_PORT, &GPIO_Init_Struct);GPIO_Init_Struct.GPIO_Pin = OLED_SDA_PIN;GPIO_Init(OLED_SDA_PORT, &GPIO_Init_Struct);RCC_APB1PeriphClockCmd(IIC_PERI_CLK, ENABLE);I2C_InitTypeDef I2C_Init_Struct;I2C_Init_Struct.I2C_Ack = I2C_Ack_Enable; // 使能ACkI2C_Init_Struct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; // 7位从机地址I2C_Init_Struct.I2C_ClockSpeed = 1000000; // 速度100kHzI2C_Init_Struct.I2C_DutyCycle = I2C_DutyCycle_2;I2C_Init_Struct.I2C_Mode = I2C_Mode_I2C;I2C_Init_Struct.I2C_OwnAddress1 = 0x00; // STM32自己的地址,任意值即可I2C_Init(IIC_PORT, &I2C_Init_Struct);I2C_Cmd(IIC_PORT, ENABLE);
}/*** @brief 初始化SSD1306* @param None* @retval None*/
void OLED_Init(void)
{OLED_GPIO_Init();OLED_SendCmd(0xAE);//--turn off oled panelOLED_SendCmd(0x00);//---set low column addressOLED_SendCmd(0x10);//---set high column addressOLED_SendCmd(0x40);//--set start line address Set Mapping RAM Display Start Line (0x00~0x3F)OLED_SendCmd(0x81);//--set contrast control registerOLED_SendCmd(0xCF); // Set SEG Output Current BrightnessOLED_SendCmd(0xA1);//--Set SEG/Column Mapping 0xa0左右反置 0xa1正常OLED_SendCmd(0xC8);//Set COM/Row Scan Direction 0xc0上下反置 0xc8正常OLED_SendCmd(0xA6);//--set normal displayOLED_SendCmd(0xA8);//--set multiplex ratio(1 to 64)OLED_SendCmd(0x3f);//--1/64 dutyOLED_SendCmd(0xD3);//-set display offset Shift Mapping RAM Counter (0x00~0x3F)OLED_SendCmd(0x00);//-not offsetOLED_SendCmd(0xd5);//--set display clock divide ratio/oscillator frequencyOLED_SendCmd(0x80);//--set divide ratio, Set Clock as 100 Frames/SecOLED_SendCmd(0xD9);//--set pre-charge periodOLED_SendCmd(0xF1);//Set Pre-Charge as 15 Clocks & Discharge as 1 ClockOLED_SendCmd(0xDA);//--set com pins hardware configurationOLED_SendCmd(0x12);OLED_SendCmd(0xDB);//--set vcomhOLED_SendCmd(0x40);//Set VCOM Deselect LevelOLED_SendCmd(0x20);//-Set Page Addressing Mode (0x00/0x01/0x02)OLED_SendCmd(0x02);//OLED_SendCmd(0x8D);//--set Charge Pump enable/disableOLED_SendCmd(0x14);//--set(0x10) disableOLED_SendCmd(0xA4);// Disable Entire Display On (0xa4/0xa5)OLED_SendCmd(0xA6);// Disable Inverse Display On (0xa6/a7) OLED_SendCmd(0xAF);//--turn on oled panelOLED_SendCmd(0xAF); /*display ON*/OLED_Clear();OLED_Set_Pos(0,0);
}/*** @brief 向SSD1106写入一个字节* @param dat 要写入的数据/命令* @param cmd 数据/命令标志 0,表示命令;1,表示数据* @retval*/
static void OLED_WR_Byte(uint8_t dat, uint8_t cmd)
{// FlagStatus bitstatus = RESETwhile (I2C_GetFlagStatus(IIC_PORT, I2C_FLAG_BUSY)); // 检查I2C总线是否繁忙 I2C_GenerateSTART(IIC_PORT, ENABLE); // 打开IIC总线// ErrorStatus status = ERROR, ERROR是个枚举类型, 值为0 while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); // 检查总线是否打开I2C_Send7bitAddress(IIC_PORT, IIC_ADDR, I2C_Direction_Transmitter); // 配置STM32的IIC设备自己的地址,每个连接到IIC总线上的设备都有一个自己的地址,作为主机也不例外。while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); // 检查地址是否发送if (cmd) I2C_SendData(IIC_PORT, 0x40); // 进入数据模式else I2C_SendData(IIC_PORT, 0x00); // 进入命令模式while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING)); // 等待发送数据完成I2C_SendData(IIC_PORT, dat); //发送数据while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING)); // 等待发送数据完成I2C_GenerateSTOP(IIC_PORT, ENABLE); // 关闭IIC总线
}
main.c文件
概述
应队长的要求这个小项目用了FreeRTOS系统,但实际上除了用到最基本的任务调度外,其他的功能都没有用到。
至于FreeRTOS系统的移植网上都有好多的教程了,这里就不赘述了。
简单说主任务做的就是一段时间后切换OLED屏幕的显示内容(因为一块OLED屏幕显示不了所有传感器的数据)
代码
简单贴一下代码:
static void MainTask(void* params)
{uint8_t status = 0;while(1){if (status){DHT11_Read_TempAndHumidity(&dht11_data);OLED_ShowTempAndHumi(dht11_data.temp_int, dht11_data.temp_deci, dht11_data.humi_int, dht11_data.humi_deci);printf("Displaying temperature and humidity\n");}else{OLED_ShowPpmAndWaterLevel(MQ2_GetPPM(), WaterSensor_GetWaterLevel());printf("Displaying PPM and water level\n");}status = !status;vTaskDelay(2000);}
}static void AppInitTask(void* params)
{taskENTER_CRITICAL(); // 进入临界段NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);USART_Config();MQ2_Init();WaterSensor_Init();ADC_Config();TIMER_Init();DHT11_Init();OLED_Init();printf("Init completed\n");vTaskDelay(100);xTaskCreate(MainTask, "MainTask", 1024, NULL, 5, NULL);printf("Main task created\n");vTaskDelete(NULL); // 删除这个任务taskEXIT_CRITICAL(); // 退出临界段
}/*** @brief 主函数* @param None* @retval None*/
int main(void)
{BaseType_t xReturn = pdPASS;xReturn = xTaskCreate(AppInitTask, "AppInitTask", 1024, NULL, 5, NULL);if (xReturn == pdPASS) vTaskStartScheduler(); // 开启任务调度else while(1);
}
总结
总的来说,这个项目还是蛮适合对STM32已经入门然后想进阶的小伙伴。
项目包含了对各种常见模块的代码撰写,每种模块对应的通信协议、用到的外设也不尽相同;项目还涉及了对FreeRTOS系统的基本移植和使用,对于想进阶STM32的小伙伴是非常好的。
项目代码下载
链接:https://download.csdn.net/download/JackieCoo/86506760
【小项目】STM32环境监测 | MQ2可燃气体传感器+雨滴传感器+DHT11温湿度传感器+OLED屏幕相关推荐
- 【STM32 Net MF开发板学习-19】DHT11温湿度传感器通信(上)
前段时间开发远程医疗系统(Dr.Cloud)就曾用到过温湿度传感器,不过当时考虑到集成难度,选了一个RS485接口的传感器,该传感器实现了Modbus Rtu Slave的功能,只要客户程序实现Mod ...
- 【STM32 .Net MF开发板学习-19】DHT11温湿度传感器通信(上)
前段时间开发远程医疗系统(Dr.Cloud)就曾用到过温湿度传感器,不过当时考虑到集成难度,选了一个RS485接口的传感器,该传感器实现了Modbus Rtu Slave的功能,只要客户程序实现Mod ...
- 基于STM32单片机的多功能智能时钟【DHT11温湿度传感器蜂鸣器报警12864液晶显示】
系统功能 系统可以显示日期.时间.星期.温度.湿度,可以对日期时间进行设置,可以设置闹钟,可以打开和关闭背光显示,有两种计时模式:正计时和倒计时. 液晶显示界面
- 【MQ-2 可燃气体和烟雾传感器与 Arduino 配合使用】
MQ-2 可燃气体和烟雾传感器与 Arduino 配合使用 前言 MQ-2 气体传感器引脚 MQ-2 气体和烟雾传感器模块组成 MQ-2 气体传感器模块如何工作? MQ-2 可燃气体传感器模块常见问题 ...
- 51单片机 DHT11温湿度传感器 MQ2传感器
目录 前言 程序思路 DHT11 一.DHT11基础储备 二.接口说明 三.协议及数据格式 编辑 四.DHT11代码 MQ-2烟雾传感器 一.MQ-2烟雾传感器介绍 二.工作原理 三.时序配置 四. ...
- STM32读取MQ4传感器、DHT11温湿度传感器、GP2Y1014AU0F夏普光学灰尘传感器数据
1.功能 STM32测量MQ4.灰尘传感器.DHT11温湿度传感器,并在TFT上显示,超过浓度阈值蜂鸣器报警. 使用普中STM32F103ZET6开发板+2.8寸触摸屏. 2.MQ4天然气传感器 MQ ...
- 玩转传感器——DHT11温湿度传感器(STM32版)
玩转传感器--DHT11温湿度传感器(STM32版) 文章目录 玩转传感器--DHT11温湿度传感器(STM32版) 前言 一.接口说明 1 接线图 2 电源引脚 3 串行接口(单线双向) 二.通信过 ...
- 基于STM32的DHT11温湿度传感器设计
文章目录 前言 一.DHT11温湿度传感器是什么? 二.DHT11驱动程序详解 1.相关宏定义 2.输入输出GPIO配置 2.GPIO初始化设计 3.检测DHT11是否正常工作 4.读取DHT11数据 ...
- 嵌入式设计与开发项目-DHT11温湿度传感器程序设计
嵌入式设计与开发项目-DHT11温湿度传感器程序设计 一.实现的功能 二.根据功能实现代码 1.主文件main.c 2.DHT11温湿度的头文件"dht11.h" 3.DHT11温 ...
- Esp8266 进阶之路19 【外设篇①】esp8266驱动 ds18b20、dht11 温湿度传感器,采集温湿度传感器到服务器。(附带Demo)
本系列博客学习由非官方人员 半颗心脏 潜心所力所写,不做开发板.仅仅做个人技术交流分享,不做任何商业用途.如有不对之处,请留言,本人及时更改. 序号 SDK版本 内容 链接 1 nonos2.0 搭建 ...
最新文章
- 【转】多语言的正则表达式,我们应该掌握
- es6基础0x012:Map
- CCNA-Cisco-Packet-Tracerchs(思科官网)安装教程以及使用
- kindeditor自定义插件插入视频代码
- 硬盘整数分区大小计算公式(硬盘分区计算)
- 宝塔 无法自动认证,请填写本地服务器的登录信息
- 癌症病人不让吃鸡蛋,癌症病人营养要如何补充?
- 蚂蚁金服java二面_蚂蚁金服Java开发二面
- Kubernetes中配置Pod的liveness和readiness探针
- 路由器克隆电脑mac地址,破解电脑连接固定网线ip
- 浅谈计算机专业的毕业生如何提高自身素质
- 基于历史使用数据的虚拟机动态整合研究( 文献阅读与问题理解)
- Git develop分支的一些操作
- UTC与BJT时间换算C语言
- 架构师的5大基本能力
- 你真的了解promise.resolve()吗
- Power BI----DAX讲解
- H.264是什么?H.265是什么?视频码率是什么?了解视频原理
- 一个手机游戏服务器的架构
- 在ios桌面添加web站点图标及增加启动画面
热门文章
- 系泊系统设计建模matlab程序,系泊系统设计-数学建模论文.docx
- arcgis desktop10.2(arcmap)安装教程,已成功安装
- ArcMap图例横放教程
- 华为交换机修改radius服务器地址,华为交换机radius认证-组网配置:pc+华为三层交换机+radius服务器(2003系统),求radius服务器的配置...
- 如何使用EDI系统解决对接多工厂的问题?
- 2.PCIe协议分析
- 极限学习机 matlab,深度极限学习机的研究笔记
- 计算机应用基础实操题怎么操,计算机基础实操试题
- python学习第十弹:宝可梦数据分析-平民最强
- C++课程设计班级管理系统