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

《基于stm32的智慧家居基础项目》

智慧家居

开发文档:
OneNet开发文档

系统架构设计

首先我想先通过一个图片,来说明项目整体框架

在这里插入图片描述

硬件部分

1.按键与LED实现开关功能

LED驱动代码

#include "led.h"
uint8_t led_sta=0;
void led_init(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOC,&GPIO_InitStructure);GPIO_SetBits(GPIOC,GPIO_Pin_13);
}
void led_turn(void)
{if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_13)==1){GPIO_ResetBits(GPIOC,GPIO_Pin_13);led_sta=1;	}else{GPIO_SetBits(GPIOC,GPIO_Pin_13);led_sta=0;}
}
void led_off(void)
{GPIO_SetBits(GPIOC,GPIO_Pin_13);led_sta=0;
}void led_on(void)
{GPIO_ResetBits(GPIOC,GPIO_Pin_13);led_sta=1;
}

Key驱动代码

疑点解析:

  1. 我这里用的是外部中断实现的
  2. 上拉输入就是默认是高电平1,比如我有个按键,按下就是0,如果是下拉输入,默认是0,按下是1
  3. EXTI9_5_IRQHandler(void)是触发中断要执行的功能
#include "key.h"void key_init(void)
{GPIO_InitTypeDef my_key_init;EXTI_InitTypeDef my_exti_init;NVIC_InitTypeDef my_nvic_init;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//开启gpio口时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开启外部中断AFIO时钟//gpio初始化my_key_init.GPIO_Mode=GPIO_Mode_IPU;//上拉输入my_key_init.GPIO_Speed=GPIO_Speed_50MHz;my_key_init.GPIO_Pin=GPIO_Pin_6;GPIO_Init(GPIOA,&my_key_init);//AFIO初始化GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource6);//EXTI初始化my_exti_init.EXTI_Line = EXTI_Line6;             // 选择中断线 6,对应 GPIO 的第 6 号引脚my_exti_init.EXTI_LineCmd = ENABLE;              // 使能这条中断线my_exti_init.EXTI_Mode = EXTI_Mode_Interrupt;    // 中断模式(不是事件)my_exti_init.EXTI_Trigger = EXTI_Trigger_Falling;// 触发方式:下降沿触发EXTI_Init(&my_exti_init);                        // 调用库函数初始化//NVIC初始化//设置优先级my_nvic_init.NVIC_IRQChannel=EXTI9_5_IRQn;my_nvic_init.NVIC_IRQChannelCmd=ENABLE;my_nvic_init.NVIC_IRQChannelPreemptionPriority=2;my_nvic_init.NVIC_IRQChannelSubPriority=2;NVIC_Init(&my_nvic_init);}void EXTI9_5_IRQHandler(void)
{if (EXTI_GetITStatus(EXTI_Line6) != RESET)  // 判断是否真的是 EXTI6 触发的中断{if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6) == 0){DelayMs(20);  // 简单消抖while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6) == 0);DelayMs(20);led_turn();  // 执行你的功能函数}EXTI_ClearITPendingBit(EXTI_Line6);  // 清除中断标志,避免重复进入中断}
}

OLED驱动我采用的是江科大的驱动代码,这里不写出了

2.温度与光照传感器模块

这里主要是adc初始化、adc转化温度光照值

#include "waishe.h"
#include <math.h>#define R1 10000.0f      // NTC分压电阻阻值 10kΩ
#define B 3950.0f        // NTC B值
#define R0 10000.0f      // NTC 25℃时阻值
#define T0 298.15f       // 25℃开尔文温度
#define R2 10000.0f      // LDR分压电阻阻值 10kΩ
#define ADC_REF 3.3f     // ADC参考电压
#define ADC_MAX 4095.0f  // 12位ADC最大值void waishe_init(void)
{GPIO_InitTypeDef gpio;ADC_InitTypeDef adc;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE);gpio.GPIO_Mode = GPIO_Mode_AIN;gpio.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;GPIO_Init(GPIOA, &gpio);//adc初始化ADC_DeInit(ADC1);adc.ADC_Mode = ADC_Mode_Independent;adc.ADC_ScanConvMode = DISABLE;adc.ADC_ContinuousConvMode = DISABLE;adc.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;adc.ADC_DataAlign = ADC_DataAlign_Right;adc.ADC_NbrOfChannel = 1;ADC_Init(ADC1, &adc);ADC_Cmd(ADC1, ENABLE);ADC_ResetCalibration(ADC1);while (ADC_GetResetCalibrationStatus(ADC1));ADC_StartCalibration(ADC1);while (ADC_GetCalibrationStatus(ADC1));
}uint16_t Read_ADC_Channel(uint8_t channel)
{ADC_RegularChannelConfig(ADC1, channel, 1, ADC_SampleTime_239Cycles5);ADC_SoftwareStartConvCmd(ADC1, ENABLE);while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));return ADC_GetConversionValue(ADC1);
}// 计算NTC温度,返回摄氏度
float calculate_ntc_temperature(uint16_t adc_val)
{float voltage;float resistance;float temp_k;voltage = adc_val * ADC_REF / ADC_MAX;if (voltage == 0) return -273.15f;  // 防止除零错误resistance = (voltage * R1) / (ADC_REF - voltage);temp_k = 1.0f / ( (1.0f / T0) + (1.0f / B) * log(resistance / R0) );return temp_k - 273.15f;  // 转摄氏度
}float calculate_ldr_light_level(uint16_t adc_val)
{float voltage;float resistance;float light_level;voltage = adc_val * ADC_REF / ADC_MAX;if (voltage == 0) return 0.0f;  // 防止除零resistance = (ADC_REF - voltage) * R2 / voltage;light_level = 100000.0f / resistance;if (light_level > 100.0f) light_level = 100.0f;if (light_level < 0.0f) light_level = 0.0f;return light_level;
}void show_info(float *temperature, float *light)
{uint16_t temp_val = Read_ADC_Channel(ADC_Channel_0);   // PA0: NTCuint16_t light_val = Read_ADC_Channel(ADC_Channel_1);  // PA1: LDR*temperature = calculate_ntc_temperature(temp_val);*light = calculate_ldr_light_level(light_val);OLED_ShowString(1, 1, "Tem:");OLED_ShowNum(1, 5, (int)(*temperature), 2);OLED_ShowString(2, 1, "Light:");OLED_ShowNum(2, 7, (100-(int)(*light)%100), 2);OLED_ShowString(2, 9, "%");if (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_13) == 0){OLED_ShowString(3, 1, "Led_status:On   "); // 注意后面空格}else{OLED_ShowString(3, 1, "Led_status:Off  ");}
}

3.usart通讯模块

Usart1用于ch340通讯
/*
************************************************************
*	函数名称:	Usart1_Init
*
*	函数功能:	串口1初始化
*
*	入口参数:	baud:设定的波特率
*
*	返回参数:	无
*
*	说明:		TX-PA9		RX-PA10
************************************************************
*/
void Usart1_Init(unsigned int baud)
{GPIO_InitTypeDef gpio_initstruct;USART_InitTypeDef usart_initstruct;NVIC_InitTypeDef nvic_initstruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);//PA9	TXDgpio_initstruct.GPIO_Mode = GPIO_Mode_AF_PP;gpio_initstruct.GPIO_Pin = GPIO_Pin_9;gpio_initstruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &gpio_initstruct);//PA10	RXDgpio_initstruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;gpio_initstruct.GPIO_Pin = GPIO_Pin_10;gpio_initstruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &gpio_initstruct);usart_initstruct.USART_BaudRate = baud;usart_initstruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;		//无硬件流控usart_initstruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;						//接收和发送usart_initstruct.USART_Parity = USART_Parity_No;									//无校验usart_initstruct.USART_StopBits = USART_StopBits_1;								//1位停止位usart_initstruct.USART_WordLength = USART_WordLength_8b;							//8位数据位USART_Init(USART1, &usart_initstruct);USART_Cmd(USART1, ENABLE);														//使能串口USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);									//使能接收中断nvic_initstruct.NVIC_IRQChannel = USART1_IRQn;nvic_initstruct.NVIC_IRQChannelCmd = ENABLE;nvic_initstruct.NVIC_IRQChannelPreemptionPriority = 0;nvic_initstruct.NVIC_IRQChannelSubPriority = 2;NVIC_Init(&nvic_initstruct);}
Usart2用于esp和服务器通讯
/*
************************************************************
*	函数名称:	Usart2_Init
*
*	函数功能:	串口2初始化
*
*	入口参数:	baud:设定的波特率
*
*	返回参数:	无
*
*	说明:		TX-PA2		RX-PA3
************************************************************
*/
void Usart2_Init(unsigned int baud)
{GPIO_InitTypeDef gpio_initstruct;USART_InitTypeDef usart_initstruct;NVIC_InitTypeDef nvic_initstruct;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);//PA2	TXDgpio_initstruct.GPIO_Mode = GPIO_Mode_AF_PP;gpio_initstruct.GPIO_Pin = GPIO_Pin_2;gpio_initstruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &gpio_initstruct);//PA3	RXDgpio_initstruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;gpio_initstruct.GPIO_Pin = GPIO_Pin_3;gpio_initstruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &gpio_initstruct);usart_initstruct.USART_BaudRate = baud;usart_initstruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;		//无硬件流控usart_initstruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;						//接收和发送usart_initstruct.USART_Parity = USART_Parity_No;									//无校验usart_initstruct.USART_StopBits = USART_StopBits_1;								//1位停止位usart_initstruct.USART_WordLength = USART_WordLength_8b;							//8位数据位USART_Init(USART2, &usart_initstruct);USART_Cmd(USART2, ENABLE);														//使能串口USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);									//使能接收中断nvic_initstruct.NVIC_IRQChannel = USART2_IRQn;nvic_initstruct.NVIC_IRQChannelCmd = ENABLE;nvic_initstruct.NVIC_IRQChannelPreemptionPriority = 0;nvic_initstruct.NVIC_IRQChannelSubPriority = 0;NVIC_Init(&nvic_initstruct);}
串口函数
/*
************************************************************
*	函数名称:	Usart_SendString
*
*	函数功能:	串口数据发送
*
*	入口参数:	USARTx:串口组
*				str:要发送的数据
*				len:数据长度
*
*	返回参数:	无
*
*	说明:		
************************************************************
*/
void Usart_SendString(USART_TypeDef *USARTx, unsigned char *str, unsigned short len)
{unsigned short count = 0;for(; count < len; count++){USART_SendData(USARTx, *str++);									//发送数据while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET);		//等待发送完成}}/*
************************************************************
*	函数名称:	UsartPrintf
*
*	函数功能:	格式化打印
*
*	入口参数:	USARTx:串口组
*				fmt:不定长参
*
*	返回参数:	无
*
*	说明:		
************************************************************
*/
void UsartPrintf(USART_TypeDef *USARTx, char *fmt,...)
{unsigned char UsartPrintfBuf[296];va_list ap;unsigned char *pStr = UsartPrintfBuf;va_start(ap, fmt);vsnprintf((char *)UsartPrintfBuf, sizeof(UsartPrintfBuf), fmt, ap);							//格式化va_end(ap);while(*pStr != 0){USART_SendData(USARTx, *pStr++);while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == RESET);}}/*
************************************************************
*	函数名称:	USART1_IRQHandler
*
*	函数功能:	串口1收发中断
*
*	入口参数:	无
*
*	返回参数:	无
*
*	说明:		
************************************************************
*/
void USART1_IRQHandler(void)
{if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断{USART_ClearFlag(USART1, USART_FLAG_RXNE);}}

4.esp8266驱动

为了便于后续了解外设各个功能,我这里拆解一下esp的驱动代码

#define REV_OK		0	//接收完成标志
#define REV_WAIT	1	//接收未完成标志

1.初始化

void ESP8266_Init(void)
{ESP8266_Clear();UsartPrintf(USART_DEBUG, "1. AT\r\n");          //u1负责打印到串口助手while(ESP8266_SendCmd("AT\r\n", "OK"))DelayXms(500);UsartPrintf(USART_DEBUG, "2. CWMODE\r\n");while(ESP8266_SendCmd("AT+CWMODE=1\r\n", "OK"))DelayXms(500);UsartPrintf(USART_DEBUG, "3. AT+CWDHCP\r\n");while(ESP8266_SendCmd("AT+CWDHCP=1,1\r\n", "OK"))DelayXms(500);UsartPrintf(USART_DEBUG, "4. CWJAP\r\n");while(ESP8266_SendCmd(ESP8266_WIFI_INFO, "GOT IP"))DelayXms(500);UsartPrintf(USART_DEBUG, "5. ESP8266 Init OK\r\n");}

2.发送esp执行命令

Bool ESP8266_SendCmd(char *cmd, char *res)
{unsigned char timeOut = 200;Usart_SendString(USART2, (unsigned char *)cmd, strlen((const char *)cmd));while(timeOut--){if(ESP8266_WaitRecive() == REV_OK)							//如果收到数据{if(strstr((const char *)esp8266_buf, res) != NULL)		//如果检索到关键词{ESP8266_Clear();									//清空缓存return 0;}}	DelayXms(10);}return 1;
}

3.清空缓存

void ESP8266_Clear(void)
{memset(esp8266_buf, 0, sizeof(esp8266_buf));esp8266_cnt = 0;
}

4.等待响应

Bool ESP8266_WaitRecive(void)
{if(esp8266_cnt == 0) 							//如果接收计数为0 则说明没有处于接收数据中,所以直接跳出,结束函数return REV_WAIT;if(esp8266_cnt == esp8266_cntPre)				//如果上一次的值和这次相同,则说明接收完毕{esp8266_cnt = 0;							//清0接收计数return REV_OK;								//返回接收完成标志}esp8266_cntPre = esp8266_cnt;					//置为相同return REV_WAIT;								//返回接收未完成标志}

5.esp发送数据给服务器

AT+CIPSEND=%d\r\n这是发送数据给服务器的指令,所以下面串口发送的数据不是给esp而是服务器

void ESP8266_SendData(unsigned char *data, unsigned short len)
{char cmdBuf[32];ESP8266_Clear();								//清空接收缓存sprintf(cmdBuf, "AT+CIPSEND=%d\r\n", len);		//发送命令if(!ESP8266_SendCmd(cmdBuf, ">"))				//收到‘>’时可以发送数据{Usart_SendString(USART2, data, len);		//发送设备连接请求数据}
}

6.获取平台返回数据

unsigned char *ESP8266_GetIPD(unsigned short timeOut)
{char *ptrIPD = NULL;do{if(ESP8266_WaitRecive() == REV_OK)								//如果接收完成{ptrIPD = strstr((char *)esp8266_buf, "IPD,");				//搜索“IPD”头if(ptrIPD == NULL)											//如果没找到,可能是IPD头的延迟,还是需要等待一会,但不会超过设定的时间{//UsartPrintf(USART_DEBUG, "\"IPD\" not found\r\n");}else{ptrIPD = strchr(ptrIPD, ':');							//找到':'if(ptrIPD != NULL){ptrIPD++;return (unsigned char *)(ptrIPD);}elsereturn NULL;	}}DelayXms(5);													//延时等待} while(timeOut--);	return NULL;														//超时还未找到,返回空指针
}

通信部分

1.mqtt

​ 这里我们要用到MQTT.fx这一个客户端去进行测试,客户端就是在模拟我们设备(这个项目),去和服务器通讯

你作为客户端程序

  • 想要连服务器 → 调 MQTT_PacketConnect() 组一个 CONNECT 报文,通过 TCP 发送。
  • 想要订阅主题 → 调 MQTT_PacketSubscribe() 组一个 SUBSCRIBE 报文,发给服务器。
  • 想要发消息 → 调 MQTT_PacketPublish() 组一个 PUBLISH 报文,发给服务器。

服务器返回的数据(二进制 MQTT 报文):

  • 收到后先用 MQTT_UnPacketRecv() 或者具体的解包函数,比如 MQTT_UnPacketConnectAck()MQTT_UnPacketPublish() 来解析。
  • 解析出来的结果就是你能在代码里直接用的内容(比如连接是否成功、主题是什么、消息内容是什么)。

小程序部分

先介绍一下

JavaScriptJSON 是两个不同的东西:


JavaScript

  • 是一种编程语言,用来写逻辑、操作网页、调用 API、控制流程等。

  • 例如:

    let name = "Tom";
    function sayHello() {console.log("Hello, " + name);
    }
    sayHello();
    

    👉 这是 JavaScript 代码,能执行。


JSON (JavaScript Object Notation)

  • 是一种 数据格式,长得很像 JavaScript 的对象语法,但只能用来存数据,不能执行逻辑

  • 常用在前后端通信、配置文件里。

  • 例如:

    {"name": "Tom","age": 18,"isStudent": true
    }
    

    👉 这是 JSON,只能存数据,不能像 JavaScript 那样写函数或逻辑。


关系

  • JSON 的语法最早就是从 JavaScript 对象语法演变出来的。

  • 但 JSON 独立于语言,Python、Java、C、Go 等都能读写 JSON。

  • JavaScript 可以很方便地处理 JSON:

    let obj = JSON.parse('{"name":"Tom"}');  // JSON → JS 对象
    console.log(obj.name);let str = JSON.stringify({name: "Tom"}); // JS 对象 → JSON
    console.log(str);
    

👉 所以:

  • JavaScript = 一门编程语言
  • JSON = 一种数据交换格式

Vue 组件的 <script>,功能是:

👉 定时从 OneNET 平台获取设备数据(温度、光照、LED 状态),并能控制 LED 开关。


1. 导入部分

const { createCommonToken } = require('@/key.js')
  • key.js 文件里引入了 createCommonToken 函数。
  • 这个函数用来生成 鉴权 token,请求 OneNET 平台 API 时要带上。

2. data 数据

data() {return {temp: '',   // 温度light: '',  // 光照led: true,  // led状态(布尔值)token: '',  // 鉴权 token}
}

这些变量绑定到页面 <template> 里,用来显示和交互。


3. 生命周期钩子

onLoad() {const params = {author_key: 'xxx',version: '2022-05-01',user_id: '460751',}this.token = createCommonToken(params);
},
  • 页面加载时执行。
  • 传入密钥、版本号、用户 ID,生成 token,保存到 this.token
onShow() {this.fetchDevData();setInterval(() => {this.fetchDevData();}, 3000)
},
  • 页面显示时执行。
  • 先调用一次 fetchDevData() 获取设备数据。
  • 然后每隔 3 秒刷新一次数据,实现 实时监控

4. methods 方法

(1) 获取设备数据
fetchDevData() {uni.request({url: 'https://iot-api.heclouds.com/thingmodel/query-device-property',method: 'GET',data: {product_id: 'ECHECArR1s',device_name: 't1'},header: {'authorization': this.token // 自定义请求头信息},success: (res) => {console.log(res.data);this.led = res.data.data[0].value === 'true';this.light = res.data.data[1].value;this.temp = res.data.data[2].value;}})
}
  • 调用 OneNET 设备属性查询接口,获取 t1 设备的数据。
  • 带上 authorization 头部(token)。
  • 成功后解析返回数据,更新页面的 LED、光照、温度
    • this.led = res.data.data[0].value === 'true'; → 解析出 LED 状态并转成布尔值。
    • this.light = res.data.data[1].value; → 光照数值。
    • this.temp = res.data.data[2].value; → 温度数值。

(2) 控制 LED 开关
on_led(event) {let value = event.detail.value;uni.request({url: 'https://iot-api.heclouds.com/thingmodel/set-device-property',method: 'POST',data: {product_id: 'ECHECArR1s',device_name: 't1',params: {"led": value}},header: {'authorization': this.token},success: () => {console.log();}})
}
  • 当用户在页面点击 <switch> 控件时触发。
  • 获取开关状态 event.detail.value (true / false)。
  • 调用 OneNET 设置设备属性接口,修改 LED 的状态。
  • 请求体里的 params: {"led": value} 告诉服务器要开还是关。

5. 总体流程

  1. 生成 token → 用于鉴权。
  2. 页面加载 → 保存 token。
  3. 页面显示 → 每 3 秒调用一次 OneNET 查询接口,获取设备属性(温度、光照、LED)。
  4. 用户切换开关 → 调用 OneNET 设置接口,控制设备的 LED 灯。


内容还需更新改进,感谢Onenet平台提供的开发文档以及demo,后续可以在此基础添加新的功能


文章转载自:

http://tL7BWgOL.sytzq.cn
http://yfl2GEhT.sytzq.cn
http://CIaYZHTT.sytzq.cn
http://T61vgqip.sytzq.cn
http://jkdJ2MFq.sytzq.cn
http://yowVFa1W.sytzq.cn
http://xpEAhcBG.sytzq.cn
http://5SIUWinI.sytzq.cn
http://7im9zsyV.sytzq.cn
http://vA0KOAtO.sytzq.cn
http://8tQdg94M.sytzq.cn
http://vGUccCk7.sytzq.cn
http://B65HW15w.sytzq.cn
http://nLpwkLF5.sytzq.cn
http://UAoIyJt3.sytzq.cn
http://NoQProG0.sytzq.cn
http://3hHRYCed.sytzq.cn
http://o25Xtfap.sytzq.cn
http://yR4zAXWL.sytzq.cn
http://b7ZU2WWY.sytzq.cn
http://FNNgXsAQ.sytzq.cn
http://wqWNQVfc.sytzq.cn
http://eAzz2fNs.sytzq.cn
http://yiyETEfu.sytzq.cn
http://Ttbspw6R.sytzq.cn
http://0Gub7VKZ.sytzq.cn
http://2EyY876B.sytzq.cn
http://aFA4ryw8.sytzq.cn
http://5vPbi5h3.sytzq.cn
http://2xrzVyyE.sytzq.cn
http://www.dtcms.com/a/369018.html

相关文章:

  • Docker在Windows与Linux系统安装的一体化教学设计
  • sub3G和sub6G的区别和联系
  • 【存储选型终极指南】RustFS vs MinIO:5大维度深度对决,95%技术团队的选择秘密!
  • 【Python基础】 18 Rust 与 Python print 函数完整对比笔记
  • Rust Axum 快速上手指南(静态网页和动态网页2024版)
  • CVPR 2025|无类别词汇的视觉-语言模型少样本学习
  • 9月14日 不见不散|2025年华望M-Design v2软件线上发布会
  • 疯狂星期四文案网第61天运营日记
  • 还在堆模型、拼算力?醒醒吧!你的AI项目99%会死于数据
  • DL3382P6平替RClamp3382P.TCT
  • 硬件基础:串口通信
  • 华为在国内搞的研发基地有多野?标杆游学带你解锁“研发界顶流”
  • LangChain关于提示词的几种写法
  • openharmony之AV_CodeC音视频编解码模块详解(二)
  • 【明道云】[工作表控件9] 子表控件:一对多数据建模实战指南
  • Linux/UNIX系统编程手册笔记:DAEMON、编写安全的特权程序、能力、登录记账
  • Docker部署PanSou 一款开源网盘搜索项目,集成前后端,一键部署
  • 【服务器】英伟达M40显卡风冷方案心得
  • Process Explorer 学习笔记(第三章3.3.1):DLL和句柄
  • 解锁无限创意:Tldraw+cpolar如何通过内网穿透技术打破空间限制
  • 安全沙箱配置针对海外vps容器隔离的验证方法
  • SQL-DML
  • 数据库原理及应用_数据库基础_第4章关系模型的基本理论_触发器
  • RWA点亮新能源的数字未来
  • css margin外边距重叠/塌陷问题
  • 【Python - 基础 - 规范】(01)Python命名规范...
  • 高级RAG策略学习(四)——上下文窗口增强检索RAG
  • 如何通过AI进行数据资产梳理
  • 跨平台超低延迟RTSP播放器技术设计探究
  • 一文了解大模型推理优化